resolve merge
This commit is contained in:
commit
79cd9bd6e7
|
@ -639,7 +639,7 @@ class DidRegisterView(Credentials, CreateView):
|
||||||
icon = 'bi bi-patch-check-fill'
|
icon = 'bi bi-patch-check-fill'
|
||||||
wallet = True
|
wallet = True
|
||||||
model = DID
|
model = DID
|
||||||
fields = ('label',)
|
fields = ('label', 'type')
|
||||||
success_url = reverse_lazy('idhub:admin_dids')
|
success_url = reverse_lazy('idhub:admin_dids')
|
||||||
object = None
|
object = None
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
def create_defaults_dids(self):
|
def create_defaults_dids(self):
|
||||||
for u in User.objects.all():
|
for u in User.objects.all():
|
||||||
did = DID(label="Default", user=u)
|
did = DID(label="Default", user=u, type=DID.Types.KEY)
|
||||||
did.set_did()
|
did.set_did()
|
||||||
did.save()
|
did.save()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2023-12-11 08:35
|
# Generated by Django 4.2.5 on 2024-01-16 13:04
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -25,10 +25,17 @@ class Migration(migrations.Migration):
|
||||||
verbose_name='ID',
|
verbose_name='ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
'type',
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[(1, 'Key'), (2, 'Web')], verbose_name='Type'
|
||||||
|
),
|
||||||
|
),
|
||||||
('created_at', models.DateTimeField(auto_now=True)),
|
('created_at', models.DateTimeField(auto_now=True)),
|
||||||
('label', models.CharField(max_length=50)),
|
('label', models.CharField(max_length=50, verbose_name='Label')),
|
||||||
('did', models.CharField(max_length=250)),
|
('did', models.CharField(max_length=250)),
|
||||||
('key_material', models.CharField(max_length=250)),
|
('key_material', models.CharField(max_length=250)),
|
||||||
|
('didweb_document', models.TextField()),
|
||||||
(
|
(
|
||||||
'user',
|
'user',
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
@ -256,8 +263,11 @@ class Migration(migrations.Migration):
|
||||||
verbose_name='ID',
|
verbose_name='ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
('created', models.DateTimeField(auto_now=True)),
|
('created', models.DateTimeField(auto_now=True, verbose_name='Date')),
|
||||||
('message', models.CharField(max_length=350)),
|
(
|
||||||
|
'message',
|
||||||
|
models.CharField(max_length=350, verbose_name='Description'),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
'type',
|
'type',
|
||||||
models.PositiveSmallIntegerField(
|
models.PositiveSmallIntegerField(
|
||||||
|
@ -295,7 +305,8 @@ class Migration(migrations.Migration):
|
||||||
(28, 'Organisational DID deleted by admin'),
|
(28, 'Organisational DID deleted by admin'),
|
||||||
(29, 'User deactivated'),
|
(29, 'User deactivated'),
|
||||||
(30, 'User activated'),
|
(30, 'User activated'),
|
||||||
]
|
],
|
||||||
|
verbose_name='Event',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -327,6 +338,7 @@ class Migration(migrations.Migration):
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
related_name='users',
|
related_name='users',
|
||||||
to='idhub.service',
|
to='idhub.service',
|
||||||
|
verbose_name='Service',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
|
@ -11,7 +11,7 @@ from utils.idhub_ssikit import (
|
||||||
generate_did_controller_key,
|
generate_did_controller_key,
|
||||||
keydid_from_controller_key,
|
keydid_from_controller_key,
|
||||||
sign_credential,
|
sign_credential,
|
||||||
verify_credential
|
webdid_from_controller_key,
|
||||||
)
|
)
|
||||||
from idhub_auth.models import User
|
from idhub_auth.models import User
|
||||||
|
|
||||||
|
@ -406,6 +406,13 @@ class Event(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class DID(models.Model):
|
class DID(models.Model):
|
||||||
|
class Types(models.IntegerChoices):
|
||||||
|
KEY = 1, "Key"
|
||||||
|
WEB = 2, "Web"
|
||||||
|
type = models.PositiveSmallIntegerField(
|
||||||
|
_("Type"),
|
||||||
|
choices=Types.choices,
|
||||||
|
)
|
||||||
created_at = models.DateTimeField(auto_now=True)
|
created_at = models.DateTimeField(auto_now=True)
|
||||||
label = models.CharField(_("Label"), max_length=50)
|
label = models.CharField(_("Label"), max_length=50)
|
||||||
did = models.CharField(max_length=250)
|
did = models.CharField(max_length=250)
|
||||||
|
@ -419,6 +426,7 @@ class DID(models.Model):
|
||||||
related_name='dids',
|
related_name='dids',
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
|
didweb_document = models.TextField()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_organization_did(self):
|
def is_organization_did(self):
|
||||||
|
@ -428,7 +436,12 @@ class DID(models.Model):
|
||||||
|
|
||||||
def set_did(self):
|
def set_did(self):
|
||||||
self.key_material = generate_did_controller_key()
|
self.key_material = generate_did_controller_key()
|
||||||
|
if self.type == self.Types.KEY:
|
||||||
self.did = keydid_from_controller_key(self.key_material)
|
self.did = keydid_from_controller_key(self.key_material)
|
||||||
|
elif self.type == self.Types.WEB:
|
||||||
|
didurl, document = webdid_from_controller_key(self.key_material)
|
||||||
|
self.did = didurl
|
||||||
|
self.didweb_document = document
|
||||||
|
|
||||||
def get_key(self):
|
def get_key(self):
|
||||||
return json.loads(self.key_material)
|
return json.loads(self.key_material)
|
||||||
|
|
|
@ -17,7 +17,7 @@ Including another URLconf
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
from django.urls import path, reverse_lazy
|
from django.urls import path, reverse_lazy
|
||||||
from .views import LoginView
|
from .views import LoginView, serve_did
|
||||||
from .admin import views as views_admin
|
from .admin import views as views_admin
|
||||||
from .user import views as views_user
|
from .user import views as views_user
|
||||||
# from .verification_portal import views as views_verification_portal
|
# from .verification_portal import views as views_verification_portal
|
||||||
|
@ -173,6 +173,8 @@ urlpatterns = [
|
||||||
path('admin/import/new', views_admin.ImportAddView.as_view(),
|
path('admin/import/new', views_admin.ImportAddView.as_view(),
|
||||||
name='admin_import_add'),
|
name='admin_import_add'),
|
||||||
|
|
||||||
|
path('did-registry/<str:did_id>', serve_did)
|
||||||
|
|
||||||
# path('verification_portal/verify/', views_verification_portal.verify,
|
# path('verification_portal/verify/', views_verification_portal.verify,
|
||||||
# name="verification_portal_verify")
|
# name="verification_portal_verify")
|
||||||
]
|
]
|
||||||
|
|
|
@ -202,7 +202,7 @@ class DidRegisterView(MyWallet, CreateView):
|
||||||
icon = 'bi bi-patch-check-fill'
|
icon = 'bi bi-patch-check-fill'
|
||||||
wallet = True
|
wallet = True
|
||||||
model = DID
|
model = DID
|
||||||
fields = ('label',)
|
fields = ('label', 'type')
|
||||||
success_url = reverse_lazy('idhub:user_dids')
|
success_url = reverse_lazy('idhub:user_dids')
|
||||||
object = None
|
object = None
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
from django.contrib.auth import login as auth_login
|
from django.contrib.auth import login as auth_login
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect, HttpResponse
|
||||||
|
|
||||||
|
from idhub.models import DID
|
||||||
|
from trustchain_idhub import settings
|
||||||
|
|
||||||
|
|
||||||
class LoginView(auth_views.LoginView):
|
class LoginView(auth_views.LoginView):
|
||||||
|
@ -26,3 +30,12 @@ class LoginView(auth_views.LoginView):
|
||||||
self.extra_context['success_url'] = admin_dashboard
|
self.extra_context['success_url'] = admin_dashboard
|
||||||
auth_login(self.request, user)
|
auth_login(self.request, user)
|
||||||
return HttpResponseRedirect(self.extra_context['success_url'])
|
return HttpResponseRedirect(self.extra_context['success_url'])
|
||||||
|
|
||||||
|
|
||||||
|
def serve_did(request, did_id):
|
||||||
|
id_did = f'did:web:{settings.DOMAIN}:did-registry:{did_id}'
|
||||||
|
did = get_object_or_404(DID, did=id_did)
|
||||||
|
document = did.didweb_document
|
||||||
|
retval = HttpResponse(document)
|
||||||
|
retval.headers["Content-Type"] = "application/json"
|
||||||
|
return retval
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2023-12-11 08:35
|
# Generated by Django 4.2.5 on 2024-01-16 13:04
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -31,13 +31,23 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
'email',
|
'email',
|
||||||
models.EmailField(
|
models.EmailField(
|
||||||
max_length=255, unique=True, verbose_name='email address'
|
max_length=255, unique=True, verbose_name='Email address'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
('is_active', models.BooleanField(default=True)),
|
('is_active', models.BooleanField(default=True)),
|
||||||
('is_admin', models.BooleanField(default=False)),
|
('is_admin', models.BooleanField(default=False)),
|
||||||
('first_name', models.CharField(blank=True, max_length=255, null=True)),
|
(
|
||||||
('last_name', models.CharField(blank=True, max_length=255, null=True)),
|
'first_name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name='First name'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'last_name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name='Last name'
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2023-12-11 08:35
|
# Generated by Django 4.2.5 on 2024-01-16 13:04
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -30,7 +30,7 @@ class Migration(migrations.Migration):
|
||||||
'code',
|
'code',
|
||||||
models.CharField(default=oidc4vp.models.set_code, max_length=24),
|
models.CharField(default=oidc4vp.models.set_code, max_length=24),
|
||||||
),
|
),
|
||||||
('code_used', models.BooleanField()),
|
('code_used', models.BooleanField(default=False)),
|
||||||
('created', models.DateTimeField(auto_now=True)),
|
('created', models.DateTimeField(auto_now=True)),
|
||||||
('presentation_definition', models.CharField(max_length=250)),
|
('presentation_definition', models.CharField(max_length=250)),
|
||||||
],
|
],
|
||||||
|
@ -91,7 +91,7 @@ class Migration(migrations.Migration):
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
null=True,
|
null=True,
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
related_name='oauth2vptoken',
|
related_name='vp_tokens',
|
||||||
to='oidc4vp.authorization',
|
to='oidc4vp.authorization',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2023-12-11 08:35
|
# Generated by Django 4.2.5 on 2024-01-16 13:04
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
|
@ -6,6 +6,8 @@ import jinja2
|
||||||
from django.template.backends.django import Template
|
from django.template.backends.django import Template
|
||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
|
|
||||||
|
from trustchain_idhub import settings
|
||||||
|
|
||||||
|
|
||||||
def generate_did_controller_key():
|
def generate_did_controller_key():
|
||||||
return didkit.generate_ed25519_key()
|
return didkit.generate_ed25519_key()
|
||||||
|
@ -15,6 +17,30 @@ def keydid_from_controller_key(key):
|
||||||
return didkit.key_to_did("key", key)
|
return didkit.key_to_did("key", key)
|
||||||
|
|
||||||
|
|
||||||
|
async def resolve_keydid(keydid):
|
||||||
|
return await didkit.resolve_did(keydid, "{}")
|
||||||
|
|
||||||
|
|
||||||
|
def webdid_from_controller_key(key):
|
||||||
|
"""
|
||||||
|
Se siguen los pasos para generar un webdid a partir de un keydid.
|
||||||
|
Documentado en la docu de spruceid.
|
||||||
|
"""
|
||||||
|
keydid = keydid_from_controller_key(key) # "did:key:<...>"
|
||||||
|
pubkeyid = keydid.rsplit(":")[-1] # <...>
|
||||||
|
document = json.loads(asyncio.run(resolve_keydid(keydid))) # Documento DID en terminos "key"
|
||||||
|
webdid_url = f"did:web:{settings.DOMAIN}:did-registry:{pubkeyid}" # nueva URL: "did:web:idhub.pangea.org:<...>"
|
||||||
|
webdid_url_owner = webdid_url + "#owner"
|
||||||
|
# Reemplazamos los campos del documento DID necesarios:
|
||||||
|
document["id"] = webdid_url
|
||||||
|
document["verificationMethod"][0]["id"] = webdid_url_owner
|
||||||
|
document["verificationMethod"][0]["controller"] = webdid_url
|
||||||
|
document["authentication"][0] = webdid_url_owner
|
||||||
|
document["assertionMethod"][0] = webdid_url_owner
|
||||||
|
document_fixed_serialized = json.dumps(document)
|
||||||
|
return webdid_url, document_fixed_serialized
|
||||||
|
|
||||||
|
|
||||||
def generate_generic_vc_id():
|
def generate_generic_vc_id():
|
||||||
# TODO agree on a system for Verifiable Credential IDs
|
# TODO agree on a system for Verifiable Credential IDs
|
||||||
return "https://pangea.org/credentials/42"
|
return "https://pangea.org/credentials/42"
|
||||||
|
|
Loading…
Reference in a new issue