Skip to content

Commit

Permalink
Refactor to different yivi app
Browse files Browse the repository at this point in the history
  • Loading branch information
KiOui committed Sep 18, 2023
1 parent f432bfc commit 2d19fc6
Show file tree
Hide file tree
Showing 27 changed files with 150 additions and 101 deletions.
2 changes: 2 additions & 0 deletions website/age/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def ready(self):
AgeOverviewView,
)

from age import signals # noqa

def filter_user_page(user_page_list: list):
"""Add age overview tab on accounts page."""
user_page_list.append(
Expand Down
8 changes: 6 additions & 2 deletions website/age/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.4 on 2023-09-18 05:28
# Generated by Django 4.2.4 on 2023-09-18 20:45

from django.conf import settings
from django.db import migrations, models
Expand All @@ -21,7 +21,11 @@ class Migration(migrations.Migration):
("created_at", models.DateTimeField(auto_now_add=True)),
(
"user",
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="is_18_years_old",
to=settings.AUTH_USER_MODEL,
),
),
],
),
Expand Down
25 changes: 0 additions & 25 deletions website/age/migrations/0002_alter_is18yearsold_user.py

This file was deleted.

21 changes: 0 additions & 21 deletions website/age/migrations/0003_sessionmapping.py

This file was deleted.

18 changes: 0 additions & 18 deletions website/age/migrations/0004_alter_sessionmapping_session_token.py

This file was deleted.

7 changes: 0 additions & 7 deletions website/age/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,3 @@ class Is18YearsOld(models.Model):

user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="is_18_years_old")
created_at = models.DateTimeField(auto_now_add=True)


class SessionMapping(models.Model):
"""Session mapping class for Yivi."""

id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
session_token = models.CharField(max_length=20, unique=True)
23 changes: 23 additions & 0 deletions website/age/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from django.conf import settings
from django.dispatch import receiver

from age import models
from yivi.models import Session
from yivi.signals import attributes_verified


@receiver(attributes_verified)
def update_is_over_18(sender, **kwargs):
session: Session = kwargs.get("session")
if session.user is None or models.Is18YearsOld.objects.filter(user=session.user).exists():
return

attributes = kwargs.get("attributes")
for attribute_conjuction_clause in attributes:
for attribute_disjunction_clause in attribute_conjuction_clause:
attribute_id = attribute_disjunction_clause["id"]
if (
attribute_id == settings.AGE_VERIFICATION_DISCLOSE_ATTRIBUTE
and attribute_disjunction_clause["status"] == "PRESENT"
):
models.Is18YearsOld.objects.create(user=session.user)
20 changes: 15 additions & 5 deletions website/age/templates/age/age_overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ <h3 class="modal-title">Verify your age</h3>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="modal-body d-flex justify-content-center">
<section class="yivi-web-form" id="yivi-web-form"></section>
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>
<script src="{% static "age/js/yivi.js" %}" type="text/javascript"></script>
<script src="{% static "yivi/js/yivi.js" %}" type="text/javascript"></script>
<script>
const yiviWeb = yivi.newWeb({
debugging: true,
Expand All @@ -40,10 +40,13 @@ <h3 class="modal-title">Verify your age</h3>
method: 'POST',
headers: {
"X-CSRFToken": get_csrf_token(),
"Accept": 'application/json',
"Content-Type": 'application/json',
},
body: '{{ disclose }}',
},
result: {
url: (o, {sessionPtr, sessionToken}) => `/api/v1/age/session/${sessionToken}/result/`,
url: (o, {sessionPtr, sessionToken}) => `/api/v1/yivi/session/${sessionToken}/result/`,
method: 'GET',
headers: {
"X-CSRFToken": get_csrf_token(),
Expand All @@ -53,7 +56,14 @@ <h3 class="modal-title">Verify your age</h3>
});

yiviWeb.start()
.then(result => console.log("Successful disclosure! 🎉", result))
.catch(error => console.error("Couldn't do what you asked 😢", error));
.then(result => {
tata.success("", "Your age has been verified. You will be redirected in a couple of seconds.");
setTimeout(() => {
window.location.reload();
}, 3000)
})
.catch(error => {
tata.error("", `Failed to verify your age, the following error occurred: ${error}`);
});
</script>
{% endif %}
6 changes: 0 additions & 6 deletions website/age/urls.py

This file was deleted.

18 changes: 16 additions & 2 deletions website/age/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import json

from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from django.views.generic import TemplateView

from age import models
Expand All @@ -15,10 +19,20 @@ def get(self, request, **kwargs):
"""Get Age Overview View."""

is_18_years_old = models.Is18YearsOld.objects.filter(user=request.user).exists()
rendered_tab = render_to_string("age/age_overview.html", context={"is_over_18": is_18_years_old})
rendered_tab = render_to_string(
"age/age_overview.html",
context={
"is_over_18": is_18_years_old,
"disclose": mark_safe(json.dumps({"disclose": [[[settings.AGE_VERIFICATION_DISCLOSE_ATTRIBUTE]]]})),
},
)

return render(
request,
self.template_name,
{"active": kwargs.get("active"), "tabs": kwargs.get("tabs"), "rendered_tab": rendered_tab},
{
"active": kwargs.get("active"),
"tabs": kwargs.get("tabs"),
"rendered_tab": rendered_tab,
},
)
2 changes: 1 addition & 1 deletion website/tosti/api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
path("associations/", include("associations.api.v1.urls")),
path("transactions/", include("transactions.api.v1.urls")),
path("users/", include("users.api.v1.urls")),
path("age/", include("age.api.v1.urls")),
path("yivi/", include("yivi.api.v1.urls")),
path("fridges/", include("fridges.api.v1.urls")),
path(
"schema",
Expand Down
3 changes: 3 additions & 0 deletions website/tosti/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"silvasoft",
"oauth2_provider",
"corsheaders",
"yivi",
"age",
"fridges",
]
Expand Down Expand Up @@ -260,3 +261,5 @@
]

