diff --git a/apiregiter.py b/apiregiter.py
new file mode 100644
index 0000000..e794181
--- /dev/null
+++ b/apiregiter.py
@@ -0,0 +1,17 @@
+import uuid
+import hashlib
+
+
+class Iota:
+ """
+ Framework for simulate the comunication with IOTA DLT
+ """
+
+ def issue_did(self):
+ u = str(uuid.uuid4()).encode()
+ d = hashlib.sha3_256(u).hexdigest()
+ did = "did:iota:{}".format(d)
+ return did
+
+
+iota = Iota()
diff --git a/examples/import_credentials.csv b/examples/import_credentials.csv
new file mode 100644
index 0000000..4a06714
--- /dev/null
+++ b/examples/import_credentials.csv
@@ -0,0 +1,2 @@
+name email membershipType
+Pepe user1@example.org individual
diff --git a/idhub/admin.py b/idhub/admin.py
deleted file mode 100644
index 049dca3..0000000
--- a/idhub/admin.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from django.contrib import admin
-
-from .models import AppUser
-
-admin.site.register(AppUser)
diff --git a/idhub/admin/forms.py b/idhub/admin/forms.py
index fc66f14..22b4954 100644
--- a/idhub/admin/forms.py
+++ b/idhub/admin/forms.py
@@ -1,27 +1,9 @@
from django import forms
-from django.contrib.auth.models import User
-from idhub.models import Rol
-class ProfileForm(forms.ModelForm):
- MANDATORY_FIELDS = ['first_name', 'last_name', 'email', 'username']
-
- class Meta:
- model = User
- fields = ('first_name', 'last_name', 'email')
+class ImportForm(forms.Form):
+ file_import = forms.FileField()
-class MembershipForm(forms.ModelForm):
- MANDATORY_FIELDS = ['type']
-
-
-class RolForm(forms.ModelForm):
- MANDATORY_FIELDS = ['name']
-
-
-class ServiceForm(forms.ModelForm):
- MANDATORY_FIELDS = ['domain', 'rol']
-
-
-class UserRolForm(forms.ModelForm):
- MANDATORY_FIELDS = ['service']
+class SchemaForm(forms.Form):
+ file_template = forms.FileField()
diff --git a/idhub/admin/views.py b/idhub/admin/views.py
index 13031b0..9e5b4e7 100644
--- a/idhub/admin/views.py
+++ b/idhub/admin/views.py
@@ -1,22 +1,35 @@
+import os
+import csv
+import json
+import copy
import logging
+import pandas as pd
+from pathlib import Path
+from jsonschema import validate
from smtplib import SMTPException
+from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.views.generic.base import TemplateView
-from django.views.generic.edit import UpdateView, CreateView
-from django.contrib.auth.models import User
+from django.views.generic.edit import UpdateView, CreateView, DeleteView
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse_lazy
+from django.http import HttpResponse
from django.contrib import messages
-from idhub.models import Membership, Rol, Service, UserRol
+from apiregiter import iota
+from idhub_auth.models import User
from idhub.mixins import AdminView
from idhub.email.views import NotifyActivateUserByEmail
-from idhub.admin.forms import (
- ProfileForm,
- MembershipForm,
- RolForm,
- ServiceForm,
- UserRolForm
+from idhub.admin.forms import ImportForm, SchemaForm
+from idhub.models import (
+ DID,
+ File_datas,
+ Membership,
+ Rol,
+ Service,
+ Schemas,
+ UserRol,
+ VerificableCredential,
)
@@ -42,9 +55,9 @@ class Credentials(AdminView, TemplateView):
section = "Credentials"
-class Schemes(AdminView, TemplateView):
- title = _("Schemes Management")
- section = "Schemes"
+class SchemasMix(AdminView, TemplateView):
+ title = _("Templates Management")
+ section = "Templates"
class ImportExport(AdminView, TemplateView):
@@ -118,8 +131,7 @@ class AdminPeopleDeleteView(AdminPeopleView):
class AdminPeopleEditView(AdminPeopleView, UpdateView):
template_name = "idhub/admin/user_edit.html"
- from_class = ProfileForm
- fields = ('first_name', 'last_name', 'email', 'username')
+ fields = ('first_name', 'last_name', 'email')
success_url = reverse_lazy('idhub:admin_people_list')
@@ -128,8 +140,7 @@ class AdminPeopleRegisterView(NotifyActivateUserByEmail, People, CreateView):
subtitle = _('People Register')
icon = 'bi bi-person'
model = User
- from_class = ProfileForm
- fields = ('first_name', 'last_name', 'email', 'username')
+ fields = ('first_name', 'last_name', 'email')
success_url = reverse_lazy('idhub:admin_people_list')
def get_success_url(self):
@@ -155,7 +166,6 @@ class AdminPeopleMembershipRegisterView(People, CreateView):
subtitle = _('People add membership')
icon = 'bi bi-person'
model = Membership
- from_class = MembershipForm
fields = ('type', 'start_date', 'end_date')
success_url = reverse_lazy('idhub:admin_people_list')
@@ -193,7 +203,6 @@ class AdminPeopleMembershipEditView(People, CreateView):
subtitle = _('People add membership')
icon = 'bi bi-person'
model = Membership
- from_class = MembershipForm
fields = ('type', 'start_date', 'end_date')
success_url = reverse_lazy('idhub:admin_people_list')
@@ -232,7 +241,6 @@ class AdminPeopleRolRegisterView(People, CreateView):
subtitle = _('Add Rol to User')
icon = 'bi bi-person'
model = UserRol
- from_class = UserRolForm
fields = ('service',)
def get(self, request, *args, **kwargs):
@@ -263,7 +271,6 @@ class AdminPeopleRolEditView(People, CreateView):
subtitle = _('Edit Rol to User')
icon = 'bi bi-person'
model = UserRol
- from_class = UserRolForm
fields = ('service',)
def get_form_kwargs(self):
@@ -311,7 +318,6 @@ class AdminRolRegisterView(AccessControl, CreateView):
subtitle = _('Add Rol')
icon = ''
model = Rol
- from_class = RolForm
fields = ('name',)
success_url = reverse_lazy('idhub:admin_roles')
object = None
@@ -322,7 +328,6 @@ class AdminRolEditView(AccessControl, CreateView):
subtitle = _('Edit Rol')
icon = ''
model = Rol
- from_class = RolForm
fields = ('name',)
success_url = reverse_lazy('idhub:admin_roles')
@@ -362,7 +367,6 @@ class AdminServiceRegisterView(AccessControl, CreateView):
subtitle = _('Add Service')
icon = ''
model = Service
- from_class = ServiceForm
fields = ('domain', 'description', 'rol')
success_url = reverse_lazy('idhub:admin_services')
object = None
@@ -373,7 +377,6 @@ class AdminServiceEditView(AccessControl, CreateView):
subtitle = _('Edit Service')
icon = ''
model = Service
- from_class = ServiceForm
fields = ('domain', 'description', 'rol')
success_url = reverse_lazy('idhub:admin_services')
@@ -401,11 +404,31 @@ class AdminCredentialsView(Credentials):
subtitle = _('Credentials list')
icon = ''
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'credentials': VerificableCredential.objects,
+ })
+ return context
-class AdminIssueCredentialsView(Credentials):
+
+class AdminCredentialView(Credentials):
template_name = "idhub/admin/issue_credentials.html"
- subtitle = _('Issuance of Credentials')
+ subtitle = _('Change status of Credential')
icon = ''
+ model = VerificableCredential
+
+ 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 get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'object': self.object,
+ })
+ return context
class AdminRevokeCredentialsView(Credentials):
@@ -414,12 +437,89 @@ class AdminRevokeCredentialsView(Credentials):
icon = ''
-class AdminWalletIdentitiesView(Credentials):
- template_name = "idhub/admin/wallet_identities.html"
+class AdminDidsView(Credentials):
+ template_name = "idhub/admin/dids.html"
subtitle = _('Organization Identities (DID)')
icon = 'bi bi-patch-check-fill'
wallet = True
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'dids': DID.objects,
+ })
+ return context
+
+class AdminDidRegisterView(Credentials, CreateView):
+ template_name = "idhub/admin/did_register.html"
+ subtitle = _('Add a new Organization Identities (DID)')
+ icon = 'bi bi-patch-check-fill'
+ wallet = True
+ model = DID
+ fields = ('did', 'label')
+ success_url = reverse_lazy('idhub:admin_dids')
+ object = None
+
+ def get_form_kwargs(self):
+ kwargs = super().get_form_kwargs()
+ kwargs['initial'] = {
+ 'did': iota.issue_did()
+ }
+ return kwargs
+
+ def get_form(self):
+ form = super().get_form()
+ form.fields['did'].required = False
+ form.fields['did'].disabled = True
+ return form
+
+ def form_valid(self, form):
+ form.save()
+ messages.success(self.request, _('DID created successfully'))
+ return super().form_valid(form)
+
+
+class AdminDidEditView(Credentials, UpdateView):
+ template_name = "idhub/admin/did_register.html"
+ subtitle = _('Organization Identities (DID)')
+ icon = 'bi bi-patch-check-fill'
+ wallet = True
+ model = DID
+ fields = ('did', 'label')
+ success_url = reverse_lazy('idhub:admin_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 get_form(self):
+ form = super().get_form()
+ form.fields['did'].required = False
+ form.fields['did'].disabled = True
+ return form
+
+ def form_valid(self, form):
+ user = form.save()
+ messages.success(self.request, _('DID updated successfully'))
+ return super().form_valid(form)
+
+
+class AdminDidDeleteView(Credentials, DeleteView):
+ subtitle = _('Organization Identities (DID)')
+ icon = 'bi bi-patch-check-fill'
+ wallet = True
+ model = DID
+ success_url = reverse_lazy('idhub:admin_dids')
+
+ def get(self, request, *args, **kwargs):
+ self.pk = kwargs['pk']
+ self.object = get_object_or_404(self.model, pk=self.pk)
+ self.object.delete()
+ messages.success(self.request, _('DID delete successfully'))
+
+ return redirect(self.success_url)
+
class AdminWalletCredentialsView(Credentials):
template_name = "idhub/admin/wallet_credentials.html"
@@ -435,22 +535,136 @@ class AdminWalletConfigIssuesView(Credentials):
wallet = True
-class AdminSchemesView(Schemes):
- template_name = "idhub/admin/schemes.html"
- subtitle = _('Schemes List')
+class AdminSchemasView(SchemasMix):
+ template_name = "idhub/admin/schemas.html"
+ subtitle = _('Template List')
icon = ''
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'schemas': Schemas.objects,
+ })
+ return context
-class AdminSchemesImportView(Schemes):
- template_name = "idhub/admin/schemes_import.html"
- subtitle = _('Import Schemes')
+
+class AdminSchemasDeleteView(SchemasMix):
+
+ def get(self, request, *args, **kwargs):
+ self.pk = kwargs['pk']
+ self.object = get_object_or_404(Schemas, pk=self.pk)
+ self.object.delete()
+
+ return redirect('idhub:admin_schemas')
+
+
+class AdminSchemasDownloadView(SchemasMix):
+
+ def get(self, request, *args, **kwargs):
+ self.pk = kwargs['pk']
+ self.object = get_object_or_404(Schemas, pk=self.pk)
+
+ response = HttpResponse(self.object.data, content_type="application/json")
+ response['Content-Disposition'] = 'inline; filename={}'.format(self.object.file_schema)
+ return response
+
+
+class AdminSchemasNewView(SchemasMix):
+ template_name = "idhub/admin/schemas_new.html"
+ subtitle = _('Upload Template')
+ icon = ''
+ success_url = reverse_lazy('idhub:admin_schemas')
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'form': SchemaForm(),
+ })
+ return context
+
+ def post(self, request, *args, **kwargs):
+ form = SchemaForm(request.POST, request.FILES)
+ if form.is_valid():
+ schema = self.handle_uploaded_file()
+ if not schema:
+ messages.error(request, _("There are some errors in the file"))
+ return super().get(request, *args, **kwargs)
+ return redirect(self.success_url)
+ else:
+ return super().get(request, *args, **kwargs)
+
+ return super().post(request, *args, **kwargs)
+
+ def handle_uploaded_file(self):
+ f = self.request.FILES.get('file_template')
+ if not f:
+ return
+ file_name = f.name
+ if Schemas.objects.filter(file_schema=file_name).exists():
+ messages.error(self.request, _("This template already exists!"))
+ return
+ try:
+ data = f.read().decode('utf-8')
+ json.loads(data)
+ except Exception:
+ messages.error(self.request, _('This is not a schema valid!'))
+ return
+ schema = Schemas.objects.create(file_schema=file_name, data=data)
+ schema.save()
+ return schema
+
+
+class AdminSchemasImportView(SchemasMix):
+ template_name = "idhub/admin/schemas_import.html"
+ subtitle = _('Import Template')
icon = ''
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'schemas': self.get_schemas(),
+ })
+ return context
-class AdminSchemesExportView(Schemes):
- template_name = "idhub/admin/schemes_export.html"
- subtitle = _('Export Schemes')
- icon = ''
+ def get_schemas(self):
+ schemas_files = os.listdir(settings.SCHEMAS_DIR)
+ schemas = [x for x in schemas_files
+ if not Schemas.objects.filter(file_schema=x).exists()]
+ return schemas
+
+
+class AdminSchemasImportAddView(SchemasMix):
+
+ def get(self, request, *args, **kwargs):
+ file_name = kwargs['file_schema']
+ schemas_files = os.listdir(settings.SCHEMAS_DIR)
+ if not file_name in schemas_files:
+ messages.error(self.request, f"The schema {file_name} not exist!")
+ return redirect('idhub:admin_schemas_import')
+
+ schema = self.create_schema(file_name)
+ if schema:
+ messages.success(self.request, _("The schema add successfully!"))
+ return redirect('idhub:admin_schemas_import')
+
+ def create_schema(self, file_name):
+ data = self.open_file(file_name)
+ try:
+ json.loads(data)
+ except Exception:
+ messages.error(self.request, _('This is not a schema valid!'))
+ return
+ schema = Schemas.objects.create(file_schema=file_name, data=data)
+ schema.save()
+ return schema
+
+ def open_file(self, file_name):
+ data = ''
+ filename = Path(settings.SCHEMAS_DIR).joinpath(file_name)
+ with filename.open() as schema_file:
+ data = schema_file.read()
+
+ return data
class AdminImportView(ImportExport):
@@ -458,8 +672,114 @@ class AdminImportView(ImportExport):
subtitle = _('Import')
icon = ''
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'dates': File_datas.objects,
+ })
+ return context
-class AdminExportView(ImportExport):
- template_name = "idhub/admin/export.html"
- subtitle = _('Export')
+
+class AdminImportStep2View(ImportExport):
+ template_name = "idhub/admin/import_step2.html"
+ subtitle = _('Import')
icon = ''
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'schemas': Schemas.objects,
+ })
+ return context
+
+
+class AdminImportStep3View(ImportExport):
+ template_name = "idhub/admin/import_step3.html"
+ subtitle = _('Import')
+ icon = ''
+ success_url = reverse_lazy('idhub:admin_import')
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'form': ImportForm(),
+ })
+ return context
+
+ def post(self, request, *args, **kwargs):
+ self.pk = kwargs['pk']
+ self.schema = get_object_or_404(Schemas, pk=self.pk)
+ form = ImportForm(request.POST, request.FILES)
+ if form.is_valid():
+ result = self.handle_uploaded_file()
+ if not result:
+ messages.error(request, _("There are some errors in the file"))
+ return super().get(request, *args, **kwargs)
+ return redirect(self.success_url)
+ else:
+ return super().get(request, *args, **kwargs)
+
+ return super().post(request, *args, **kwargs)
+
+ def handle_uploaded_file(self):
+ f = self.request.FILES.get('file_import')
+ if not f:
+ messages.error(self.request, _("There aren't file"))
+ return
+
+ file_name = f.name
+ if File_datas.objects.filter(file_name=file_name, success=True).exists():
+ messages.error(self.request, _("This file already exists!"))
+ return
+
+ self.json_schema = json.loads(self.schema.data)
+ df = pd.read_csv (f, delimiter="\t", quotechar='"', quoting=csv.QUOTE_ALL)
+ data_pd = df.fillna('').to_dict()
+ rows = {}
+
+ if not data_pd:
+ File_datas.objects.create(file_name=file_name, success=False)
+ return
+
+ for n in range(df.last_valid_index()+1):
+ row = {}
+ for k in data_pd.keys():
+ row[k] = data_pd[k][n]
+
+ user = self.validate(n, row)
+ if not user:
+ File_datas.objects.create(file_name=file_name, success=False)
+ return
+
+ rows[user] = row
+
+ File_datas.objects.create(file_name=file_name)
+ for k, v in rows.items():
+ self.create_credential(k, v)
+
+ return True
+
+ def validate(self, line, row):
+ try:
+ validate(instance=row, schema=self.json_schema)
+ except Exception as e:
+ messages.error(self.request, "line {}: {}".format(line+1, e))
+ return
+
+ user = User.objects.filter(email=row.get('email'))
+ if not user:
+ txt = _('The user not exist!')
+ messages.error(self.request, "line {}: {}".format(line+1, txt))
+ return
+
+ return user.first()
+
+ def create_credential(self, user, row):
+ d = copy.copy(self.json_schema)
+ d['instance'] = row
+ return VerificableCredential.objects.create(
+ verified=False,
+ user=user,
+ data=json.dumps(d)
+ )
+
diff --git a/idhub/management/__init__.py b/idhub/management/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/idhub/management/commands/__init__.py b/idhub/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/idhub/management/commands/initial_datas.py b/idhub/management/commands/initial_datas.py
new file mode 100644
index 0000000..71506c6
--- /dev/null
+++ b/idhub/management/commands/initial_datas.py
@@ -0,0 +1,39 @@
+from django.core.management.base import BaseCommand, CommandError
+from django.contrib.auth import get_user_model
+from idhub.models import Organization
+
+
+User = get_user_model()
+
+
+class Command(BaseCommand):
+ help = "Insert minimum datas for the project"
+
+ def handle(self, *args, **kwargs):
+ admin = 'admin@example.org'
+ pw_admin = '1234'
+
+ user = 'user1@example.org'
+ pw_user = '1234'
+ organization = [
+ ("ExO", "https://verify.exo.cat"),
+ ("Somos Connexión", "https://verify.somosconexion.coop")
+ ]
+
+ # self.create_admin_users(admin, pw_admin)
+ self.create_users(user, pw_user)
+ for o in organization:
+ self.create_organizations(*o)
+
+ def create_admin_users(self, email, password):
+ User.objects.create_superuser(email=email, password=password)
+
+
+ def create_users(self, email, password):
+ u= User.objects.create(email=email, password=password)
+ u.set_password(password)
+ u.save()
+
+
+ def create_organizations(self, name, url):
+ Organization.objects.create(name=name, url=url)
diff --git a/idhub/migrations/0001_initial.py b/idhub/migrations/0001_initial.py
index 81b98e5..fe6fc19 100644
--- a/idhub/migrations/0001_initial.py
+++ b/idhub/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 4.2.5 on 2023-10-16 09:41
+# Generated by Django 4.2.5 on 2023-11-02 15:08
from django.conf import settings
from django.db import migrations, models
@@ -14,115 +14,247 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- name="VCTemplate",
+ name='File_datas',
fields=[
(
- "id",
+ 'id',
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
- verbose_name="ID",
+ verbose_name='ID',
),
),
- ("wkit_template_id", models.CharField(max_length=250)),
- ("data", models.TextField()),
+ ('file_name', models.CharField(max_length=250)),
+ ('success', models.BooleanField(default=True)),
+ ('created_at', models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
- name="VerifiableCredential",
+ name='Organization',
fields=[
(
- "id",
+ 'id',
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
- verbose_name="ID",
+ verbose_name='ID',
),
),
- ("id_string", models.CharField(max_length=250)),
- ("verified", models.BooleanField()),
- ("created_on", models.DateTimeField()),
- ("did_issuer", models.CharField(max_length=250)),
- ("did_subject", models.CharField(max_length=250)),
- ("data", models.TextField()),
+ ('name', models.CharField(max_length=250)),
(
- "user",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="vcredentials",
- to=settings.AUTH_USER_MODEL,
+ 'url',
+ models.CharField(
+ help_text='Url where to send the presentation', max_length=250
),
),
],
),
migrations.CreateModel(
- name="Membership",
+ name='Rol',
fields=[
(
- "id",
+ 'id',
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
- verbose_name="ID",
+ verbose_name='ID',
),
),
+ ('name', models.CharField(max_length=250)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Schemas',
+ fields=[
(
- "type",
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ ('file_schema', models.CharField(max_length=250)),
+ ('data', models.TextField()),
+ ('created_at', models.DateTimeField(auto_now=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Service',
+ fields=[
+ (
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ ('domain', models.CharField(max_length=250)),
+ ('description', models.CharField(max_length=250)),
+ ('rol', models.ManyToManyField(to='idhub.rol')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='VCTemplate',
+ fields=[
+ (
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ ('wkit_template_id', models.CharField(max_length=250)),
+ ('data', models.TextField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='VerificableCredential',
+ fields=[
+ (
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ ('id_string', models.CharField(max_length=250)),
+ ('verified', models.BooleanField()),
+ ('created_on', models.DateTimeField(auto_now=True)),
+ ('issuer_on', models.DateTimeField(null=True)),
+ ('did_issuer', models.CharField(max_length=250)),
+ ('did_subject', models.CharField(max_length=250)),
+ ('data', models.TextField()),
+ (
+ 'status',
models.PositiveSmallIntegerField(
- choices=[(1, "Beneficiary"), (2, "Employee"), (3, "Partner")],
- verbose_name="Type of membership",
+ choices=[
+ (1, 'Enabled'),
+ (2, 'Issued'),
+ (3, 'Revoked'),
+ (4, 'Expired'),
+ ],
+ default=1,
),
),
(
- "start_date",
- models.DateField(
- blank=True,
- help_text="What date did the membership start?",
- null=True,
- verbose_name="Start date",
- ),
- ),
- (
- "end_date",
- models.DateField(
- blank=True,
- help_text="What date did the membership end?",
- null=True,
- verbose_name="End date",
- ),
- ),
- (
- "user",
+ 'user',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
- related_name="memberships",
+ related_name='vcredentials',
to=settings.AUTH_USER_MODEL,
),
),
],
),
migrations.CreateModel(
- name="DID",
+ name='UserRol',
fields=[
(
- "id",
+ 'id',
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
- verbose_name="ID",
+ verbose_name='ID',
),
),
- ("did_string", models.CharField(max_length=250)),
- ("label", models.CharField(max_length=50)),
(
- "user",
+ 'service',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
- related_name="dids",
+ related_name='users',
+ to='idhub.service',
+ ),
+ ),
+ (
+ 'user',
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='roles',
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Membership',
+ fields=[
+ (
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ (
+ 'type',
+ models.PositiveSmallIntegerField(
+ choices=[(1, 'Beneficiary'), (2, 'Employee'), (3, 'Partner')],
+ verbose_name='Type of membership',
+ ),
+ ),
+ (
+ 'start_date',
+ models.DateField(
+ blank=True,
+ help_text='What date did the membership start?',
+ null=True,
+ verbose_name='Start date',
+ ),
+ ),
+ (
+ 'end_date',
+ models.DateField(
+ blank=True,
+ help_text='What date did the membership end?',
+ null=True,
+ verbose_name='End date',
+ ),
+ ),
+ (
+ 'user',
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='memberships',
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
+ ],
+ ),
+ migrations.CreateModel(
+ name='DID',
+ fields=[
+ (
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ ('created_at', models.DateTimeField(auto_now=True)),
+ ('did', models.CharField(max_length=250, unique=True)),
+ ('label', models.CharField(max_length=50)),
+ (
+ 'user',
+ models.ForeignKey(
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='dids',
to=settings.AUTH_USER_MODEL,
),
),
diff --git a/idhub/migrations/0002_rol.py b/idhub/migrations/0002_rol.py
deleted file mode 100644
index 41f8aba..0000000
--- a/idhub/migrations/0002_rol.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 4.2.5 on 2023-10-17 11:28
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
- dependencies = [
- ("idhub", "0001_initial"),
- ]
-
- operations = [
- migrations.CreateModel(
- name="Rol",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- ("name", models.CharField(max_length=250)),
- ],
- ),
- ]
diff --git a/idhub/migrations/0003_service.py b/idhub/migrations/0003_service.py
deleted file mode 100644
index 2c908de..0000000
--- a/idhub/migrations/0003_service.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Generated by Django 4.2.5 on 2023-10-17 13:29
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
- dependencies = [
- ("idhub", "0002_rol"),
- ]
-
- operations = [
- migrations.CreateModel(
- name="Service",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- ("domain", models.CharField(max_length=250)),
- ("description", models.CharField(max_length=250)),
- (
- "rol",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="services",
- to="idhub.rol",
- ),
- ),
- ],
- ),
- ]
diff --git a/idhub/migrations/0004_userrol.py b/idhub/migrations/0004_userrol.py
deleted file mode 100644
index 5955a70..0000000
--- a/idhub/migrations/0004_userrol.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Generated by Django 4.2.5 on 2023-10-17 14:24
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ("idhub", "0003_service"),
- ]
-
- operations = [
- migrations.CreateModel(
- name="UserRol",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- (
- "service",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="users",
- to="idhub.service",
- ),
- ),
- (
- "user",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="roles",
- to=settings.AUTH_USER_MODEL,
- ),
- ),
- ],
- ),
- ]
diff --git a/idhub/migrations/0005_remove_service_rol_service_rol.py b/idhub/migrations/0005_remove_service_rol_service_rol.py
deleted file mode 100644
index a383ca4..0000000
--- a/idhub/migrations/0005_remove_service_rol_service_rol.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Generated by Django 4.2.5 on 2023-10-19 13:01
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
- dependencies = [
- ("idhub", "0004_userrol"),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name="service",
- name="rol",
- ),
- migrations.AddField(
- model_name="service",
- name="rol",
- field=models.ManyToManyField(to="idhub.rol"),
- ),
- ]
diff --git a/idhub/mixins.py b/idhub/mixins.py
index c888327..68b7344 100644
--- a/idhub/mixins.py
+++ b/idhub/mixins.py
@@ -26,7 +26,7 @@ class UserView(LoginRequiredMixin):
class AdminView(UserView):
def get(self, request, *args, **kwargs):
- if not request.user.is_superuser:
+ if not request.user.is_admin:
url = reverse_lazy('idhub:user_dashboard')
return redirect(url)
diff --git a/idhub/models.py b/idhub/models.py
index 3c187b3..8a805d4 100644
--- a/idhub/models.py
+++ b/idhub/models.py
@@ -1,15 +1,8 @@
+import json
+import requests
from django.db import models
from django.utils.translation import gettext_lazy as _
-from django.contrib.auth.models import User
-
-
-# class AppUser(models.Model):
- # Ya incluye "first_name", "last_name", "email", y "date_joined" heredando de la clase User de django.
- # Falta ver que más información hay que añadir a nuestros usuarios, como los roles etc.
- # django_user = models.OneToOneField(DjangoUser, on_delete=models.CASCADE)
-
- # Extra data, segun entidad/organizacion
- # pass
+from idhub_auth.models import User
# class Event(models.Model):
@@ -20,35 +13,103 @@ from django.contrib.auth.models import User
class DID(models.Model):
- did_string = models.CharField(max_length=250)
+ created_at = models.DateTimeField(auto_now=True)
+ did = models.CharField(max_length=250, unique=True)
label = models.CharField(max_length=50)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='dids',
+ null=True,
)
# kind = "KEY|WEB"
+ @property
+ def is_organization_did(self):
+ if not self.user:
+ return True
+ return False
+
+
+class Schemas(models.Model):
+ file_schema = models.CharField(max_length=250)
+ data = models.TextField()
+ created_at = models.DateTimeField(auto_now=True)
+
+ @property
+ def get_schema(self):
+ if not self.data:
+ return {}
+ return json.loads(self.data)
+
+ def name(self):
+ return self.get_schema.get('name', '')
+
+ def description(self):
+ return self.get_schema.get('description', '')
+
+
+class VerificableCredential(models.Model):
+ """
+ Definition of Verificable Credentials
+ """
+ class Status(models.IntegerChoices):
+ ENABLED = 1, _("Enabled")
+ ISSUED = 2, _("Issued")
+ REVOKED = 3, _("Revoked")
+ EXPIRED = 4, _("Expired")
-class VerifiableCredential(models.Model):
id_string = models.CharField(max_length=250)
verified = models.BooleanField()
- created_on = models.DateTimeField()
+ created_on = models.DateTimeField(auto_now=True)
+ issuer_on = models.DateTimeField(null=True)
did_issuer = models.CharField(max_length=250)
did_subject = models.CharField(max_length=250)
+ data = models.TextField()
+ status = models.PositiveSmallIntegerField(
+ choices=Status.choices,
+ default=Status.ENABLED
+ )
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='vcredentials',
)
- data = models.TextField()
+ @property
+ def get_schema(self):
+ if not self.data:
+ return {}
+ return json.loads(self.data)
+
+ def type(self):
+ return self.get_schema.get('name', '')
+
+ def description(self):
+ return self.get_schema.get('description', '')
+
+ def get_status(self):
+ return self.Status(self.status).label
+
+ def get_datas(self):
+ data = json.loads(self.data).get('instance').items()
+ return data
+
+ def get_issued(self, did):
+ self.status = self.Status.ISSUED
+ self.did_subject = did
class VCTemplate(models.Model):
wkit_template_id = models.CharField(max_length=250)
data = models.TextField()
+class File_datas(models.Model):
+ file_name = models.CharField(max_length=250)
+ success = models.BooleanField(default=True)
+ created_at = models.DateTimeField(auto_now=True)
+
+
class Membership(models.Model):
"""
This model represent the relation of this user with the ecosystem.
@@ -100,7 +161,7 @@ class Service(models.Model):
return ", ".join([x.name for x in self.rol.all()])
def __str__(self):
- return "{} -> {}".format(self.domain, self.rol.name)
+ return "{} -> {}".format(self.domain, self.get_roles())
class UserRol(models.Model):
@@ -114,3 +175,18 @@ class UserRol(models.Model):
on_delete=models.CASCADE,
related_name='users',
)
+
+
+class Organization(models.Model):
+ name = models.CharField(max_length=250)
+ url = models.CharField(
+ help_text=_("Url where to send the presentation"),
+ max_length=250
+ )
+
+ def __str__(self):
+ return self.name
+
+ def send(self, cred):
+ return
+ requests.post(self.url, data=cred.data)
\ No newline at end of file
diff --git a/idhub/templates/idhub/admin/credentials.html b/idhub/templates/idhub/admin/credentials.html
index f5849fd..0d7e84c 100644
--- a/idhub/templates/idhub/admin/credentials.html
+++ b/idhub/templates/idhub/admin/credentials.html
@@ -6,4 +6,34 @@
{{ subtitle }}
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+
+ {% for f in credentials.all %}
+
+ {{ f.type }} |
+ {{ f.description }} |
+ {{ f.issue_on }} |
+ {{ f.get_status }} |
+ {{ f.user.email }} |
+ {% trans 'View' %} |
+
+ {% endfor %}
+
+
+
+
+
{% endblock %}
diff --git a/idhub/templates/idhub/admin/did_register.html b/idhub/templates/idhub/admin/did_register.html
new file mode 100644
index 0000000..a4fe719
--- /dev/null
+++ b/idhub/templates/idhub/admin/did_register.html
@@ -0,0 +1,34 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+{% load django_bootstrap5 %}
+
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/dids.html b/idhub/templates/idhub/admin/dids.html
new file mode 100644
index 0000000..00765af
--- /dev/null
+++ b/idhub/templates/idhub/admin/dids.html
@@ -0,0 +1,60 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+ {% for d in dids.all %}
+
+ {{ d.created_at }} |
+ {{ d.label }} |
+ {{ d.did }} |
+ |
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+
+{% for d in dids.all %}
+
+
+
+
+
+ {% trans 'Are you sure that you want delete this DID?' %}
+
+
+
+
+
+{% endfor %}
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/import.html b/idhub/templates/idhub/admin/import.html
index f5849fd..a1b77be 100644
--- a/idhub/templates/idhub/admin/import.html
+++ b/idhub/templates/idhub/admin/import.html
@@ -6,4 +6,31 @@
{{ subtitle }}
+
+
+
+
+
+
+ |
+ |
+ |
+
+
+
+ {% for f in dates.all %}
+
+ {{ f.created_at }} |
+ {{ f.file_name }} |
+ {% if f.success %}{% else %}{% endif %} |
+
+ {% endfor %}
+
+
+
+
+
+
{% endblock %}
diff --git a/idhub/templates/idhub/admin/import_step2.html b/idhub/templates/idhub/admin/import_step2.html
new file mode 100644
index 0000000..f18821f
--- /dev/null
+++ b/idhub/templates/idhub/admin/import_step2.html
@@ -0,0 +1,34 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+
+ {% for schema in schemas.all %}
+
+ {{ schema.created_at }} |
+ {{ schema.file_schema }} |
+ {% trans 'Import Dates' %} |
+
+ {% endfor %}
+
+
+
+
+
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/import_step3.html b/idhub/templates/idhub/admin/import_step3.html
new file mode 100644
index 0000000..7cb6270
--- /dev/null
+++ b/idhub/templates/idhub/admin/import_step3.html
@@ -0,0 +1,32 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+{% load django_bootstrap5 %}
+
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/issue_credentials.html b/idhub/templates/idhub/admin/issue_credentials.html
index f5849fd..ccb48a4 100644
--- a/idhub/templates/idhub/admin/issue_credentials.html
+++ b/idhub/templates/idhub/admin/issue_credentials.html
@@ -2,8 +2,55 @@
{% load i18n %}
{% block content %}
-
-
- {{ subtitle }}
-
+
+
+
+
+
+ {% for k, v in object.get_datas %}
+
+
+ {{ k|capfirst }}:
+
+
+ {{ v }}
+
+
+ {% endfor %}
+
+
+ Date of Issue:
+
+
+ {{ object.issuer_on|default_if_none:"" }}
+
+
+
+
+ Status:
+
+
+ {{ object.get_status}}
+
+
+
+
+
{% endblock %}
diff --git a/idhub/templates/idhub/admin/people.html b/idhub/templates/idhub/admin/people.html
index ff19975..2df8577 100644
--- a/idhub/templates/idhub/admin/people.html
+++ b/idhub/templates/idhub/admin/people.html
@@ -12,7 +12,7 @@
|
|
- |
+ |
|
|
|
@@ -23,7 +23,7 @@
{{ user.last_name }} |
{{ user.first_name }} |
- {{ user.username }} |
+ {{ user.email }} |
{% for m in user.memberships.all %}
{{ m.get_type }}
diff --git a/idhub/templates/idhub/admin/schemas.html b/idhub/templates/idhub/admin/schemas.html
new file mode 100644
index 0000000..2aa2e88
--- /dev/null
+++ b/idhub/templates/idhub/admin/schemas.html
@@ -0,0 +1,62 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+
+ {% for schema in schemas.all %}
+
+ {{ schema.created_at }} |
+ {{ schema.file_schema }} |
+ {{ schema.name }} |
+ {{ schema.description }} |
+ {% trans 'View' %} |
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+
+{% for schema in schemas.all %}
+
+
+
+
+
+ {% trans 'Are you sure that you want delete this template?' %}
+
+
+
+
+
+{% endfor %}
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/schemes.html b/idhub/templates/idhub/admin/schemas_export.html
similarity index 100%
rename from idhub/templates/idhub/admin/schemes.html
rename to idhub/templates/idhub/admin/schemas_export.html
diff --git a/idhub/templates/idhub/admin/schemas_import.html b/idhub/templates/idhub/admin/schemas_import.html
new file mode 100644
index 0000000..b20608b
--- /dev/null
+++ b/idhub/templates/idhub/admin/schemas_import.html
@@ -0,0 +1,34 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+ {% for schema in schemas %}
+
+ {{ schema }} |
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/schemas_new.html b/idhub/templates/idhub/admin/schemas_new.html
new file mode 100644
index 0000000..83ad176
--- /dev/null
+++ b/idhub/templates/idhub/admin/schemas_new.html
@@ -0,0 +1,32 @@
+{% extends "idhub/base_admin.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+{% load django_bootstrap5 %}
+
+{% endblock %}
diff --git a/idhub/templates/idhub/admin/schemes_export.html b/idhub/templates/idhub/admin/schemes_export.html
deleted file mode 100644
index f5849fd..0000000
--- a/idhub/templates/idhub/admin/schemes_export.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "idhub/base_admin.html" %}
-{% load i18n %}
-
-{% block content %}
-
-
- {{ subtitle }}
-
-{% endblock %}
diff --git a/idhub/templates/idhub/admin/schemes_import.html b/idhub/templates/idhub/admin/schemes_import.html
deleted file mode 100644
index f5849fd..0000000
--- a/idhub/templates/idhub/admin/schemes_import.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "idhub/base_admin.html" %}
-{% load i18n %}
-
-{% block content %}
-
-
- {{ subtitle }}
-
-{% endblock %}
diff --git a/idhub/templates/idhub/admin/user.html b/idhub/templates/idhub/admin/user.html
index 3bee80f..410146f 100644
--- a/idhub/templates/idhub/admin/user.html
+++ b/idhub/templates/idhub/admin/user.html
@@ -109,7 +109,7 @@
diff --git a/idhub/templates/idhub/admin/wallet_identities.html b/idhub/templates/idhub/admin/wallet_identities.html
deleted file mode 100644
index f5849fd..0000000
--- a/idhub/templates/idhub/admin/wallet_identities.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "idhub/base_admin.html" %}
-{% load i18n %}
-
-{% block content %}
-
-
- {{ subtitle }}
-
-{% endblock %}
diff --git a/idhub/templates/idhub/base.html b/idhub/templates/idhub/base.html
index 17627ad..f279027 100644
--- a/idhub/templates/idhub/base.html
+++ b/idhub/templates/idhub/base.html
@@ -100,7 +100,7 @@
-
-
- {{ subtitle }}
-
{% block content %}
{% endblock content %}
diff --git a/idhub/templates/idhub/base_admin.html b/idhub/templates/idhub/base_admin.html
index 8f8e3aa..91715e2 100644
--- a/idhub/templates/idhub/base_admin.html
+++ b/idhub/templates/idhub/base_admin.html
@@ -117,23 +117,13 @@
Credentials list
-
-
- Issue credentials
-
-
-
-
- Revoke Credentials
-
-
Wallet
-
+
- Schemes
+ Templates
-
-
+
- Imports/Exports
+ Import Datas
-
diff --git a/idhub/templates/idhub/user/credential.html b/idhub/templates/idhub/user/credential.html
new file mode 100644
index 0000000..4593adf
--- /dev/null
+++ b/idhub/templates/idhub/user/credential.html
@@ -0,0 +1,46 @@
+{% extends "idhub/base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+ {% for k, v in object.get_datas %}
+
+
+ {{ k|capfirst }}:
+
+
+ {{ v }}
+
+
+ {% endfor %}
+
+
+ Date of Issue:
+
+
+ {{ object.issuer_on|default_if_none:"" }}
+
+
+
+
+ Status:
+
+
+ {{ object.get_status}}
+
+
+
+
+
+{% endblock %}
diff --git a/idhub/templates/idhub/user/credentials.html b/idhub/templates/idhub/user/credentials.html
index d6520a0..f6f694d 100644
--- a/idhub/templates/idhub/user/credentials.html
+++ b/idhub/templates/idhub/user/credentials.html
@@ -2,4 +2,40 @@
{% load i18n %}
{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+ {% for f in credentials.all %}
+
+ {{ f.type }} |
+ {{ f.description }} |
+ {{ f.issue_on }} |
+ {{ f.get_status }} |
+
+
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+
{% endblock %}
diff --git a/idhub/templates/idhub/user/credentials_presentation.html b/idhub/templates/idhub/user/credentials_presentation.html
index d6520a0..b94e3c8 100644
--- a/idhub/templates/idhub/user/credentials_presentation.html
+++ b/idhub/templates/idhub/user/credentials_presentation.html
@@ -2,4 +2,33 @@
{% load i18n %}
{% block content %}
+
+
+ {{ subtitle }}
+
+{% load django_bootstrap5 %}
+
{% endblock %}
diff --git a/idhub/templates/idhub/user/credentials_request.html b/idhub/templates/idhub/user/credentials_request.html
new file mode 100644
index 0000000..6dc720d
--- /dev/null
+++ b/idhub/templates/idhub/user/credentials_request.html
@@ -0,0 +1,34 @@
+{% extends "idhub/base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+{% load django_bootstrap5 %}
+
+{% endblock %}
diff --git a/idhub/templates/idhub/user/credentials_required.html b/idhub/templates/idhub/user/credentials_required.html
deleted file mode 100644
index d6520a0..0000000
--- a/idhub/templates/idhub/user/credentials_required.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "idhub/base.html" %}
-{% load i18n %}
-
-{% block content %}
-{% endblock %}
diff --git a/idhub/templates/idhub/user/dashboard.html b/idhub/templates/idhub/user/dashboard.html
index 8fa4a87..29154f4 100644
--- a/idhub/templates/idhub/user/dashboard.html
+++ b/idhub/templates/idhub/user/dashboard.html
@@ -2,6 +2,10 @@
{% load i18n %}
{% block content %}
+
+
+ {{ subtitle }}
+
diff --git a/idhub/templates/idhub/user/did_register.html b/idhub/templates/idhub/user/did_register.html
new file mode 100644
index 0000000..b2e1111
--- /dev/null
+++ b/idhub/templates/idhub/user/did_register.html
@@ -0,0 +1,34 @@
+{% extends "idhub/base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+{% load django_bootstrap5 %}
+
+{% endblock %}
diff --git a/idhub/templates/idhub/user/dids.html b/idhub/templates/idhub/user/dids.html
new file mode 100644
index 0000000..eae3db6
--- /dev/null
+++ b/idhub/templates/idhub/user/dids.html
@@ -0,0 +1,60 @@
+{% extends "idhub/base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+ {% for d in dids.all %}
+
+ {{ d.created_at }} |
+ {{ d.label }} |
+ {{ d.did }} |
+ |
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+
+{% for d in dids.all %}
+
+
+
+
+
+ {% trans 'Are you sure that you want delete this DID?' %}
+
+
+
+
+
+{% endfor %}
+{% endblock %}
diff --git a/idhub/templates/idhub/user/gdpr.html b/idhub/templates/idhub/user/gdpr.html
index d6520a0..1ac25fd 100644
--- a/idhub/templates/idhub/user/gdpr.html
+++ b/idhub/templates/idhub/user/gdpr.html
@@ -2,4 +2,8 @@
{% load i18n %}
{% block content %}
+
+
+ {{ subtitle }}
+
{% endblock %}
diff --git a/idhub/templates/idhub/user/identities.html b/idhub/templates/idhub/user/identities.html
deleted file mode 100644
index d6520a0..0000000
--- a/idhub/templates/idhub/user/identities.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "idhub/base.html" %}
-{% load i18n %}
-
-{% block content %}
-{% endblock %}
diff --git a/idhub/templates/idhub/user/profile.html b/idhub/templates/idhub/user/profile.html
index fb129ba..da1597a 100644
--- a/idhub/templates/idhub/user/profile.html
+++ b/idhub/templates/idhub/user/profile.html
@@ -2,6 +2,18 @@
{% load i18n %}
{% block content %}
+
+
+
+
+ {{ subtitle }}
+
+
+
+
{% load django_bootstrap5 %}
+
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+
+ {% for membership in object.memberships.all %}
+
+ {{ membership.get_type }} |
+ {{ membership.start_date|default:'' }} |
+ {{ membership.end_date|default:'' }} |
+
+
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+
{% endblock %}
diff --git a/idhub/templates/idhub/user/roles.html b/idhub/templates/idhub/user/roles.html
index e439a01..0295b53 100644
--- a/idhub/templates/idhub/user/roles.html
+++ b/idhub/templates/idhub/user/roles.html
@@ -2,6 +2,10 @@
{% load i18n %}
{% block content %}
+
+
+ {{ subtitle }}
+
@@ -16,7 +20,7 @@
{% for rol in user.roles.all %}
- {{ rol.service.rol.name }} |
+ {{ rol.service.get_roles }} |
{{ rol.service.description }} |
{{ rol.service.domain }} |
diff --git a/idhub/urls.py b/idhub/urls.py
index 6254243..eeb6b09 100644
--- a/idhub/urls.py
+++ b/idhub/urls.py
@@ -67,13 +67,23 @@ urlpatterns = [
name='user_roles'),
path('user/gdpr/', views_user.UserGDPRView.as_view(),
name='user_gdpr'),
- path('user/identities/', views_user.UserIdentitiesView.as_view(),
- name='user_identities'),
+ path('user/identities/', views_user.UserDidsView.as_view(),
+ name='user_dids'),
+ path('user/dids/new/', views_user.UserDidRegisterView.as_view(),
+ name='user_dids_new'),
+ path('user/dids//', views_user.UserDidEditView.as_view(),
+ name='user_dids_edit'),
+ path('user/dids//del/', views_user.UserDidDeleteView.as_view(),
+ name='user_dids_del'),
path('user/credentials/', views_user.UserCredentialsView.as_view(),
name='user_credentials'),
- path('user/credentials_required/',
- views_user.UserCredentialsRequiredView.as_view(),
- name='user_credentials_required'),
+ path('user/credentials/', views_user.UserCredentialView.as_view(),
+ name='user_credential'),
+ path('user/credentials//json', views_user.UserCredentialJsonView.as_view(),
+ name='user_credential_json'),
+ path('user/credentials/request/',
+ views_user.UserCredentialsRequestView.as_view(),
+ name='user_credentials_request'),
path('user/credentials_presentation/',
views_user.UserCredentialsPresentationView.as_view(),
name='user_credentials_presentation'),
@@ -123,26 +133,40 @@ urlpatterns = [
name='admin_service_del'),
path('admin/credentials/', views_admin.AdminCredentialsView.as_view(),
name='admin_credentials'),
- path('admin/credentials/new/', views_admin.AdminIssueCredentialsView.as_view(),
- name='admin_credentials_new'),
+ path('admin/credentials//', views_admin.AdminCredentialView.as_view(),
+ name='admin_credential'),
path('admin/credentials/revoke/', views_admin.AdminRevokeCredentialsView.as_view(),
name='admin_credentials_revoke'),
- path('admin/wallet/identities/', views_admin.AdminWalletIdentitiesView.as_view(),
- name='admin_wallet_identities'),
+ path('admin/wallet/identities/', views_admin.AdminDidsView.as_view(),
+ name='admin_dids'),
+ path('admin/dids/new/', views_admin.AdminDidRegisterView.as_view(),
+ name='admin_dids_new'),
+ path('admin/dids//', views_admin.AdminDidEditView.as_view(),
+ name='admin_dids_edit'),
+ path('admin/dids//del/', views_admin.AdminDidDeleteView.as_view(),
+ name='admin_dids_del'),
path('admin/wallet/credentials/', views_admin.AdminWalletCredentialsView.as_view(),
name='admin_wallet_credentials'),
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
name='admin_wallet_config_issue'),
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
name='admin_wallet_config_issue'),
- path('admin/schemes/', views_admin.AdminSchemesView.as_view(),
- name='admin_schemes'),
- path('admin/schemes/import', views_admin.AdminSchemesImportView.as_view(),
- name='admin_schemes_import'),
- path('admin/schemes/export/', views_admin.AdminSchemesExportView.as_view(),
- name='admin_schemes_export'),
+ path('admin/schemas/', views_admin.AdminSchemasView.as_view(),
+ name='admin_schemas'),
+ path('admin/schemas//del/', views_admin.AdminSchemasDeleteView.as_view(),
+ name='admin_schemas_del'),
+ path('admin/schemas//', views_admin.AdminSchemasDownloadView.as_view(),
+ name='admin_schemas_download'),
+ path('admin/schemas/new', views_admin.AdminSchemasNewView.as_view(),
+ name='admin_schemas_new'),
+ path('admin/schemas/import', views_admin.AdminSchemasImportView.as_view(),
+ name='admin_schemas_import'),
+ path('admin/schemas/import/', views_admin.AdminSchemasImportAddView.as_view(),
+ name='admin_schemas_import_add'),
path('admin/import', views_admin.AdminImportView.as_view(),
name='admin_import'),
- path('admin/export/', views_admin.AdminExportView.as_view(),
- name='admin_export'),
+ path('admin/import/new', views_admin.AdminImportStep2View.as_view(),
+ name='admin_import_step2'),
+ path('admin/import//', views_admin.AdminImportStep3View.as_view(),
+ name='admin_import_step3'),
]
diff --git a/idhub/user/forms.py b/idhub/user/forms.py
index 2293aac..a8f6997 100644
--- a/idhub/user/forms.py
+++ b/idhub/user/forms.py
@@ -1,5 +1,7 @@
from django import forms
-from django.contrib.auth.models import User
+from idhub_auth.models import User
+from idhub.models import DID, VerificableCredential, Organization
+
class ProfileForm(forms.ModelForm):
@@ -7,4 +9,86 @@ class ProfileForm(forms.ModelForm):
class Meta:
model = User
- fields = ('first_name', 'last_name', 'email')
\ No newline at end of file
+ fields = ('first_name', 'last_name', 'email')
+
+
+class RequestCredentialForm(forms.Form):
+ did = forms.ChoiceField(choices=[])
+ credential = forms.ChoiceField(choices=[])
+
+ def __init__(self, *args, **kwargs):
+ self.user = kwargs.pop('user', None)
+ super().__init__(*args, **kwargs)
+ self.fields['did'].choices = [
+ (x.did, x.label) for x in DID.objects.filter(user=self.user)
+ ]
+ self.fields['credential'].choices = [
+ (x.id, x.type()) for x in VerificableCredential.objects.filter(
+ user=self.user,
+ status=VerificableCredential.Status.ENABLED
+ )
+ ]
+
+ def save(self, commit=True):
+ did = DID.objects.filter(
+ user=self.user,
+ did=self.data['did']
+ )
+ cred = VerificableCredential.objects.filter(
+ user=self.user,
+ id=self.data['credential'],
+ status=VerificableCredential.Status.ENABLED
+ )
+ if not all([cred.exists(), did.exists()]):
+ return
+
+ did = did[0].did
+ cred = cred[0]
+ cred.get_issued(did)
+
+ if commit:
+ cred.save()
+ return cred
+
+ return
+
+
+
+class CredentialPresentationForm(forms.Form):
+ organization = forms.ChoiceField(choices=[])
+ credential = forms.ChoiceField(choices=[])
+
+ def __init__(self, *args, **kwargs):
+ self.user = kwargs.pop('user', None)
+ super().__init__(*args, **kwargs)
+ self.fields['organization'].choices = [
+ (x.id, x.name) for x in Organization.objects.filter()
+ ]
+ self.fields['credential'].choices = [
+ (x.id, x.type()) for x in VerificableCredential.objects.filter(
+ user=self.user,
+ status=VerificableCredential.Status.ISSUED
+ )
+ ]
+
+ def save(self, commit=True):
+ org = Organization.objects.filter(
+ id=self.data['organization']
+ )
+ cred = VerificableCredential.objects.filter(
+ user=self.user,
+ id=self.data['credential'],
+ status=VerificableCredential.Status.ISSUED
+ )
+ if not all([org.exists(), cred.exists()]):
+ return
+
+ org =org[0]
+ cred = cred[0]
+
+ if commit:
+ org.send(cred)
+ return cred
+
+ return
+
diff --git a/idhub/user/views.py b/idhub/user/views.py
index 95316ed..5071968 100644
--- a/idhub/user/views.py
+++ b/idhub/user/views.py
@@ -1,12 +1,21 @@
import logging
from django.utils.translation import gettext_lazy as _
-from django.views.generic.edit import UpdateView
+from django.views.generic.edit import (
+ UpdateView,
+ CreateView,
+ DeleteView,
+ FormView
+)
from django.views.generic.base import TemplateView
+from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse_lazy
+from django.http import HttpResponse
from django.contrib import messages
-from idhub.user.forms import ProfileForm
+from apiregiter import iota
+from idhub.user.forms import ProfileForm, RequestCredentialForm, CredentialPresentationForm
from idhub.mixins import UserView
+from idhub.models import DID, VerificableCredential
class MyProfile(UserView):
@@ -14,7 +23,7 @@ class MyProfile(UserView):
section = "MyProfile"
-class MyWallet(UserView, TemplateView):
+class MyWallet(UserView):
title = _("My Wallet")
section = "MyWallet"
@@ -51,25 +60,178 @@ class UserGDPRView(MyProfile, TemplateView):
icon = 'bi bi-file-earmark-medical'
-class UserIdentitiesView(MyWallet):
- template_name = "idhub/user/identities.html"
- subtitle = _('Identities (DID)')
- icon = 'bi bi-patch-check-fill'
-
-
-class UserCredentialsView(MyWallet):
+class UserCredentialsView(MyWallet, TemplateView):
template_name = "idhub/user/credentials.html"
subtitle = _('Credentials')
icon = 'bi bi-patch-check-fill'
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'credentials': VerificableCredential.objects,
+ })
+ return context
-class UserCredentialsRequiredView(MyWallet):
- template_name = "idhub/user/credentials_required.html"
- subtitle = _('Credentials required')
+
+class UserCredentialView(MyWallet, TemplateView):
+ 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)
-class UserCredentialsPresentationView(MyWallet):
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'object': self.object,
+ })
+ return context
+
+
+class UserCredentialJsonView(MyWallet, TemplateView):
+
+ 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
+
+
+class UserCredentialsRequestView(MyWallet, FormView):
+ template_name = "idhub/user/credentials_request.html"
+ subtitle = _('Credentials request')
+ icon = 'bi bi-patch-check-fill'
+ form_class = RequestCredentialForm
+ success_url = reverse_lazy('idhub:user_credentials')
+
+ 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:
+ messages.success(self.request, _("The credential was required successfully!"))
+ else:
+ messages.error(self.request, _("Not exists the credential!"))
+ return super().form_valid(form)
+
+
+class UserCredentialsPresentationView(MyWallet, FormView):
template_name = "idhub/user/credentials_presentation.html"
subtitle = _('Credentials Presentation')
icon = 'bi bi-patch-check-fill'
+ form_class = CredentialPresentationForm
+ success_url = reverse_lazy('idhub:user_credentials')
+
+ 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:
+ messages.success(self.request, _("The credential was presented successfully!"))
+ else:
+ messages.error(self.request, _("Error sending credential!"))
+ return super().form_valid(form)
+
+
+class UserDidsView(MyWallet, TemplateView):
+ template_name = "idhub/user/dids.html"
+ subtitle = _('Identities (DID)')
+ 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
+
+
+class UserDidRegisterView(MyWallet, CreateView):
+ template_name = "idhub/user/did_register.html"
+ subtitle = _('Add a new Identities (DID)')
+ icon = 'bi bi-patch-check-fill'
+ wallet = True
+ model = DID
+ fields = ('did', 'label')
+ success_url = reverse_lazy('idhub:user_dids')
+ object = None
+
+ def get_form_kwargs(self):
+ kwargs = super().get_form_kwargs()
+ kwargs['initial'] = {
+ 'did': iota.issue_did(),
+ 'user': self.request.user
+ }
+ return kwargs
+
+ def get_form(self):
+ form = super().get_form()
+ form.fields['did'].required = False
+ form.fields['did'].disabled = True
+ return form
+
+ def form_valid(self, form):
+ form.instance.user = self.request.user
+ form.save()
+ messages.success(self.request, _('DID created successfully'))
+ return super().form_valid(form)
+
+
+class UserDidEditView(MyWallet, UpdateView):
+ template_name = "idhub/user/did_register.html"
+ subtitle = _('Identities (DID)')
+ icon = 'bi bi-patch-check-fill'
+ wallet = True
+ model = DID
+ fields = ('did', 'label')
+ 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 get_form(self):
+ form = super().get_form()
+ form.fields['did'].required = False
+ form.fields['did'].disabled = True
+ return form
+
+ def form_valid(self, form):
+ user = form.save()
+ messages.success(self.request, _('DID updated successfully'))
+ return super().form_valid(form)
+
+
+class UserDidDeleteView(MyWallet, DeleteView):
+ subtitle = _('Identities (DID)')
+ 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)
+ self.object.delete()
+ messages.success(self.request, _('DID delete successfully'))
+
+ return redirect(self.success_url)
diff --git a/idhub_auth/__init__.py b/idhub_auth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/idhub_auth/admin.py b/idhub_auth/admin.py
new file mode 100644
index 0000000..cb7f452
--- /dev/null
+++ b/idhub_auth/admin.py
@@ -0,0 +1,7 @@
+from django.contrib import admin
+from django.contrib.auth import get_user_model
+
+
+User = get_user_model()
+
+admin.site.register(User)
diff --git a/idhub_auth/apps.py b/idhub_auth/apps.py
new file mode 100644
index 0000000..3439cf8
--- /dev/null
+++ b/idhub_auth/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class AuthConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'idhub_auth'
diff --git a/idhub_auth/migrations/0001_initial.py b/idhub_auth/migrations/0001_initial.py
new file mode 100644
index 0000000..2196067
--- /dev/null
+++ b/idhub_auth/migrations/0001_initial.py
@@ -0,0 +1,46 @@
+# Generated by Django 4.2.5 on 2023-11-02 15:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ initial = True
+
+ dependencies = []
+
+ operations = [
+ migrations.CreateModel(
+ name='User',
+ fields=[
+ (
+ 'id',
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name='ID',
+ ),
+ ),
+ ('password', models.CharField(max_length=128, verbose_name='password')),
+ (
+ 'last_login',
+ models.DateTimeField(
+ blank=True, null=True, verbose_name='last login'
+ ),
+ ),
+ (
+ 'email',
+ models.EmailField(
+ max_length=255, unique=True, verbose_name='email address'
+ ),
+ ),
+ ('is_active', models.BooleanField(default=True)),
+ ('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)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ ]
diff --git a/idhub_auth/migrations/__init__.py b/idhub_auth/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/idhub_auth/models.py b/idhub_auth/models.py
new file mode 100644
index 0000000..64f5491
--- /dev/null
+++ b/idhub_auth/models.py
@@ -0,0 +1,74 @@
+from django.db import models
+from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
+
+
+class UserManager(BaseUserManager):
+ def create_user(self, email, password=None):
+ """
+ Creates and saves a User with the given email, date of
+ birth and password.
+ """
+ if not email:
+ raise ValueError("Users must have an email address")
+
+ user = self.model(
+ email=self.normalize_email(email),
+ )
+
+ user.set_password(password)
+ user.save(using=self._db)
+ return user
+
+ def create_superuser(self, email, password=None):
+ """
+ Creates and saves a superuser with the given email, date of
+ birth and password.
+ """
+ user = self.create_user(
+ email,
+ password=password,
+ )
+ user.is_admin = True
+ user.save(using=self._db)
+ return user
+
+
+class User(AbstractBaseUser):
+ email = models.EmailField(
+ verbose_name="email address",
+ max_length=255,
+ unique=True,
+ )
+ is_active = models.BooleanField(default=True)
+ is_admin = models.BooleanField(default=False)
+ first_name = models.CharField(max_length=255, blank=True, null=True)
+ last_name = models.CharField(max_length=255, blank=True, null=True)
+
+ objects = UserManager()
+
+ USERNAME_FIELD = "email"
+ REQUIRED_FIELDS = []
+
+ def __str__(self):
+ return self.email
+
+ def has_perm(self, perm, obj=None):
+ "Does the user have a specific permission?"
+ # Simplest possible answer: Yes, always
+ return True
+
+ def has_module_perms(self, app_label):
+ "Does the user have permissions to view the app `app_label`?"
+ # Simplest possible answer: Yes, always
+ return True
+
+ @property
+ def is_staff(self):
+ "Is the user a member of staff?"
+ # Simplest possible answer: All admins are staff
+ return self.is_admin
+
+ @property
+ def username(self):
+ "Is the email of the user"
+ return self.email
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..e3b8acf
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,6 @@
+[tool.black]
+skip-string-normalization = true
+target-version = ['py311']
+
+[tool.isort]
+profile = "black"
diff --git a/requirements.txt b/requirements.txt
index b1a0f3f..4281ff1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,3 +3,7 @@ django-bootstrap5==23.3
django-extensions==3.2.3
black==23.9.1
python-decouple==3.8
+jsonschema==4.19.1
+pandas==2.1.1
+requests==2.31.0
+
diff --git a/schemas/member-schema.json b/schemas/member-schema.json
new file mode 100644
index 0000000..38199be
--- /dev/null
+++ b/schemas/member-schema.json
@@ -0,0 +1,21 @@
+ {
+ "$id": "https://pangea.org/schemas/member-credential-schema.json",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "name": "MemberCredential",
+ "description": "MemberCredential using JsonSchemaCredential",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "email": {
+ "type": "string",
+ "format": "email"
+ },
+ "membershipType": {
+ "type": "string",
+ "enum": ["individual", "organization"]
+ }
+ },
+ "required": ["name", "email", "membershipType"]
+ }
diff --git a/schemas/member.json b/schemas/member.json
new file mode 100644
index 0000000..845ab50
--- /dev/null
+++ b/schemas/member.json
@@ -0,0 +1,40 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://www.w3.org/ns/credentials/examples/v2"
+ ],
+ "id": "https://example.com/credentials/3734",
+ "type": ["VerifiableCredential", "JsonSchemaCredential"],
+ "issuer": "https://pangea.org/issuers/10",
+ "issuanceDate": "2023-09-01T19:23:24Z",
+ "credentialSchema": {
+ "id": "https://www.w3.org/2022/credentials/v2/json-schema-credential-schema.json",
+ "type": "JsonSchema",
+ "digestSRI": "sha384-S57yQDg1MTzF56Oi9DbSQ14u7jBy0RDdx0YbeV7shwhCS88G8SCXeFq82PafhCrW"
+ },
+ "credentialSubject": {
+ "id": "https://pangea.org/schemas/member-credential-schema.json",
+ "type": "JsonSchema",
+ "jsonSchema": {
+ "$id": "https://pangea.org/schemas/member-credential-schema.json",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "name": "MemberCredential",
+ "description": "MemberCredential using JsonSchemaCredential",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "email": {
+ "type": "string",
+ "format": "email"
+ },
+ "membershipType": {
+ "type": "string",
+ "enum": ["individual", "organization"]
+ }
+ },
+ "required": ["name", "email", "membershipType"]
+ }
+ }
+}
diff --git a/trustchain_idhub/settings.py b/trustchain_idhub/settings.py
index d00dea2..93ad79b 100644
--- a/trustchain_idhub/settings.py
+++ b/trustchain_idhub/settings.py
@@ -70,6 +70,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'django_extensions',
'django_bootstrap5',
+ 'idhub_auth',
'idhub'
]
@@ -160,6 +161,7 @@ MEDIA_URL = '/media/'
STATIC_ROOT = config('STATIC_ROOT')
MEDIA_ROOT = config('MEDIA_ROOT', default="idhub/upload")
FIXTURE_DIRS = (os.path.join(BASE_DIR, 'fixtures'),)
+SCHEMAS_DIR = os.path.join(BASE_DIR, 'schemas')
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
@@ -176,3 +178,4 @@ MESSAGE_TAGS = {
messages.ERROR: 'alert-danger',
}
+AUTH_USER_MODEL = 'idhub_auth.User'
|