QTime (QueueTime) is a mobile application designed to track wait times and occupancy levels for services across McMaster's campus to help students plan their day.
Python flask backend for the QTime system.
- Clone the project:
git clone https://github.com/QueueTime/qtime-backend.git
- Create a virtual environment:
python3 -m venv env
- Activate the virtual environment:
activate env/bin/activate
- Install the required packages:
python3 -m pip install -r requirements.txt
Note: At any if you wish to deactivate the virtual environment run deactivate
.
This project uses Firebase APIs to communicate with the Firestore database and manage authentication. In order to connect to Firebase we need to generate a private service key.
To generate a private key file for your service account:
- In the Firebase console, open Settings > Service Accounts.
- Select "Python" as the target admin SDK and click Generate new private key.
- Copy the contents of the downloaded JSON file and replace the contents of the serviceAccount.sample.json file. Rename the file to
serviceAccountKey.json
.
Note: This service account key is private and should not be shared.
This project manages many external dependencies. If adding or removing dependencies update the requirements.txt file by running
python3 -m pip freeze > requirements.txt
This project leverages Connexion as a framework to manage http requests based on OpenAPI specifications.
This project leverages the opinionated Black formatter for code formatting and mypy for static typechecking.
This project leverages Unittest as a unit testing framework to run tests.
Run the following commands to test a module
python -m unittest tests/test_target.py
The full instructions for testing with the command line are found in the Unittest documentation.
In order to test functionality that connects to firebase we use firebase emulators to emulate a firebase instance.
- Follow the install steps to setup firebase emulators.
- Run
firebase --version
to ensure you installed the firebase cli.
- Run
- Setup the firestore emulator with the following command
firebase setup:emulators:firestore
- Start the emulators with the command
firebase emulators:start --only firestore,auth --project qtime-bd47e --import=./sample_firebase_data
-
You should now be able to visit the firestore emulator UI and firebase auth emulator UI pages.
-
Export the following environment variables before running the flask app
export FIRESTORE_EMULATOR_HOST="localhost:8080"
export FIREBASE_AUTH_EMULATOR_HOST="localhost:9099"
- Fetch a user authentication token by making a POST http call:
POST http://127.0.0.1:9099/identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=key
{
"email": "<USER_EMAIL>",
"password": "<PASSWORD>"
}
- Export data from the firebase emulator with the command. The emulator must be running.
firebase emulators:export ./sample_firebase_data --project qtime-bd47e
The firebase utility script is used to simplify management tasks for Firebase and the Firestore database. It is located in scripts/manage_firebase.py
. Currently, the following command line arguments are supported:
--add-pois
: Update thePOI
collection on Firestore with a list of POI data given in a file in JSON format. Example:
python manage_firebase.py --add-pois ./pois.json
--add-property
,--remove-property
: These options will add a new field to every document in a collection or remove a field from all documents in a collection respectively. To add a new property, the following syntax is used:
--add-property collection_path=<COLLECTION_PATH> name=<FIELD_NAME> type=[string | number | boolean | map | array | timestamp] value=<VALUE>
Example commands:
python manage_firebase.py --remove-property collection_path=users name=hasCompletedOnboarding
This will delete the hasCompletedOnboarding
field from all documents in the users collection.
python manage_firebase.py --add-property collection_path=users name=has_completed_onboarding type=boolean value=true
This will add a new boolean field to all documents in the users collection called has_completed_onboarding
with a default value of true.
Command line help for the utility is also available by providing the -h
or --help
argument.
The QTime backend is deployed to AWS Lightsail automatically on push to main using the Deploy
workflow. The steps to manually deploy are below:
- Install Docker, AWS CLI and the Lightsail Plugin if you haven't already.
- Create a docker image of the backend with
docker build -t qtime-container .
Note: (You can run this image as a container with docker run -p 5000:5000 qtime-container
)
- Push the image to AWS Lightsail
aws lightsail push-container-image \
--service-name qtime \
--label qtime-latest \
--image qtime-container:latest
This will return information about the image you just pushed, take note of container number assigned. It should look like qtime.qtime-latest.X
.
- Deploy your container to AWS Lightsail, replacing the image name in the command below.
aws lightsail create-container-service-deployment \
--service-name qtime \
--containers "{
"flask": {
"image": "qtime.qtime-latest.X",
"ports": {
"5000": "HTTP"
}
}
}" \
--public-endpoint "{
"containerName": "flask",
"containerPort": 5000,
"healthCheck": {
"path": "/api/health",
"successCodes": "200"
}
}"
- It will take a few minutes for the new deployment to finish. Once finished you should be able to access https://queuetime.tech/api/health to verify the service is up.