2024-01-08 19:11:41 +00:00
|
|
|
import os
|
|
|
|
import base64
|
|
|
|
import qrcode
|
2023-10-10 08:54:13 +00:00
|
|
|
import logging
|
2024-01-08 19:11:41 +00:00
|
|
|
import weasyprint
|
|
|
|
import qrcode.image.svg
|
|
|
|
|
|
|
|
from io import BytesIO
|
|
|
|
from pathlib import Path
|
|
|
|
from pyhanko.sign import fields, signers
|
|
|
|
from pyhanko import stamp
|
|
|
|
from pyhanko.pdf_utils import text
|
|
|
|
from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
|
2023-10-10 08:54:13 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2023-11-02 13:17:07 +00:00
|
|
|
from django.views.generic.edit import (
|
|
|
|
UpdateView,
|
|
|
|
CreateView,
|
|
|
|
DeleteView,
|
|
|
|
FormView
|
|
|
|
)
|
2023-10-11 07:52:05 +00:00
|
|
|
from django.views.generic.base import TemplateView
|
2023-10-27 09:19:10 +00:00
|
|
|
from django.shortcuts import get_object_or_404, redirect
|
2023-10-10 08:54:13 +00:00
|
|
|
from django.urls import reverse_lazy
|
2023-10-30 12:53:19 +00:00
|
|
|
from django.http import HttpResponse
|
2023-10-10 08:54:13 +00:00
|
|
|
from django.contrib import messages
|
2023-11-28 08:39:02 +00:00
|
|
|
from idhub.user.forms import (
|
|
|
|
ProfileForm,
|
|
|
|
RequestCredentialForm,
|
|
|
|
DemandAuthorizationForm
|
|
|
|
)
|
2023-10-10 08:54:13 +00:00
|
|
|
from idhub.mixins import UserView
|
2023-11-09 16:58:06 +00:00
|
|
|
from idhub.models import DID, VerificableCredential, Event
|
2023-10-10 08:54:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
class MyProfile(UserView):
|
|
|
|
title = _("My profile")
|
|
|
|
section = "MyProfile"
|
|
|
|
|
|
|
|
|
2023-10-27 09:19:10 +00:00
|
|
|
class MyWallet(UserView):
|
2023-11-13 09:15:52 +00:00
|
|
|
title = _("My wallet")
|
2023-10-10 08:54:13 +00:00
|
|
|
section = "MyWallet"
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class DashboardView(UserView, TemplateView):
|
2023-10-17 15:42:48 +00:00
|
|
|
template_name = "idhub/user/dashboard.html"
|
2023-10-10 08:54:13 +00:00
|
|
|
title = _('Dashboard')
|
2023-11-21 11:38:12 +00:00
|
|
|
subtitle = _('Events')
|
2023-10-10 08:54:13 +00:00
|
|
|
icon = 'bi bi-bell'
|
|
|
|
section = "Home"
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class ProfileView(MyProfile, UpdateView):
|
2023-10-17 15:42:48 +00:00
|
|
|
template_name = "idhub/user/profile.html"
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('My personal data')
|
2023-11-22 14:05:05 +00:00
|
|
|
icon = 'bi bi-person-gear'
|
2023-10-11 07:52:05 +00:00
|
|
|
from_class = ProfileForm
|
|
|
|
fields = ('first_name', 'last_name', 'email')
|
|
|
|
success_url = reverse_lazy('idhub:user_profile')
|
2023-10-10 08:54:13 +00:00
|
|
|
|
2023-10-11 07:52:05 +00:00
|
|
|
def get_object(self):
|
|
|
|
return self.request.user
|
2023-10-10 08:54:13 +00:00
|
|
|
|
2023-11-09 17:09:10 +00:00
|
|
|
def get_form(self):
|
|
|
|
form = super().get_form()
|
|
|
|
form.fields['first_name'].disabled = True
|
|
|
|
form.fields['last_name'].disabled = True
|
|
|
|
form.fields['email'].disabled = True
|
|
|
|
return form
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
2023-10-11 07:52:05 +00:00
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class RolesView(MyProfile, TemplateView):
|
2023-10-17 15:42:48 +00:00
|
|
|
template_name = "idhub/user/roles.html"
|
2023-10-10 08:54:13 +00:00
|
|
|
subtitle = _('My roles')
|
|
|
|
icon = 'fa-brands fa-critical-role'
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class GDPRView(MyProfile, TemplateView):
|
2023-10-17 15:42:48 +00:00
|
|
|
template_name = "idhub/user/gdpr.html"
|
2023-10-10 08:54:13 +00:00
|
|
|
subtitle = _('GDPR info')
|
|
|
|
icon = 'bi bi-file-earmark-medical'
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class CredentialsView(MyWallet, TemplateView):
|
2023-10-17 15:42:48 +00:00
|
|
|
template_name = "idhub/user/credentials.html"
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('Credential management')
|
2023-10-10 08:54:13 +00:00
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
|
2023-10-30 12:53:19 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
2023-12-12 17:00:04 +00:00
|
|
|
creds = VerificableCredential.objects.filter(
|
|
|
|
user=self.request.user
|
|
|
|
)
|
2023-10-30 12:53:19 +00:00
|
|
|
context.update({
|
2023-12-12 17:00:04 +00:00
|
|
|
'credentials': creds,
|
2023-10-30 12:53:19 +00:00
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class CredentialView(MyWallet, TemplateView):
|
2023-10-30 12:53:19 +00:00
|
|
|
template_name = "idhub/user/credential.html"
|
|
|
|
subtitle = _('Credential')
|
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
self.pk = kwargs['pk']
|
|
|
|
self.object = get_object_or_404(
|
|
|
|
VerificableCredential,
|
|
|
|
pk=self.pk,
|
|
|
|
user=self.request.user
|
|
|
|
)
|
|
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context.update({
|
|
|
|
'object': self.object,
|
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class CredentialJsonView(MyWallet, TemplateView):
|
2024-01-08 19:11:41 +00:00
|
|
|
template_name = "certificates/4_Model_Certificat.html"
|
|
|
|
subtitle = _('Credential management')
|
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
file_name = "certificate.pdf"
|
|
|
|
_pss = '123456'
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
# pk = kwargs['pk']
|
|
|
|
# self.object = get_object_or_404(
|
|
|
|
# VerificableCredential,
|
|
|
|
# pk=pk,
|
|
|
|
# user=self.request.user
|
|
|
|
# )
|
|
|
|
# return self.render_to_response(context=self.get_context_data())
|
|
|
|
|
|
|
|
data = self.build_certificate()
|
|
|
|
doc = self.insert_signature(data)
|
|
|
|
import pdb; pdb.set_trace()
|
|
|
|
response = HttpResponse(doc, content_type="application/pdf")
|
|
|
|
response['Content-Disposition'] = 'attachment; filename={}'.format(self.file_name)
|
|
|
|
return response
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
this_folder = str(Path.cwd())
|
|
|
|
path_img_sig = "idhub/static/images/4_Model_Certificat_html_58d7f7eeb828cf29.jpg"
|
|
|
|
img_signature = next(Path.cwd().glob(path_img_sig))
|
|
|
|
with open(img_signature, 'rb') as _f:
|
|
|
|
img_sig = base64.b64encode(_f.read()).decode('utf-8')
|
|
|
|
|
|
|
|
path_img_head = "idhub/static/images/4_Model_Certificat_html_7a0214c6fc8f2309.jpg"
|
|
|
|
img_header= next(Path.cwd().glob(path_img_head))
|
|
|
|
with open(img_header, 'rb') as _f:
|
|
|
|
img_head = base64.b64encode(_f.read()).decode('utf-8')
|
|
|
|
|
|
|
|
qr = self.generate_qr_code("http://localhost")
|
|
|
|
context.update({
|
|
|
|
# 'object': self.object,
|
|
|
|
"image_signature": img_sig,
|
|
|
|
"image_header": img_head,
|
|
|
|
"qr": qr
|
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
|
|
def build_certificate(self):
|
|
|
|
doc = self.render_to_response(context=self.get_context_data())
|
|
|
|
doc.render()
|
|
|
|
pdf = weasyprint.HTML(string=doc.content)
|
|
|
|
return pdf.write_pdf()
|
|
|
|
|
|
|
|
def generate_qr_code(self, data):
|
|
|
|
qr = qrcode.QRCode(
|
|
|
|
version=1,
|
|
|
|
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
|
|
|
box_size=10,
|
|
|
|
border=4,
|
|
|
|
)
|
|
|
|
qr.add_data(data)
|
|
|
|
qr.make(fit=True)
|
|
|
|
img_buffer = BytesIO()
|
|
|
|
img = qr.make_image(fill_color="black", back_color="white")
|
|
|
|
img.save(img_buffer, format="PNG")
|
|
|
|
|
|
|
|
return base64.b64encode(img_buffer.getvalue()).decode('utf-8')
|
|
|
|
|
|
|
|
def signer_init(self):
|
|
|
|
fname = "examples/signerDNIe004.pfx"
|
|
|
|
# pfx_buffer = BytesIO()
|
|
|
|
pfx_file= next(Path.cwd().glob(fname))
|
|
|
|
s = signers.SimpleSigner.load_pkcs12(
|
|
|
|
pfx_file=pfx_file, passphrase=self._pss.encode('utf-8')
|
|
|
|
)
|
|
|
|
return s
|
|
|
|
|
|
|
|
def insert_signature(self, doc):
|
|
|
|
sig = self.signer_init()
|
|
|
|
_buffer = BytesIO()
|
|
|
|
_buffer.write(doc)
|
|
|
|
w = IncrementalPdfFileWriter(_buffer)
|
|
|
|
fields.append_signature_field(
|
|
|
|
w, sig_field_spec=fields.SigFieldSpec(
|
|
|
|
'Signature', box=(150, 100, 450, 150)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
meta = signers.PdfSignatureMetadata(field_name='Signature')
|
|
|
|
pdf_signer = signers.PdfSigner(
|
|
|
|
meta, signer=sig, stamp_style=stamp.QRStampStyle(
|
|
|
|
stamp_text='Signed by: %(signer)s\nTime: %(ts)s\nURL: %(url)s',
|
|
|
|
text_box_style=text.TextBoxStyle()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
_bf_out = BytesIO()
|
|
|
|
url = "https://localhost:8000/"
|
|
|
|
pdf_signer.sign_pdf(w, output=_bf_out, appearance_text_params={'url': url})
|
|
|
|
return _bf_out.read()
|
|
|
|
|
|
|
|
|
|
|
|
class CredentialJsonView2(MyWallet, TemplateView):
|
2023-10-30 12:53:19 +00:00
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
pk = kwargs['pk']
|
|
|
|
self.object = get_object_or_404(
|
|
|
|
VerificableCredential,
|
|
|
|
pk=pk,
|
|
|
|
user=self.request.user
|
|
|
|
)
|
|
|
|
response = HttpResponse(self.object.data, content_type="application/json")
|
|
|
|
response['Content-Disposition'] = 'attachment; filename={}'.format("credential.json")
|
|
|
|
return response
|
|
|
|
|
2023-10-10 08:54:13 +00:00
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class CredentialsRequestView(MyWallet, FormView):
|
2023-10-30 17:29:21 +00:00
|
|
|
template_name = "idhub/user/credentials_request.html"
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('Credential request')
|
2023-10-10 08:54:13 +00:00
|
|
|
icon = 'bi bi-patch-check-fill'
|
2023-11-02 13:17:07 +00:00
|
|
|
form_class = RequestCredentialForm
|
|
|
|
success_url = reverse_lazy('idhub:user_credentials')
|
2023-10-10 08:54:13 +00:00
|
|
|
|
2023-11-02 13:17:07 +00:00
|
|
|
def get_form_kwargs(self):
|
|
|
|
kwargs = super().get_form_kwargs()
|
|
|
|
kwargs['user'] = self.request.user
|
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
cred = form.save()
|
|
|
|
if cred:
|
2023-11-13 09:15:52 +00:00
|
|
|
messages.success(self.request, _("The credential was issued successfully!"))
|
2023-11-09 16:58:06 +00:00
|
|
|
Event.set_EV_CREDENTIAL_ISSUED_FOR_USER(cred)
|
|
|
|
Event.set_EV_CREDENTIAL_ISSUED(cred)
|
2023-12-13 16:52:18 +00:00
|
|
|
url = self.request.session.pop('next_url', None)
|
|
|
|
if url:
|
|
|
|
return redirect(url)
|
2023-11-02 13:17:07 +00:00
|
|
|
else:
|
2023-11-13 09:15:52 +00:00
|
|
|
messages.error(self.request, _("The credential does not exist!"))
|
2023-11-02 13:17:07 +00:00
|
|
|
return super().form_valid(form)
|
2023-10-30 17:29:21 +00:00
|
|
|
|
|
|
|
|
2023-11-28 08:39:02 +00:00
|
|
|
class DemandAuthorizationView(MyWallet, FormView):
|
|
|
|
template_name = "idhub/user/credentials_presentation.html"
|
|
|
|
subtitle = _('Credential presentation')
|
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
form_class = DemandAuthorizationForm
|
|
|
|
success_url = reverse_lazy('idhub:user_demand_authorization')
|
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
|
|
|
kwargs = super().get_form_kwargs()
|
|
|
|
kwargs['user'] = self.request.user
|
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
2023-11-29 12:22:13 +00:00
|
|
|
try:
|
|
|
|
authorization = form.save()
|
|
|
|
except Exception:
|
|
|
|
txt = _("Problems connecting with {url}").format(
|
|
|
|
url=form.org.response_uri
|
|
|
|
)
|
|
|
|
messages.error(self.request, txt)
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
2023-11-28 08:39:02 +00:00
|
|
|
if authorization:
|
2023-11-29 10:53:30 +00:00
|
|
|
return redirect(authorization)
|
2023-11-28 08:39:02 +00:00
|
|
|
else:
|
|
|
|
messages.error(self.request, _("Error sending credential!"))
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class DidsView(MyWallet, TemplateView):
|
2023-10-27 09:19:10 +00:00
|
|
|
template_name = "idhub/user/dids.html"
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('Identities (DIDs)')
|
2023-10-27 09:19:10 +00:00
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context.update({
|
|
|
|
'dids': self.request.user.dids,
|
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
2023-11-02 16:13:49 +00:00
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class DidRegisterView(MyWallet, CreateView):
|
2023-10-27 09:19:10 +00:00
|
|
|
template_name = "idhub/user/did_register.html"
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('Add a new Identity (DID)')
|
2023-10-27 09:19:10 +00:00
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
wallet = True
|
|
|
|
model = DID
|
2023-11-03 15:27:40 +00:00
|
|
|
fields = ('label',)
|
2023-10-27 09:19:10 +00:00
|
|
|
success_url = reverse_lazy('idhub:user_dids')
|
|
|
|
object = None
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
form.instance.user = self.request.user
|
2023-11-14 08:48:36 +00:00
|
|
|
form.instance.set_did()
|
2023-10-27 09:19:10 +00:00
|
|
|
form.save()
|
|
|
|
messages.success(self.request, _('DID created successfully'))
|
2023-11-09 16:58:06 +00:00
|
|
|
|
|
|
|
Event.set_EV_DID_CREATED(form.instance)
|
|
|
|
Event.set_EV_DID_CREATED_BY_USER(form.instance)
|
2023-10-27 09:19:10 +00:00
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class DidEditView(MyWallet, UpdateView):
|
2023-10-27 09:19:10 +00:00
|
|
|
template_name = "idhub/user/did_register.html"
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('Identities (DIDs)')
|
2023-10-27 09:19:10 +00:00
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
wallet = True
|
|
|
|
model = DID
|
2023-11-03 15:27:40 +00:00
|
|
|
fields = ('label',)
|
2023-10-27 09:19:10 +00:00
|
|
|
success_url = reverse_lazy('idhub:user_dids')
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
self.pk = kwargs['pk']
|
|
|
|
self.object = get_object_or_404(self.model, pk=self.pk)
|
|
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
user = form.save()
|
|
|
|
messages.success(self.request, _('DID updated successfully'))
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
|
2023-11-03 15:42:45 +00:00
|
|
|
class DidDeleteView(MyWallet, DeleteView):
|
2023-11-13 09:15:52 +00:00
|
|
|
subtitle = _('Identities (DIDs)')
|
2023-10-27 09:19:10 +00:00
|
|
|
icon = 'bi bi-patch-check-fill'
|
|
|
|
wallet = True
|
|
|
|
model = DID
|
|
|
|
success_url = reverse_lazy('idhub:user_dids')
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
self.pk = kwargs['pk']
|
|
|
|
self.object = get_object_or_404(self.model, pk=self.pk)
|
2023-11-09 16:58:06 +00:00
|
|
|
Event.set_EV_DID_DELETED(self.object)
|
2023-10-27 09:19:10 +00:00
|
|
|
self.object.delete()
|
|
|
|
messages.success(self.request, _('DID delete successfully'))
|
|
|
|
|
|
|
|
return redirect(self.success_url)
|
2023-11-09 16:58:06 +00:00
|
|
|
|