Merge pull request 'feature/templates' (#71) from feature/templates into main
Reviewed-on: https://gitea.pangea.org/trustchain-oc1-orchestral/IdHub/pulls/71
This commit is contained in:
commit
b32c0b8e20
|
@ -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()
|
|
@ -0,0 +1,2 @@
|
||||||
|
name email membershipType
|
||||||
|
Pepe user1@example.org individual
|
|
|
@ -1,5 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
from .models import AppUser
|
|
||||||
|
|
||||||
admin.site.register(AppUser)
|
|
|
@ -1,27 +1,9 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from idhub.models import Rol
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileForm(forms.ModelForm):
|
class ImportForm(forms.Form):
|
||||||
MANDATORY_FIELDS = ['first_name', 'last_name', 'email', 'username']
|
file_import = forms.FileField()
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = User
|
|
||||||
fields = ('first_name', 'last_name', 'email')
|
|
||||||
|
|
||||||
|
|
||||||
class MembershipForm(forms.ModelForm):
|
class SchemaForm(forms.Form):
|
||||||
MANDATORY_FIELDS = ['type']
|
file_template = forms.FileField()
|
||||||
|
|
||||||
|
|
||||||
class RolForm(forms.ModelForm):
|
|
||||||
MANDATORY_FIELDS = ['name']
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceForm(forms.ModelForm):
|
|
||||||
MANDATORY_FIELDS = ['domain', 'rol']
|
|
||||||
|
|
||||||
|
|
||||||
class UserRolForm(forms.ModelForm):
|
|
||||||
MANDATORY_FIELDS = ['service']
|
|
||||||
|
|
|
@ -1,22 +1,35 @@
|
||||||
|
import os
|
||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import copy
|
||||||
import logging
|
import logging
|
||||||
|
import pandas as pd
|
||||||
|
from pathlib import Path
|
||||||
|
from jsonschema import validate
|
||||||
from smtplib import SMTPException
|
from smtplib import SMTPException
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.views.generic.edit import UpdateView, CreateView
|
from django.views.generic.edit import UpdateView, CreateView, DeleteView
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.http import HttpResponse
|
||||||
from django.contrib import messages
|
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.mixins import AdminView
|
||||||
from idhub.email.views import NotifyActivateUserByEmail
|
from idhub.email.views import NotifyActivateUserByEmail
|
||||||
from idhub.admin.forms import (
|
from idhub.admin.forms import ImportForm, SchemaForm
|
||||||
ProfileForm,
|
from idhub.models import (
|
||||||
MembershipForm,
|
DID,
|
||||||
RolForm,
|
File_datas,
|
||||||
ServiceForm,
|
Membership,
|
||||||
UserRolForm
|
Rol,
|
||||||
|
Service,
|
||||||
|
Schemas,
|
||||||
|
UserRol,
|
||||||
|
VerificableCredential,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,9 +55,9 @@ class Credentials(AdminView, TemplateView):
|
||||||
section = "Credentials"
|
section = "Credentials"
|
||||||
|
|
||||||
|
|
||||||
class Schemes(AdminView, TemplateView):
|
class SchemasMix(AdminView, TemplateView):
|
||||||
title = _("Schemes Management")
|
title = _("Templates Management")
|
||||||
section = "Schemes"
|
section = "Templates"
|
||||||
|
|
||||||
|
|
||||||
class ImportExport(AdminView, TemplateView):
|
class ImportExport(AdminView, TemplateView):
|
||||||
|
@ -118,8 +131,7 @@ class AdminPeopleDeleteView(AdminPeopleView):
|
||||||
|
|
||||||
class AdminPeopleEditView(AdminPeopleView, UpdateView):
|
class AdminPeopleEditView(AdminPeopleView, UpdateView):
|
||||||
template_name = "idhub/admin/user_edit.html"
|
template_name = "idhub/admin/user_edit.html"
|
||||||
from_class = ProfileForm
|
fields = ('first_name', 'last_name', 'email')
|
||||||
fields = ('first_name', 'last_name', 'email', 'username')
|
|
||||||
success_url = reverse_lazy('idhub:admin_people_list')
|
success_url = reverse_lazy('idhub:admin_people_list')
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,8 +140,7 @@ class AdminPeopleRegisterView(NotifyActivateUserByEmail, People, CreateView):
|
||||||
subtitle = _('People Register')
|
subtitle = _('People Register')
|
||||||
icon = 'bi bi-person'
|
icon = 'bi bi-person'
|
||||||
model = User
|
model = User
|
||||||
from_class = ProfileForm
|
fields = ('first_name', 'last_name', 'email')
|
||||||
fields = ('first_name', 'last_name', 'email', 'username')
|
|
||||||
success_url = reverse_lazy('idhub:admin_people_list')
|
success_url = reverse_lazy('idhub:admin_people_list')
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
@ -155,7 +166,6 @@ class AdminPeopleMembershipRegisterView(People, CreateView):
|
||||||
subtitle = _('People add membership')
|
subtitle = _('People add membership')
|
||||||
icon = 'bi bi-person'
|
icon = 'bi bi-person'
|
||||||
model = Membership
|
model = Membership
|
||||||
from_class = MembershipForm
|
|
||||||
fields = ('type', 'start_date', 'end_date')
|
fields = ('type', 'start_date', 'end_date')
|
||||||
success_url = reverse_lazy('idhub:admin_people_list')
|
success_url = reverse_lazy('idhub:admin_people_list')
|
||||||
|
|
||||||
|
@ -193,7 +203,6 @@ class AdminPeopleMembershipEditView(People, CreateView):
|
||||||
subtitle = _('People add membership')
|
subtitle = _('People add membership')
|
||||||
icon = 'bi bi-person'
|
icon = 'bi bi-person'
|
||||||
model = Membership
|
model = Membership
|
||||||
from_class = MembershipForm
|
|
||||||
fields = ('type', 'start_date', 'end_date')
|
fields = ('type', 'start_date', 'end_date')
|
||||||
success_url = reverse_lazy('idhub:admin_people_list')
|
success_url = reverse_lazy('idhub:admin_people_list')
|
||||||
|
|
||||||
|
@ -232,7 +241,6 @@ class AdminPeopleRolRegisterView(People, CreateView):
|
||||||
subtitle = _('Add Rol to User')
|
subtitle = _('Add Rol to User')
|
||||||
icon = 'bi bi-person'
|
icon = 'bi bi-person'
|
||||||
model = UserRol
|
model = UserRol
|
||||||
from_class = UserRolForm
|
|
||||||
fields = ('service',)
|
fields = ('service',)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
@ -263,7 +271,6 @@ class AdminPeopleRolEditView(People, CreateView):
|
||||||
subtitle = _('Edit Rol to User')
|
subtitle = _('Edit Rol to User')
|
||||||
icon = 'bi bi-person'
|
icon = 'bi bi-person'
|
||||||
model = UserRol
|
model = UserRol
|
||||||
from_class = UserRolForm
|
|
||||||
fields = ('service',)
|
fields = ('service',)
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
|
@ -311,7 +318,6 @@ class AdminRolRegisterView(AccessControl, CreateView):
|
||||||
subtitle = _('Add Rol')
|
subtitle = _('Add Rol')
|
||||||
icon = ''
|
icon = ''
|
||||||
model = Rol
|
model = Rol
|
||||||
from_class = RolForm
|
|
||||||
fields = ('name',)
|
fields = ('name',)
|
||||||
success_url = reverse_lazy('idhub:admin_roles')
|
success_url = reverse_lazy('idhub:admin_roles')
|
||||||
object = None
|
object = None
|
||||||
|
@ -322,7 +328,6 @@ class AdminRolEditView(AccessControl, CreateView):
|
||||||
subtitle = _('Edit Rol')
|
subtitle = _('Edit Rol')
|
||||||
icon = ''
|
icon = ''
|
||||||
model = Rol
|
model = Rol
|
||||||
from_class = RolForm
|
|
||||||
fields = ('name',)
|
fields = ('name',)
|
||||||
success_url = reverse_lazy('idhub:admin_roles')
|
success_url = reverse_lazy('idhub:admin_roles')
|
||||||
|
|
||||||
|
@ -362,7 +367,6 @@ class AdminServiceRegisterView(AccessControl, CreateView):
|
||||||
subtitle = _('Add Service')
|
subtitle = _('Add Service')
|
||||||
icon = ''
|
icon = ''
|
||||||
model = Service
|
model = Service
|
||||||
from_class = ServiceForm
|
|
||||||
fields = ('domain', 'description', 'rol')
|
fields = ('domain', 'description', 'rol')
|
||||||
success_url = reverse_lazy('idhub:admin_services')
|
success_url = reverse_lazy('idhub:admin_services')
|
||||||
object = None
|
object = None
|
||||||
|
@ -373,7 +377,6 @@ class AdminServiceEditView(AccessControl, CreateView):
|
||||||
subtitle = _('Edit Service')
|
subtitle = _('Edit Service')
|
||||||
icon = ''
|
icon = ''
|
||||||
model = Service
|
model = Service
|
||||||
from_class = ServiceForm
|
|
||||||
fields = ('domain', 'description', 'rol')
|
fields = ('domain', 'description', 'rol')
|
||||||
success_url = reverse_lazy('idhub:admin_services')
|
success_url = reverse_lazy('idhub:admin_services')
|
||||||
|
|
||||||
|
@ -401,11 +404,31 @@ class AdminCredentialsView(Credentials):
|
||||||
subtitle = _('Credentials list')
|
subtitle = _('Credentials list')
|
||||||
icon = ''
|
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"
|
template_name = "idhub/admin/issue_credentials.html"
|
||||||
subtitle = _('Issuance of Credentials')
|
subtitle = _('Change status of Credential')
|
||||||
icon = ''
|
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):
|
class AdminRevokeCredentialsView(Credentials):
|
||||||
|
@ -414,12 +437,89 @@ class AdminRevokeCredentialsView(Credentials):
|
||||||
icon = ''
|
icon = ''
|
||||||
|
|
||||||
|
|
||||||
class AdminWalletIdentitiesView(Credentials):
|
class AdminDidsView(Credentials):
|
||||||
template_name = "idhub/admin/wallet_identities.html"
|
template_name = "idhub/admin/dids.html"
|
||||||
subtitle = _('Organization Identities (DID)')
|
subtitle = _('Organization Identities (DID)')
|
||||||
icon = 'bi bi-patch-check-fill'
|
icon = 'bi bi-patch-check-fill'
|
||||||
wallet = True
|
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):
|
class AdminWalletCredentialsView(Credentials):
|
||||||
template_name = "idhub/admin/wallet_credentials.html"
|
template_name = "idhub/admin/wallet_credentials.html"
|
||||||
|
@ -435,22 +535,136 @@ class AdminWalletConfigIssuesView(Credentials):
|
||||||
wallet = True
|
wallet = True
|
||||||
|
|
||||||
|
|
||||||
class AdminSchemesView(Schemes):
|
class AdminSchemasView(SchemasMix):
|
||||||
template_name = "idhub/admin/schemes.html"
|
template_name = "idhub/admin/schemas.html"
|
||||||
subtitle = _('Schemes List')
|
subtitle = _('Template List')
|
||||||
icon = ''
|
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"
|
class AdminSchemasDeleteView(SchemasMix):
|
||||||
subtitle = _('Import Schemes')
|
|
||||||
|
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 = ''
|
icon = ''
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({
|
||||||
|
'schemas': self.get_schemas(),
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
class AdminSchemesExportView(Schemes):
|
def get_schemas(self):
|
||||||
template_name = "idhub/admin/schemes_export.html"
|
schemas_files = os.listdir(settings.SCHEMAS_DIR)
|
||||||
subtitle = _('Export Schemes')
|
schemas = [x for x in schemas_files
|
||||||
icon = ''
|
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):
|
class AdminImportView(ImportExport):
|
||||||
|
@ -458,8 +672,114 @@ class AdminImportView(ImportExport):
|
||||||
subtitle = _('Import')
|
subtitle = _('Import')
|
||||||
icon = ''
|
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"
|
class AdminImportStep2View(ImportExport):
|
||||||
subtitle = _('Export')
|
template_name = "idhub/admin/import_step2.html"
|
||||||
|
subtitle = _('Import')
|
||||||
icon = ''
|
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)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -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.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -14,115 +14,247 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="VCTemplate",
|
name='File_datas',
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
'id',
|
||||||
models.BigAutoField(
|
models.BigAutoField(
|
||||||
auto_created=True,
|
auto_created=True,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False,
|
serialize=False,
|
||||||
verbose_name="ID",
|
verbose_name='ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("wkit_template_id", models.CharField(max_length=250)),
|
('file_name', models.CharField(max_length=250)),
|
||||||
("data", models.TextField()),
|
('success', models.BooleanField(default=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now=True)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="VerifiableCredential",
|
name='Organization',
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
'id',
|
||||||
models.BigAutoField(
|
models.BigAutoField(
|
||||||
auto_created=True,
|
auto_created=True,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False,
|
serialize=False,
|
||||||
verbose_name="ID",
|
verbose_name='ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("id_string", models.CharField(max_length=250)),
|
('name', 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()),
|
|
||||||
(
|
(
|
||||||
"user",
|
'url',
|
||||||
models.ForeignKey(
|
models.CharField(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
help_text='Url where to send the presentation', max_length=250
|
||||||
related_name="vcredentials",
|
|
||||||
to=settings.AUTH_USER_MODEL,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Membership",
|
name='Rol',
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
'id',
|
||||||
models.BigAutoField(
|
models.BigAutoField(
|
||||||
auto_created=True,
|
auto_created=True,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False,
|
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(
|
models.PositiveSmallIntegerField(
|
||||||
choices=[(1, "Beneficiary"), (2, "Employee"), (3, "Partner")],
|
choices=[
|
||||||
verbose_name="Type of membership",
|
(1, 'Enabled'),
|
||||||
|
(2, 'Issued'),
|
||||||
|
(3, 'Revoked'),
|
||||||
|
(4, 'Expired'),
|
||||||
|
],
|
||||||
|
default=1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"start_date",
|
'user',
|
||||||
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(
|
models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
related_name="memberships",
|
related_name='vcredentials',
|
||||||
to=settings.AUTH_USER_MODEL,
|
to=settings.AUTH_USER_MODEL,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="DID",
|
name='UserRol',
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
'id',
|
||||||
models.BigAutoField(
|
models.BigAutoField(
|
||||||
auto_created=True,
|
auto_created=True,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False,
|
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(
|
models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
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,
|
to=settings.AUTH_USER_MODEL,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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"),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -26,7 +26,7 @@ class UserView(LoginRequiredMixin):
|
||||||
class AdminView(UserView):
|
class AdminView(UserView):
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if not request.user.is_superuser:
|
if not request.user.is_admin:
|
||||||
url = reverse_lazy('idhub:user_dashboard')
|
url = reverse_lazy('idhub:user_dashboard')
|
||||||
return redirect(url)
|
return redirect(url)
|
||||||
|
|
||||||
|
|
106
idhub/models.py
106
idhub/models.py
|
@ -1,15 +1,8 @@
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.contrib.auth.models import User
|
from idhub_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
|
|
||||||
|
|
||||||
|
|
||||||
# class Event(models.Model):
|
# class Event(models.Model):
|
||||||
|
@ -20,35 +13,103 @@ from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
class DID(models.Model):
|
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)
|
label = models.CharField(max_length=50)
|
||||||
user = models.ForeignKey(
|
user = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='dids',
|
related_name='dids',
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
# kind = "KEY|WEB"
|
# 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)
|
id_string = models.CharField(max_length=250)
|
||||||
verified = models.BooleanField()
|
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_issuer = models.CharField(max_length=250)
|
||||||
did_subject = 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 = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='vcredentials',
|
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):
|
class VCTemplate(models.Model):
|
||||||
wkit_template_id = models.CharField(max_length=250)
|
wkit_template_id = models.CharField(max_length=250)
|
||||||
data = models.TextField()
|
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):
|
class Membership(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represent the relation of this user with the ecosystem.
|
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()])
|
return ", ".join([x.name for x in self.rol.all()])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{} -> {}".format(self.domain, self.rol.name)
|
return "{} -> {}".format(self.domain, self.get_roles())
|
||||||
|
|
||||||
|
|
||||||
class UserRol(models.Model):
|
class UserRol(models.Model):
|
||||||
|
@ -114,3 +175,18 @@ class UserRol(models.Model):
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='users',
|
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)
|
|
@ -6,4 +6,34 @@
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Type' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Details' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Issue' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Status' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'User' %}</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for f in credentials.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ f.type }}</td>
|
||||||
|
<td>{{ f.description }}</td>
|
||||||
|
<td>{{ f.issue_on }}</td>
|
||||||
|
<td>{{ f.get_status }}</td>
|
||||||
|
<td>{{ f.user.email }}</td>
|
||||||
|
<td><a href="{% url 'idhub:admin_credential' f.id %}" class="btn btn-green-admin">{% trans 'View' %}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'idhub:admin_dids' %}">{% translate "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,60 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Date' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Label' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">ID</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for d in dids.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ d.created_at }}</td>
|
||||||
|
<td>{{ d.label }}</td>
|
||||||
|
<td>{{ d.did }}</td>
|
||||||
|
<td><a class="text-primary" href="{% url 'idhub:admin_dids_edit' d.id %}" title="{% trans 'Edit' %}"><i class="bi bi-pencil-square"></i></a></td>
|
||||||
|
<td><a class="text-danger" href="jacascript:void()" data-bs-toggle="modal" data-bs-target="#confirm-delete-{{ d.id }}" title="{% trans 'Remove' %}"><i class="bi bi-x-circle"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_dids_new' %}">{% translate "Add Identity" %} <i class="bi bi-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
{% for d in dids.all %}
|
||||||
|
<div class="modal" id="confirm-delete-{{ d.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">{% trans 'Delete DID' %} {{ d.did }}</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% trans 'Are you sure that you want delete this DID?' %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Clancel</button>
|
||||||
|
<a href="{% url 'idhub:admin_dids_del' d.id %}" type="button" class="btn btn-danger">{% trans 'Delete' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
|
@ -6,4 +6,31 @@
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Created at' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'File' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'success' %}</button></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for f in dates.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ f.created_at }}</td>
|
||||||
|
<td>{{ f.file_name }}</td>
|
||||||
|
<td>{% if f.success %}<i class="bi bi-check-circle text-primary"></i>{% else %}<i class="bi bi-x-circle text-danger"></i>{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_import_step2' %}">{% translate "Import Datas" %} <i class="bi bi-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Created at' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Template file' %}</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for schema in schemas.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ schema.created_at }}</td>
|
||||||
|
<td>{{ schema.file_schema }}</td>
|
||||||
|
<td><a class="btn btn-green-admin" href="{% url 'idhub:admin_import_step3' schema.id %}" title="{% trans 'Import Dates' %}">{% trans 'Import Dates' %}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
<button class="close" type="button" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span class="mdi mdi-close" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'idhub:admin_import' %}">{% translate "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -2,8 +2,55 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col text-end">
|
||||||
|
{% if object.get_status == 'Issued' %}
|
||||||
|
<a class="btn btn-yellow" href="{% url 'idhub:user_credential_json' object.id %}">{% trans 'Revoke' %}</a>
|
||||||
|
<a class="btn btn-orange" href="{% url 'idhub:user_credential_json' object.id %}">{% trans 'Delete' %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-3">
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{% for k, v in object.get_datas %}
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3 text-end">
|
||||||
|
<strong>{{ k|capfirst }}:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col bg-light text-secondary">
|
||||||
|
{{ v }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3 text-end">
|
||||||
|
<strong>Date of Issue:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col bg-light text-secondary">
|
||||||
|
{{ object.issuer_on|default_if_none:"" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3 text-end">
|
||||||
|
<strong>Status:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col bg-light text-secondary">
|
||||||
|
{{ object.get_status}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col text-center">
|
||||||
|
<a class="btn btn-green-user" href="{% url 'idhub:user_credential_json' object.id %}">{% trans 'View in JSON format' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"><button type="button" class="btn btn-green-admin border border-dark">{% trans 'Last name' %}</button></th>
|
<th scope="col"><button type="button" class="btn btn-green-admin border border-dark">{% trans 'Last name' %}</button></th>
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'First name' %}</button></th>
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'First name' %}</button></th>
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">Username</button></th>
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">Email</button></th>
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Membership' %}</button></th>
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Membership' %}</button></th>
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Role' %}</button></th>
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Role' %}</button></th>
|
||||||
<th scope="col"></th>
|
<th scope="col"></th>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ user.last_name }}</td>
|
<td>{{ user.last_name }}</td>
|
||||||
<td>{{ user.first_name }}</td>
|
<td>{{ user.first_name }}</td>
|
||||||
<td>{{ user.username }}</td>
|
<td>{{ user.email }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% for m in user.memberships.all %}
|
{% for m in user.memberships.all %}
|
||||||
{{ m.get_type }}
|
{{ m.get_type }}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Created at' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Template file' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Name' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Description' %}</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for schema in schemas.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ schema.created_at }}</td>
|
||||||
|
<td>{{ schema.file_schema }}</td>
|
||||||
|
<td>{{ schema.name }}</td>
|
||||||
|
<td>{{ schema.description }}</td>
|
||||||
|
<td><a class="btn btn-green-admin" href="{% url 'idhub:admin_schemas_download' schema.id %}" target="_blank" title="{% trans 'View' %}">{% trans 'View' %}</a></td>
|
||||||
|
<td><a class="text-danger" href="jacascript:void()" data-bs-toggle="modal" data-bs-target="#confirm-delete-{{ schema.id }}" title="{% trans 'Remove' %}"><i class="bi bi-x-circle"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_schemas_import' %}">{% translate "Add Template" %} <i class="bi bi-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
{% for schema in schemas.all %}
|
||||||
|
<div class="modal" id="confirm-delete-{{ schema.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">{% trans 'Delete Template' %} {{ schema.file_schema }}</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% trans 'Are you sure that you want delete this template?' %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Clancel</button>
|
||||||
|
<a href="{% url 'idhub:admin_schemas_del' schema.id %}" type="button" class="btn btn-danger">{% trans 'Delete' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Template available' %}</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for schema in schemas %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ schema }}</td>
|
||||||
|
<td><a class="text-primary" href="{% url 'idhub:admin_schemas_import_add' schema %}" title="{% trans 'Add' %}"><i class="bi bi-plus-circle"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_schemas_new' %}">{% translate "Add template" %} <i class="bi bi-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{% extends "idhub/base_admin.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
<button class="close" type="button" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span class="mdi mdi-close" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'idhub:admin_schemas_import' %}">{% translate "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -1,9 +0,0 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h3>
|
|
||||||
<i class="{{ icon }}"></i>
|
|
||||||
{{ subtitle }}
|
|
||||||
</h3>
|
|
||||||
{% endblock %}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h3>
|
|
||||||
<i class="{{ icon }}"></i>
|
|
||||||
{{ subtitle }}
|
|
||||||
</h3>
|
|
||||||
{% endblock %}
|
|
|
@ -109,7 +109,7 @@
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="exampleModalLabel">{% trans 'Delete user' %} {{ object.username }}</h5>
|
<h5 class="modal-title" id="exampleModalLabel">{% trans 'Delete user' %} {{ object.email }}</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h3>
|
|
||||||
<i class="{{ icon }}"></i>
|
|
||||||
{{ subtitle }}
|
|
||||||
</h3>
|
|
||||||
{% endblock %}
|
|
|
@ -100,7 +100,7 @@
|
||||||
</span>
|
</span>
|
||||||
<ul class="flex-column mb-2 ul_sidebar">
|
<ul class="flex-column mb-2 ul_sidebar">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {% if path == 'user_identities' %}active2{% endif %}" href="{% url 'idhub:user_identities' %}">
|
<a class="nav-link {% if path == 'user_dids' %}active2{% endif %}" href="{% url 'idhub:user_dids' %}">
|
||||||
Identities (DID)
|
Identities (DID)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -110,8 +110,8 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {% if path == 'user_credentials_required' %}active2{% endif %}" href="{% url 'idhub:user_credentials_required' %}">
|
<a class="nav-link {% if path == 'user_credentials_request' %}active2{% endif %}" href="{% url 'idhub:user_credentials_request' %}">
|
||||||
Credentials required
|
Credentials request
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
@ -144,10 +144,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>
|
|
||||||
<i class="{{ icon }}"></i>
|
|
||||||
{{ subtitle }}
|
|
||||||
</h3>
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|
|
@ -117,23 +117,13 @@
|
||||||
Credentials list
|
Credentials list
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if path == 'admin_credentials_new' %} active2{% endif %}" href="{% url 'idhub:admin_credentials_new' %}">
|
|
||||||
Issue credentials
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if path == 'admin_credentials_revoke' %} active2{% endif %}" href="{% url 'idhub:admin_credentials_revoke' %}">
|
|
||||||
Revoke Credentials
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a id="wallet" class="nav-link" data-bs-toggle="collapse" data-bs-target="#lwallet" aria-expanded="false" aria-controls="lwallet" href="javascript:void()">
|
<a id="wallet" class="nav-link" data-bs-toggle="collapse" data-bs-target="#lwallet" aria-expanded="false" aria-controls="lwallet" href="javascript:void()">
|
||||||
Wallet
|
Wallet
|
||||||
</a>
|
</a>
|
||||||
<ul class="flex-column mb-2 accordion-collapse {% if wallet %}expanded{% else %}collapse{% endif %}" id="lwallet" data-bs-parent="#wallet">
|
<ul class="flex-column mb-2 accordion-collapse {% if wallet %}expanded{% else %}collapse{% endif %}" id="lwallet" data-bs-parent="#wallet">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link{% if path == 'admin_wallet_identities' %} active2{% endif %}" href="{% url 'idhub:admin_wallet_identities' %}">
|
<a class="nav-link{% if path == 'admin_dids' %} active2{% endif %}" href="{% url 'idhub:admin_dids' %}">
|
||||||
Identities (DID)
|
Identities (DID)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -152,45 +142,16 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="admin nav-link {% if section == 'Schemes' %}active {% endif %}fw-bold" data-bs-toggle="collapse" data-bs-target="#schemes" aria-expanded="false" aria-controls="schemes" href="javascript:void()">
|
<a class="admin nav-link {% if section == 'Templates' %}active {% endif %}fw-bold" href="{% url 'idhub:admin_schemas' %}">
|
||||||
<i class="bi bi-file-earmark-text icon_sidebar"></i>
|
<i class="bi bi-file-earmark-text icon_sidebar"></i>
|
||||||
Schemes
|
Templates
|
||||||
</a>
|
|
||||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'Schemes' %}expanded{% else %}collapse{% endif %}" id="schemes" data-bs-parent="#sidebarMenu">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if path == 'admin_schemes' %} active2{% endif %}" href="{% url 'idhub:admin_schemes' %}">
|
|
||||||
List of schemes
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link{% if path == 'admin_schemes_import' %} active2{% endif %}" href="{% url 'idhub:admin_schemes_import' %}">
|
<a class="admin nav-link {% if section == 'ImportExport' %}active {% endif %}fw-bold" href="{% url 'idhub:admin_import' %}">
|
||||||
Import scheme
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if path == 'admin_schemes_export' %} active2{% endif %}" href="{% url 'idhub:admin_schemes_export' %}">
|
|
||||||
Export scheme
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="admin nav-link {% if section == 'ImportExport' %}active {% endif %}fw-bold" data-bs-toggle="collapse" data-bs-target="#import-export" aria-expanded="false" aria-controls="import-export" href="javascript:void()">
|
|
||||||
<i class="bi bi-arrow-down-square icon_sidebar"></i>
|
<i class="bi bi-arrow-down-square icon_sidebar"></i>
|
||||||
Imports/Exports
|
Import Datas
|
||||||
</a>
|
</a>
|
||||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'ImportExport' %}expanded{% else %}collapse{% endif %}" id="import-export" data-bs-parent="#sidebarMenu">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if path == 'admin_import' %} active2{% endif %}" href="{% url 'idhub:admin_import' %}">
|
|
||||||
Import
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if path == 'admin_export' %} active2{% endif %}" href="{% url 'idhub:admin_export' %}">
|
|
||||||
Export
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
{% extends "idhub/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-3">
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{% for k, v in object.get_datas %}
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3 text-end">
|
||||||
|
<strong>{{ k|capfirst }}:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col bg-light text-secondary">
|
||||||
|
{{ v }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3 text-end">
|
||||||
|
<strong>Date of Issue:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col bg-light text-secondary">
|
||||||
|
{{ object.issuer_on|default_if_none:"" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3 text-end">
|
||||||
|
<strong>Status:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col bg-light text-secondary">
|
||||||
|
{{ object.get_status}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col text-center">
|
||||||
|
<a class="btn btn-green-user" href="{% url 'idhub:user_credential_json' object.id %}">{% trans 'View in JSON format' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -2,4 +2,40 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Type' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Details' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Issue' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Status' %}</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for f in credentials.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ f.type }}</td>
|
||||||
|
<td>{{ f.description }}</td>
|
||||||
|
<td>{{ f.issue_on }}</td>
|
||||||
|
<td>{{ f.get_status }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'idhub:user_credential' f.id %}" class="text-primary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2,4 +2,33 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'idhub:user_credentials' %}">{% trans "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-user" type="submit" name="submit" value="{% trans 'Send' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "idhub/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'idhub:user_credentials' %}">{% trans "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-user" type="submit" name="submit" value="{% trans 'Request' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -1,5 +0,0 @@
|
||||||
{% extends "idhub/base.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% endblock %}
|
|
|
@ -2,6 +2,10 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-striped table-sm">
|
<table class="table table-striped table-sm">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "idhub/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'idhub:user_dids' %}">{% trans "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-admin" type="submit" name="submit" value="{% trans 'Save' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,60 @@
|
||||||
|
{% extends "idhub/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Date' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Label' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">ID</button></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for d in dids.all %}
|
||||||
|
<tr style="font-size:15px;">
|
||||||
|
<td>{{ d.created_at }}</td>
|
||||||
|
<td>{{ d.label }}</td>
|
||||||
|
<td>{{ d.did }}</td>
|
||||||
|
<td><a class="text-primary" href="{% url 'idhub:user_dids_edit' d.id %}" title="{% trans 'Edit' %}"><i class="bi bi-pencil-square"></i></a></td>
|
||||||
|
<td><a class="text-danger" href="jacascript:void()" data-bs-toggle="modal" data-bs-target="#confirm-delete-{{ d.id }}" title="{% trans 'Remove' %}"><i class="bi bi-x-circle"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-green-user" href="{% url 'idhub:user_dids_new' %}">{% translate "Add Identity" %} <i class="bi bi-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
{% for d in dids.all %}
|
||||||
|
<div class="modal" id="confirm-delete-{{ d.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">{% trans 'Delete DID' %} {{ d.did }}</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% trans 'Are you sure that you want delete this DID?' %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Clancel</button>
|
||||||
|
<a href="{% url 'idhub:user_dids_del' d.id %}" type="button" class="btn btn-danger">{% trans 'Delete' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
|
@ -2,4 +2,8 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{% extends "idhub/base.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% endblock %}
|
|
|
@ -2,6 +2,18 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col text-center">
|
||||||
|
<a href="javascript:void()" type="button" class="btn btn-green-user me-3">{% trans 'ARCO Forms' %}</a>
|
||||||
|
<a href="javascript:void()" type="button" class="btn btn-green-user">{% trans 'Notice of Privacy' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% load django_bootstrap5 %}
|
{% load django_bootstrap5 %}
|
||||||
<form role="form" method="post">
|
<form role="form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
@ -25,4 +37,36 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm text-center">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Membership' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'From' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'To' %}</button></th>
|
||||||
|
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Credentials' %}</button></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for membership in object.memberships.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ membership.get_type }}</td>
|
||||||
|
<td>{{ membership.start_date|default:'' }}</td>
|
||||||
|
<td>{{ membership.end_date|default:'' }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="javascript:void()" class="text-primary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<h3>
|
||||||
|
<i class="{{ icon }}"></i>
|
||||||
|
{{ subtitle }}
|
||||||
|
</h3>
|
||||||
<div class="row mt-5">
|
<div class="row mt-5">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
@ -16,7 +20,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for rol in user.roles.all %}
|
{% for rol in user.roles.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ rol.service.rol.name }}</td>
|
<td>{{ rol.service.get_roles }}</td>
|
||||||
<td>{{ rol.service.description }}</td>
|
<td>{{ rol.service.description }}</td>
|
||||||
<td>{{ rol.service.domain }}</td>
|
<td>{{ rol.service.domain }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -67,13 +67,23 @@ urlpatterns = [
|
||||||
name='user_roles'),
|
name='user_roles'),
|
||||||
path('user/gdpr/', views_user.UserGDPRView.as_view(),
|
path('user/gdpr/', views_user.UserGDPRView.as_view(),
|
||||||
name='user_gdpr'),
|
name='user_gdpr'),
|
||||||
path('user/identities/', views_user.UserIdentitiesView.as_view(),
|
path('user/identities/', views_user.UserDidsView.as_view(),
|
||||||
name='user_identities'),
|
name='user_dids'),
|
||||||
|
path('user/dids/new/', views_user.UserDidRegisterView.as_view(),
|
||||||
|
name='user_dids_new'),
|
||||||
|
path('user/dids/<int:pk>/', views_user.UserDidEditView.as_view(),
|
||||||
|
name='user_dids_edit'),
|
||||||
|
path('user/dids/<int:pk>/del/', views_user.UserDidDeleteView.as_view(),
|
||||||
|
name='user_dids_del'),
|
||||||
path('user/credentials/', views_user.UserCredentialsView.as_view(),
|
path('user/credentials/', views_user.UserCredentialsView.as_view(),
|
||||||
name='user_credentials'),
|
name='user_credentials'),
|
||||||
path('user/credentials_required/',
|
path('user/credentials/<int:pk>', views_user.UserCredentialView.as_view(),
|
||||||
views_user.UserCredentialsRequiredView.as_view(),
|
name='user_credential'),
|
||||||
name='user_credentials_required'),
|
path('user/credentials/<int:pk>/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/',
|
path('user/credentials_presentation/',
|
||||||
views_user.UserCredentialsPresentationView.as_view(),
|
views_user.UserCredentialsPresentationView.as_view(),
|
||||||
name='user_credentials_presentation'),
|
name='user_credentials_presentation'),
|
||||||
|
@ -123,26 +133,40 @@ urlpatterns = [
|
||||||
name='admin_service_del'),
|
name='admin_service_del'),
|
||||||
path('admin/credentials/', views_admin.AdminCredentialsView.as_view(),
|
path('admin/credentials/', views_admin.AdminCredentialsView.as_view(),
|
||||||
name='admin_credentials'),
|
name='admin_credentials'),
|
||||||
path('admin/credentials/new/', views_admin.AdminIssueCredentialsView.as_view(),
|
path('admin/credentials/<int:pk>/', views_admin.AdminCredentialView.as_view(),
|
||||||
name='admin_credentials_new'),
|
name='admin_credential'),
|
||||||
path('admin/credentials/revoke/', views_admin.AdminRevokeCredentialsView.as_view(),
|
path('admin/credentials/revoke/', views_admin.AdminRevokeCredentialsView.as_view(),
|
||||||
name='admin_credentials_revoke'),
|
name='admin_credentials_revoke'),
|
||||||
path('admin/wallet/identities/', views_admin.AdminWalletIdentitiesView.as_view(),
|
path('admin/wallet/identities/', views_admin.AdminDidsView.as_view(),
|
||||||
name='admin_wallet_identities'),
|
name='admin_dids'),
|
||||||
|
path('admin/dids/new/', views_admin.AdminDidRegisterView.as_view(),
|
||||||
|
name='admin_dids_new'),
|
||||||
|
path('admin/dids/<int:pk>/', views_admin.AdminDidEditView.as_view(),
|
||||||
|
name='admin_dids_edit'),
|
||||||
|
path('admin/dids/<int:pk>/del/', views_admin.AdminDidDeleteView.as_view(),
|
||||||
|
name='admin_dids_del'),
|
||||||
path('admin/wallet/credentials/', views_admin.AdminWalletCredentialsView.as_view(),
|
path('admin/wallet/credentials/', views_admin.AdminWalletCredentialsView.as_view(),
|
||||||
name='admin_wallet_credentials'),
|
name='admin_wallet_credentials'),
|
||||||
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
|
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
|
||||||
name='admin_wallet_config_issue'),
|
name='admin_wallet_config_issue'),
|
||||||
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
|
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
|
||||||
name='admin_wallet_config_issue'),
|
name='admin_wallet_config_issue'),
|
||||||
path('admin/schemes/', views_admin.AdminSchemesView.as_view(),
|
path('admin/schemas/', views_admin.AdminSchemasView.as_view(),
|
||||||
name='admin_schemes'),
|
name='admin_schemas'),
|
||||||
path('admin/schemes/import', views_admin.AdminSchemesImportView.as_view(),
|
path('admin/schemas/<int:pk>/del/', views_admin.AdminSchemasDeleteView.as_view(),
|
||||||
name='admin_schemes_import'),
|
name='admin_schemas_del'),
|
||||||
path('admin/schemes/export/', views_admin.AdminSchemesExportView.as_view(),
|
path('admin/schemas/<int:pk>/', views_admin.AdminSchemasDownloadView.as_view(),
|
||||||
name='admin_schemes_export'),
|
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/<str:file_schema>', views_admin.AdminSchemasImportAddView.as_view(),
|
||||||
|
name='admin_schemas_import_add'),
|
||||||
path('admin/import', views_admin.AdminImportView.as_view(),
|
path('admin/import', views_admin.AdminImportView.as_view(),
|
||||||
name='admin_import'),
|
name='admin_import'),
|
||||||
path('admin/export/', views_admin.AdminExportView.as_view(),
|
path('admin/import/new', views_admin.AdminImportStep2View.as_view(),
|
||||||
name='admin_export'),
|
name='admin_import_step2'),
|
||||||
|
path('admin/import/<int:pk>/', views_admin.AdminImportStep3View.as_view(),
|
||||||
|
name='admin_import_step3'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from django import forms
|
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):
|
class ProfileForm(forms.ModelForm):
|
||||||
|
@ -8,3 +10,85 @@ class ProfileForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('first_name', 'last_name', 'email')
|
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
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
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.views.generic.base import TemplateView
|
||||||
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.http import HttpResponse
|
||||||
from django.contrib import messages
|
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.mixins import UserView
|
||||||
|
from idhub.models import DID, VerificableCredential
|
||||||
|
|
||||||
|
|
||||||
class MyProfile(UserView):
|
class MyProfile(UserView):
|
||||||
|
@ -14,7 +23,7 @@ class MyProfile(UserView):
|
||||||
section = "MyProfile"
|
section = "MyProfile"
|
||||||
|
|
||||||
|
|
||||||
class MyWallet(UserView, TemplateView):
|
class MyWallet(UserView):
|
||||||
title = _("My Wallet")
|
title = _("My Wallet")
|
||||||
section = "MyWallet"
|
section = "MyWallet"
|
||||||
|
|
||||||
|
@ -51,25 +60,178 @@ class UserGDPRView(MyProfile, TemplateView):
|
||||||
icon = 'bi bi-file-earmark-medical'
|
icon = 'bi bi-file-earmark-medical'
|
||||||
|
|
||||||
|
|
||||||
class UserIdentitiesView(MyWallet):
|
class UserCredentialsView(MyWallet, TemplateView):
|
||||||
template_name = "idhub/user/identities.html"
|
|
||||||
subtitle = _('Identities (DID)')
|
|
||||||
icon = 'bi bi-patch-check-fill'
|
|
||||||
|
|
||||||
|
|
||||||
class UserCredentialsView(MyWallet):
|
|
||||||
template_name = "idhub/user/credentials.html"
|
template_name = "idhub/user/credentials.html"
|
||||||
subtitle = _('Credentials')
|
subtitle = _('Credentials')
|
||||||
icon = 'bi bi-patch-check-fill'
|
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"
|
class UserCredentialView(MyWallet, TemplateView):
|
||||||
subtitle = _('Credentials required')
|
template_name = "idhub/user/credential.html"
|
||||||
|
subtitle = _('Credential')
|
||||||
icon = 'bi bi-patch-check-fill'
|
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"
|
template_name = "idhub/user/credentials_presentation.html"
|
||||||
subtitle = _('Credentials Presentation')
|
subtitle = _('Credentials Presentation')
|
||||||
icon = 'bi bi-patch-check-fill'
|
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)
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AuthConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'idhub_auth'
|
|
@ -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,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
||||||
|
[tool.black]
|
||||||
|
skip-string-normalization = true
|
||||||
|
target-version = ['py311']
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
|
@ -3,3 +3,7 @@ django-bootstrap5==23.3
|
||||||
django-extensions==3.2.3
|
django-extensions==3.2.3
|
||||||
black==23.9.1
|
black==23.9.1
|
||||||
python-decouple==3.8
|
python-decouple==3.8
|
||||||
|
jsonschema==4.19.1
|
||||||
|
pandas==2.1.1
|
||||||
|
requests==2.31.0
|
||||||
|
|
||||||
|
|
|
@ -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"]
|
||||||
|
}
|
|
@ -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"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -70,6 +70,7 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
'django_bootstrap5',
|
'django_bootstrap5',
|
||||||
|
'idhub_auth',
|
||||||
'idhub'
|
'idhub'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -160,6 +161,7 @@ MEDIA_URL = '/media/'
|
||||||
STATIC_ROOT = config('STATIC_ROOT')
|
STATIC_ROOT = config('STATIC_ROOT')
|
||||||
MEDIA_ROOT = config('MEDIA_ROOT', default="idhub/upload")
|
MEDIA_ROOT = config('MEDIA_ROOT', default="idhub/upload")
|
||||||
FIXTURE_DIRS = (os.path.join(BASE_DIR, 'fixtures'),)
|
FIXTURE_DIRS = (os.path.join(BASE_DIR, 'fixtures'),)
|
||||||
|
SCHEMAS_DIR = os.path.join(BASE_DIR, 'schemas')
|
||||||
|
|
||||||
# Default primary key field type
|
# Default primary key field type
|
||||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
@ -176,3 +178,4 @@ MESSAGE_TAGS = {
|
||||||
messages.ERROR: 'alert-danger',
|
messages.ERROR: 'alert-danger',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AUTH_USER_MODEL = 'idhub_auth.User'
|
||||||
|
|
Loading…
Reference in New Issue