Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Credentials #7

Merged
merged 10 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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