DJANGO_CRON_DELETE_LOGS_OLDER_THAN = 14

AGE_VERIFICATION_DISCLOSE_ATTRIBUTE = "irma-demo.MijnOverheid.ageLower.over18"
4 changes: 0 additions & 4 deletions website/tosti/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@
"thaliedje/",
include(("thaliedje.urls", "thaliedje"), namespace="thaliedje"),
),
path(
"age/",
include(("age.urls", "age"), namespace="age"),
),
path(
"fridges/",
include(("fridges.urls", "fridges"), namespace="fridges"),
Expand Down
File renamed without changes.
File renamed without changes.
Empty file added website/yivi/api/v1/__init__.py
Empty file.
File renamed without changes.
2 changes: 1 addition & 1 deletion website/age/api/v1/urls.py → website/yivi/api/v1/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.urls import path
from age.api.v1.views import YiviStartAPIView, YiviResultAPIView
from yivi.api.v1.views import YiviStartAPIView, YiviResultAPIView


urlpatterns = [
Expand Down
28 changes: 20 additions & 8 deletions website/age/api/v1/views.py → website/yivi/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from rest_framework.response import Response
from rest_framework.views import APIView

from age.models import SessionMapping
from age.services import get_yivi_client
from age.yivi import YiviException
from yivi import signals
from yivi.models import Session
from yivi.services import get_yivi_client
from yivi.yivi import YiviException
from tosti.api.permissions import IsAuthenticatedOrTokenHasScopeForMethod


Expand All @@ -23,19 +24,23 @@ class YiviStartAPIView(APIView):
def post(self, request, **kwargs):
"""Start a Yivi request."""
yivi_client = get_yivi_client()
disclose = request.data.get("disclose", None)
if disclose is None:
return Response(status=400, data="Parameter 'disclose' must be specified.")

try:
response = yivi_client.start_session(
{
"@context": "https://irma.app/ld/request/disclosure/v2",
"disclose": [[["irma-demo.MijnOverheid.ageLower.over18"]]],
"disclose": disclose,
}
)
except YiviException as e:
return Response(status=e.http_status, data=e.msg)

token = response["token"]
session_mapping = SessionMapping.objects.create(session_token=token)
response["token"] = session_mapping.id
session = Session.objects.create(session_token=token, user=request.user)
response["token"] = session.id
return Response(data=response)


Expand All @@ -55,8 +60,15 @@ def get(self, request, **kwargs):
"""Get the result of a Yivi session."""
yivi_client = get_yivi_client()
session_uuid = kwargs.get("pk")
session = get_object_or_404(SessionMapping, pk=session_uuid)
session = get_object_or_404(Session, pk=session_uuid, user=request.user)
try:
return Response(data=yivi_client.session_result(session.session_token))
response = yivi_client.session_result(session.session_token)
except YiviException as e:
return Response(status=e.http_status, data=e.msg)

response["token"] = session.id

if response.get("proofStatus") == "VALID":
signals.attributes_verified.send_robust(self.__class__, session=session, attributes=response["disclosed"])

return Response(data=response)
8 changes: 8 additions & 0 deletions website/yivi/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.apps import AppConfig


class YiviConfig(AppConfig):
"""Yivi App Config."""

default_auto_field = "django.db.models.BigAutoField"
name = "yivi"
35 changes: 35 additions & 0 deletions website/yivi/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 4.2.4 on 2023-09-18 20:29

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="Session",
fields=[
("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
("session_token", models.CharField(max_length=20, unique=True)),
("created_at", models.DateTimeField(auto_now_add=True)),
(
"user",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
),
),
],
),
]
Empty file.
16 changes: 16 additions & 0 deletions website/yivi/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import uuid

from django.contrib.auth import get_user_model
from django.db import models


User = get_user_model()


class Session(models.Model):
"""Session mapping class for Yivi."""

id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
session_token = models.CharField(max_length=20, unique=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
2 changes: 1 addition & 1 deletion website/age/services.py → website/yivi/services.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.conf import settings

from age.yivi import Yivi
from yivi.yivi import Yivi


def get_yivi_client() -> Yivi:
Expand Down
3 changes: 3 additions & 0 deletions website/yivi/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import django.dispatch

attributes_verified = django.dispatch.Signal()
File renamed without changes.
File renamed without changes.

0 comments on commit 2d19fc6

Please sign in to comment.