merge experimental #1
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
**/.venv/
|
||||
**/__pycache__/
|
@ -108,6 +108,7 @@ PG_HOST=medwings-postgres
|
||||
PG_PORT=5432
|
||||
GOTIFY_USER=<secret>
|
||||
GOTIFY_PASSWORD=<secret>
|
||||
GOTIFY_HOST=medwings-gotify
|
||||
WITHINGS_CLIENT_ID=<secret>
|
||||
WITHINGS_CLIENT_SECRET=<secret>
|
||||
```
|
||||
|
@ -7,6 +7,11 @@
|
||||
{% block content %}
|
||||
<div class="flex flex-col justify-center items-center gap-2 py-4 mx-4 max-w-4xl">
|
||||
<h2>Register</h2>
|
||||
<p>{{ auth_code }}</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ user_form }}
|
||||
{{ profile_form }}
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
@ -1,13 +1,19 @@
|
||||
from urllib.parse import urlencode
|
||||
from uuid import uuid4
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.shortcuts import redirect, render
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpResponseBadRequest
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.utils.dateparse import parse_datetime
|
||||
|
||||
import withings.api
|
||||
import withings.models
|
||||
import gotify.api
|
||||
import gotify.models
|
||||
from medwings.forms import ProfileForm
|
||||
|
||||
|
||||
def register_init(request):
|
||||
@ -36,15 +42,15 @@ def register_init(request):
|
||||
|
||||
|
||||
def register_continue(request):
|
||||
# Parse GET request parameters
|
||||
authorization_code = request.GET.get('code')
|
||||
authorization_state = request.GET.get('state')
|
||||
if not authorization_code:
|
||||
return HttpResponseBadRequest()
|
||||
if not authorization_state:
|
||||
return HttpResponseBadRequest()
|
||||
if not request.session.get('spoof_protection_token', None) == authorization_state:
|
||||
return HttpResponseBadRequest()
|
||||
# TODO enable this when not mocking
|
||||
# if not request.session.get('spoof_protection_token', None) == authorization_state:
|
||||
# return HttpResponseBadRequest()
|
||||
|
||||
# Fetch access and refresh tokens and save them to session storage
|
||||
redirect_uri = request.build_absolute_uri(reverse('register-continue'))
|
||||
@ -54,13 +60,62 @@ def register_continue(request):
|
||||
return HttpResponseBadRequest()
|
||||
withings.api.save_tokens_to_session(request, response_data)
|
||||
|
||||
# TODO add user registration form
|
||||
if request.method == 'POST':
|
||||
user_form = UserCreationForm(request.POST)
|
||||
profile_form = ProfileForm(request.POST)
|
||||
|
||||
# TODO once user registration form is valid, make gotify API calls
|
||||
if user_form.is_valid() and profile_form.is_valid():
|
||||
user = user_form.save(commit=False)
|
||||
profile = profile_form.save(commit=False)
|
||||
profile.user = user
|
||||
|
||||
# TODO once gotify is set up, create and save database objects
|
||||
user_password = request.POST.get('password1')
|
||||
gotify_user_info = gotify.api.create_user(user.username, user_password)
|
||||
gotify_app_info = gotify.api.create_application(user.username, user_password)
|
||||
gotify_user = gotify.models.GotifyUser(
|
||||
user=user,
|
||||
id=gotify_user_info['id']
|
||||
)
|
||||
gotify_app = gotify.models.GotifyApplication(
|
||||
user=gotify_user,
|
||||
id=gotify_app_info['id'],
|
||||
token=gotify_app_info['token']
|
||||
)
|
||||
|
||||
context = {}
|
||||
withings_api_account = withings.models.ApiAccount(
|
||||
user=user,
|
||||
userid=request.session.get('withings_userid')
|
||||
)
|
||||
withings_access_token = withings.models.AccessToken(
|
||||
account=withings_api_account,
|
||||
value=request.session.get('withings_access_token'),
|
||||
expires=parse_datetime(request.session.get('withings_access_token_expiry'))
|
||||
)
|
||||
withings_refresh_token = withings.models.RefreshToken(
|
||||
account=withings_api_account,
|
||||
value=request.session.get('withings_refresh_token'),
|
||||
expires=parse_datetime(request.session.get('withings_refresh_token_expiry'))
|
||||
)
|
||||
|
||||
for instance in [
|
||||
user, profile,
|
||||
gotify_user, gotify_app,
|
||||
withings_api_account, withings_access_token, withings_refresh_token
|
||||
]:
|
||||
instance.save()
|
||||
|
||||
# TODO sync withings health data
|
||||
# TODO redirect user to some other page and ask them to log in
|
||||
return redirect('dashboard')
|
||||
|
||||
else:
|
||||
user_form = UserCreationForm()
|
||||
profile_form = ProfileForm()
|
||||
|
||||
context = {
|
||||
'user_form': user_form,
|
||||
'profile_form': profile_form,
|
||||
}
|
||||
|
||||
return render(request, 'authentication/register-continue.html', context)
|
||||
|
||||
|
@ -127,9 +127,10 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
WITHINGS_CONFIG = {
|
||||
'CLIENT_ID': getenv('WITHINGS_CLIENT_ID'),
|
||||
'CLIENT_SECRET': getenv('WITHINGS_CLIENT_SECRET'),
|
||||
'CLIENT_SECRET': getenv('WITHINGS_CLIENT_SECRET')
|
||||
}
|
||||
GOTIFY_CONFIG = {
|
||||
'USERNAME': getenv('GOTIFY_USER'),
|
||||
'PASSWORD': getenv('GOTIFY_PASSWORD'),
|
||||
'HOST': getenv('GOTIFY_HOST')
|
||||
}
|
||||
|
58
app/gotify/api.py
Normal file
58
app/gotify/api.py
Normal file
@ -0,0 +1,58 @@
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
from django.conf import settings
|
||||
from .models import GotifyUser
|
||||
|
||||
|
||||
def create_user(username: str, password: str) -> dict:
|
||||
"""Creates a user on the Gotify instance.
|
||||
|
||||
:param username: The name of the user to be created.
|
||||
:param password: The password of the user to be created.
|
||||
"""
|
||||
|
||||
data = {
|
||||
'admin': False,
|
||||
'name': username,
|
||||
'pass': password
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
url=f"http://{settings.GOTIFY_CONFIG['HOST']}/user",
|
||||
auth=HTTPBasicAuth(
|
||||
settings.GOTIFY_CONFIG['USERNAME'],
|
||||
settings.GOTIFY_CONFIG['PASSWORD'],
|
||||
),
|
||||
json=data
|
||||
)
|
||||
|
||||
if response is not None:
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
|
||||
|
||||
def create_application(username: str, password: str) -> dict:
|
||||
"""Creates an application on the Gotify instance.
|
||||
|
||||
:param username: The user for whom an application will be created.
|
||||
:param password: The user's password.
|
||||
"""
|
||||
|
||||
data = {
|
||||
'defaultPriority': 6,
|
||||
'description': 'A remote patient health monitoring system.',
|
||||
'name': 'Medwings'
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
url=f"http://{settings.GOTIFY_CONFIG['HOST']}/application",
|
||||
auth=HTTPBasicAuth(username, password),
|
||||
json=data
|
||||
)
|
||||
|
||||
if response is not None:
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
12
app/medwings/forms.py
Normal file
12
app/medwings/forms.py
Normal file
@ -0,0 +1,12 @@
|
||||
from django import forms
|
||||
|
||||
from medwings.models import Profile
|
||||
|
||||
|
||||
class ProfileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Profile
|
||||
fields = ['date_of_birth', 'sex']
|
||||
widgets = {
|
||||
'date_of_birth': forms.DateInput(attrs={'type': 'date'}),
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
from random import randint
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from urllib.parse import urlencode
|
||||
|
||||
def fetch_withings_tokens(authorization_code, redirect_uri):
|
||||
@ -43,6 +44,6 @@ def save_tokens_to_session(request, response_data):
|
||||
request.session['withings_access_token'] = response_data['body']['access_token']
|
||||
request.session['withings_refresh_token'] = response_data['body']['refresh_token']
|
||||
|
||||
now = datetime.now()
|
||||
request.session['withings_access_token_expiry'] = now + timedelta(seconds=response_data['body']['expires_in'])
|
||||
request.session['withings_refresh_token_expiry'] = now + timedelta(days=365)
|
||||
now = timezone.now()
|
||||
request.session['withings_access_token_expiry'] = (now + timedelta(seconds=response_data['body']['expires_in'])).isoformat()
|
||||
request.session['withings_refresh_token_expiry'] = (now + timedelta(days=365)).isoformat()
|
||||
|
@ -52,6 +52,7 @@ services:
|
||||
WITHINGS_CLIENT_SECRET: ${WITHINGS_CLIENT_SECRET}
|
||||
GOTIFY_USER: ${GOTIFY_USER}
|
||||
GOTIFY_PASSWORD: ${GOTIFY_PASSWORD}
|
||||
GOTIFY_HOST: ${GOTIFY_HOST}
|
||||
medwings-postgres:
|
||||
image: postgres:alpine
|
||||
container_name: ${PG_HOST}
|
||||
@ -80,6 +81,9 @@ services:
|
||||
GOTIFY_SERVER_SSL_REDIRECTTOHTTPS: false
|
||||
GOTIFY_DEFAULTUSER_NAME: ${GOTIFY_USER}
|
||||
GOTIFY_DEFAULTUSER_PASS: ${GOTIFY_PASSWORD}
|
||||
GOTIFY_SERVER_CORS_ALLOWORIGINS: "- \"localhost:8000\"\n- \"medwings.lobbes.dev\""
|
||||
GOTIFY_SERVER_CORS_ALLOWMETHODS: "- \"GET\"\n- \"POST\""
|
||||
GOTIFY_SERVER_CORS_ALLOWHEADERS: "- \"Authorization\"\n- \"content-type\""
|
||||
medwings-pgweb:
|
||||
image: sosedoff/pgweb
|
||||
container_name: medwings-pgweb
|
||||
|
Loading…
x
Reference in New Issue
Block a user