Skip to content

Commit

Permalink
Credentials (#7)
Browse files Browse the repository at this point in the history
* initial commit on branch

* removing mongoDB from docker-compose for now

* serve participants credentials

* tidy up by removing some comments

* tweaks in response to code review

* tweaks

* remove duplicate text in README

* adjust local run command to include mongo

* update README to reflect CLI command

* change find query to find_one, and exclude _id from result

Co-authored-by: David <[email protected]>
  • Loading branch information
ColinBD and davidverweij authored Jan 21, 2022
1 parent 4cde61e commit f1c6079
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 5 deletions.
11 changes: 10 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,13 @@ AIRFLOW_SERVER="airflow-webserver"
# UCAM API
UCAM_URI=""
UCAM_USERNAME=""
UCAM_PASSWORD=""
UCAM_PASSWORD=""

# --- USERS ---
# for local development, when changing log in values
# be sure to clean the docker volumes before rebooting
_MONGO_INITDB_ROOT_USERNAME=""
_MONGO_INITDB_ROOT_PASSWORD=""
_MONGO_INITDB_DATABASE="patient_credentials"
_MONGO_INITDB_COLLECTION="credentials"
_MONGO_HOST="mongo_credentials"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ requirements.txt
.nox

# Possible remnants of local dev
/api/docs
/api/docs
/dist/*
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ docker-compose -f example.docker-compose.yml up

Open your browser and try out a few endpoints, e.g.
- http://localhost/patients
- http://localhost/patients/credentials/{participant_id}
- http://localhost/docs/axivity
- http://localhost/status

Expand Down Expand Up @@ -61,11 +62,11 @@ A CLI command sets up the API locally to enable hot-reloading as code changes, s
```shell
pyenv install 3.8.0 && pyenv global 3.8.0
```
Add the required environmental variables in the `.env` file and quickstart the API which will watch for local changes:
Add the required environmental variables in the `.env` file and quickstart the API which will watch for local changes. This will also spin up a docker container for the `mongodb` and patient credentials. Add the `--clean` command to auto-clean the docker volume when you shut down the API:

```shell
poetry install
poetry run local
poetry run local # --clean
```

#### GET /docs
Expand Down
7 changes: 7 additions & 0 deletions api/patients.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from fastapi import APIRouter, Query

from api.utils.db import PatientsCredentials, get_patients_credentials
from api.utils.ucam import PatientWithDevices, get_one_patient, get_patients

router = APIRouter()
Expand Down Expand Up @@ -35,6 +36,12 @@ def patients(
return patients


@router.get("/credentials/{id}", response_model=PatientsCredentials)
def one_patients_credentials(id: str) -> Optional[PatientsCredentials]:
"""Return list of all technology platform credentials for this patient"""
return get_patients_credentials(id)


@router.get("/{id}", response_model=PatientWithDevices)
def one_patient(id: str) -> Optional[PatientWithDevices]:
"""Get more details about a patient"""
Expand Down
41 changes: 41 additions & 0 deletions api/utils/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os
from typing import Optional

from dotenv import load_dotenv
from pydantic.dataclasses import dataclass
from pymongo import MongoClient

load_dotenv()

# setup mongodb connection
myclient = MongoClient(
host=[f"{os.getenv('_MONGO_HOST')}:27017"],
username=os.getenv("_MONGO_INITDB_ROOT_USERNAME"),
password=os.getenv("_MONGO_INITDB_ROOT_PASSWORD"),
)
mydb = myclient[os.getenv("_MONGO_INITDB_DATABASE")]
mycol = mydb[os.getenv("_MONGO_INITDB_COLLECTION")]


@dataclass
class PatientsCredentials:
"""Patient credentials"""

patient_id: str
dreem_email: str
dreem_password: str
wildkeys_email: str
wildkeys_password: str
tfa_email: str
tfa_password: str


def get_patients_credentials(the_id: str) -> Optional[PatientsCredentials]:
"""Get credentials for one patient based on the ID"""
myquery = {"patient_id": the_id}
payload = mycol.find_one(myquery, {"_id": 0}) # exclude _id from result
if payload:
patient_credentials = PatientsCredentials(**payload)
return patient_credentials
else:
return None
10 changes: 9 additions & 1 deletion cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ def version() -> None:


@cli.command()
def run_local() -> None:
@click.option("--clean", is_flag=True, help="removes volume afterwards")
def run_local(clean: bool) -> None:
"""Run locally with adjusted settings and loaded .envs"""
import os

Expand All @@ -144,9 +145,16 @@ def run_local() -> None:

load_dotenv()
os.environ["AIRFLOW_SERVER"] = "localhost"
os.environ["_MONGO_HOST"] = "localhost"

run_command("docker-compose -f example.docker-compose.yml up -d mongo")

uvicorn.run("api.main:api", host="0.0.0.0", port=80, reload=True) # noqa: S104

run_command(
f"docker-compose -f example.docker-compose.yml down {'-v' if clean else ''}"
) # cleanup


if __name__ == "__main__":
cli()
16 changes: 16 additions & 0 deletions example.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,19 @@ services:
- .env
volumes:
- ./ssh:/root/.ssh

mongo:
container_name: mongo_credentials
image: mongo:5.0
environment:
MONGO_INITDB_ROOT_USERNAME: ${_MONGO_INITDB_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${_MONGO_INITDB_ROOT_PASSWORD}
MONGO_INITDB_DATABASE: ${_MONGO_INITDB_DATABASE}
ports:
- '27017:27017'
volumes:
- mongo-db-volume:/data/db
- ./init/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro

volumes:
mongo-db-volume: null
14 changes: 14 additions & 0 deletions init/mongo-init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
set -e

mongo <<EOF
use $MONGO_INITDB_DATABASE
db.createUser({
user: '$MONGO_INITDB_ROOT_USERNAME',
pwd: '$MONGO_INITDB_ROOT_PASSWORD',
roles: [{
role: 'readWrite',
db: '$MONGO_INITDB_DATABASE'
}]
})
EOF
102 changes: 102 additions & 0 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fastapi = "^0.70.1"
uvicorn = "^0.16.0"
requests = "^2.27.0"
pydantic = "^1.9.0"
pymongo = "^4.0.1"

[tool.poetry.dev-dependencies]
pre-commit = "^2.16.0"
Expand Down

0 comments on commit f1c6079

Please sign in to comment.