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.contrib.auth.models import User
|
||||
from idhub.models import Rol
|
||||
|
||||
|
||||
class ProfileForm(forms.ModelForm):
|
||||
MANDATORY_FIELDS = ['first_name', 'last_name', 'email', 'username']
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('first_name', 'last_name', 'email')
|
||||
class ImportForm(forms.Form):
|
||||
file_import = forms.FileField()
|
||||
|
||||
|
||||
class MembershipForm(forms.ModelForm):
|
||||
MANDATORY_FIELDS = ['type']
|
||||
|
||||
|
||||
class RolForm(forms.ModelForm):
|
||||
MANDATORY_FIELDS = ['name']
|
||||
|
||||
|
||||
class ServiceForm(forms.ModelForm):
|
||||
MANDATORY_FIELDS = ['domain', 'rol']
|
||||
|
||||
|
||||
class UserRolForm(forms.ModelForm):
|
||||
MANDATORY_FIELDS = ['service']
|
||||
class SchemaForm(forms.Form):
|
||||
file_template = forms.FileField()
|
||||
|
|
|
@ -1,22 +1,35 @@
|
|||
import os
|
||||
import csv
|
||||
import json
|
||||
import copy
|
||||
import logging
|
||||
import pandas as pd
|
||||
from pathlib import Path
|
||||
from jsonschema import validate
|
||||
from smtplib import SMTPException
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.edit import UpdateView, CreateView
|
||||
from django.contrib.auth.models import User
|
||||
from django.views.generic.edit import UpdateView, CreateView, DeleteView
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.http import HttpResponse
|
||||
from django.contrib import messages
|
||||
from idhub.models import Membership, Rol, Service, UserRol
|
||||
from apiregiter import iota
|
||||
from idhub_auth.models import User
|
||||
from idhub.mixins import AdminView
|
||||
from idhub.email.views import NotifyActivateUserByEmail
|
||||
from idhub.admin.forms import (
|
||||
ProfileForm,
|
||||
MembershipForm,
|
||||
RolForm,
|
||||
ServiceForm,
|
||||
UserRolForm
|
||||
from idhub.admin.forms import ImportForm, SchemaForm
|
||||
from idhub.models import (
|
||||
DID,
|
||||
File_datas,
|
||||
Membership,
|
||||
Rol,
|
||||
Service,
|
||||
Schemas,
|
||||
UserRol,
|
||||
VerificableCredential,
|
||||
)
|
||||
|
||||
|
||||
|
@ -42,9 +55,9 @@ class Credentials(AdminView, TemplateView):
|
|||
section = "Credentials"
|
||||
|
||||
|
||||
class Schemes(AdminView, TemplateView):
|
||||
title = _("Schemes Management")
|
||||
section = "Schemes"
|
||||
class SchemasMix(AdminView, TemplateView):
|
||||
title = _("Templates Management")
|
||||
section = "Templates"
|
||||
|
||||
|
||||
class ImportExport(AdminView, TemplateView):
|
||||
|
@ -118,8 +131,7 @@ class AdminPeopleDeleteView(AdminPeopleView):
|
|||
|
||||
class AdminPeopleEditView(AdminPeopleView, UpdateView):
|
||||
template_name = "idhub/admin/user_edit.html"
|
||||
from_class = ProfileForm
|
||||
fields = ('first_name', 'last_name', 'email', 'username')
|
||||
fields = ('first_name', 'last_name', 'email')
|
||||
success_url = reverse_lazy('idhub:admin_people_list')
|
||||
|
||||
|
||||
|
@ -128,8 +140,7 @@ class AdminPeopleRegisterView(NotifyActivateUserByEmail, People, CreateView):
|
|||
subtitle = _('People Register')
|
||||
icon = 'bi bi-person'
|
||||
model = User
|
||||
from_class = ProfileForm
|
||||
fields = ('first_name', 'last_name', 'email', 'username')
|
||||
fields = ('first_name', 'last_name', 'email')
|
||||
success_url = reverse_lazy('idhub:admin_people_list')
|
||||
|
||||
def get_success_url(self):
|
||||
|
@ -155,7 +166,6 @@ class AdminPeopleMembershipRegisterView(People, CreateView):
|
|||
subtitle = _('People add membership')
|
||||
icon = 'bi bi-person'
|
||||
model = Membership
|
||||
from_class = MembershipForm
|
||||
fields = ('type', 'start_date', 'end_date')
|
||||
success_url = reverse_lazy('idhub:admin_people_list')
|
||||
|
||||
|
@ -193,7 +203,6 @@ class AdminPeopleMembershipEditView(People, CreateView):
|
|||
subtitle = _('People add membership')
|
||||
icon = 'bi bi-person'
|
||||
model = Membership
|
||||
from_class = MembershipForm
|
||||
fields = ('type', 'start_date', 'end_date')
|
||||
success_url = reverse_lazy('idhub:admin_people_list')
|
||||
|
||||
|
@ -232,7 +241,6 @@ class AdminPeopleRolRegisterView(People, CreateView):
|
|||
subtitle = _('Add Rol to User')
|
||||
icon = 'bi bi-person'
|
||||
model = UserRol
|
||||
from_class = UserRolForm
|
||||
fields = ('service',)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
@ -263,7 +271,6 @@ class AdminPeopleRolEditView(People, CreateView):
|
|||
subtitle = _('Edit Rol to User')
|
||||
icon = 'bi bi-person'
|
||||
model = UserRol
|
||||
from_class = UserRolForm
|
||||
fields = ('service',)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
|
@ -311,7 +318,6 @@ class AdminRolRegisterView(AccessControl, CreateView):
|
|||
subtitle = _('Add Rol')
|
||||
icon = ''
|
||||
model = Rol
|
||||
from_class = RolForm
|
||||
fields = ('name',)
|
||||
success_url = reverse_lazy('idhub:admin_roles')
|
||||
object = None
|
||||
|
@ -322,7 +328,6 @@ class AdminRolEditView(AccessControl, CreateView):
|
|||
subtitle = _('Edit Rol')
|
||||
icon = ''
|
||||
model = Rol
|
||||
from_class = RolForm
|
||||
fields = ('name',)
|
||||
success_url = reverse_lazy('idhub:admin_roles')
|
||||
|
||||
|
@ -362,7 +367,6 @@ class AdminServiceRegisterView(AccessControl, CreateView):
|
|||
subtitle = _('Add Service')
|
||||
icon = ''
|
||||
model = Service
|
||||
from_class = ServiceForm
|
||||
fields = ('domain', 'description', 'rol')
|
||||
success_url = reverse_lazy('idhub:admin_services')
|
||||
object = None
|
||||
|
@ -373,7 +377,6 @@ class AdminServiceEditView(AccessControl, CreateView):
|
|||
subtitle = _('Edit Service')
|
||||
icon = ''
|
||||
model = Service
|
||||
from_class = ServiceForm
|
||||
fields = ('domain', 'description', 'rol')
|
||||
success_url = reverse_lazy('idhub:admin_services')
|
||||
|
||||
|
@ -401,11 +404,31 @@ class AdminCredentialsView(Credentials):
|
|||
subtitle = _('Credentials list')
|
||||
icon = ''
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'credentials': VerificableCredential.objects,
|
||||
})
|
||||
return context
|
||||
|
||||
class AdminIssueCredentialsView(Credentials):
|
||||
|
||||
class AdminCredentialView(Credentials):
|
||||
template_name = "idhub/admin/issue_credentials.html"
|
||||
subtitle = _('Issuance of Credentials')
|
||||
subtitle = _('Change status of Credential')
|
||||
icon = ''
|
||||
model = VerificableCredential
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(self.model, pk=self.pk)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'object': self.object,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class AdminRevokeCredentialsView(Credentials):
|
||||
|
@ -414,12 +437,89 @@ class AdminRevokeCredentialsView(Credentials):
|
|||
icon = ''
|
||||
|
||||
|
||||
class AdminWalletIdentitiesView(Credentials):
|
||||
template_name = "idhub/admin/wallet_identities.html"
|
||||
class AdminDidsView(Credentials):
|
||||
template_name = "idhub/admin/dids.html"
|
||||
subtitle = _('Organization Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'dids': DID.objects,
|
||||
})
|
||||
return context
|
||||
|
||||
class AdminDidRegisterView(Credentials, CreateView):
|
||||
template_name = "idhub/admin/did_register.html"
|
||||
subtitle = _('Add a new Organization Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
fields = ('did', 'label')
|
||||
success_url = reverse_lazy('idhub:admin_dids')
|
||||
object = None
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['initial'] = {
|
||||
'did': iota.issue_did()
|
||||
}
|
||||
return kwargs
|
||||
|
||||
def get_form(self):
|
||||
form = super().get_form()
|
||||
form.fields['did'].required = False
|
||||
form.fields['did'].disabled = True
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
form.save()
|
||||
messages.success(self.request, _('DID created successfully'))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class AdminDidEditView(Credentials, UpdateView):
|
||||
template_name = "idhub/admin/did_register.html"
|
||||
subtitle = _('Organization Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
fields = ('did', 'label')
|
||||
success_url = reverse_lazy('idhub:admin_dids')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(self.model, pk=self.pk)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_form(self):
|
||||
form = super().get_form()
|
||||
form.fields['did'].required = False
|
||||
form.fields['did'].disabled = True
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
user = form.save()
|
||||
messages.success(self.request, _('DID updated successfully'))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class AdminDidDeleteView(Credentials, DeleteView):
|
||||
subtitle = _('Organization Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
success_url = reverse_lazy('idhub:admin_dids')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(self.model, pk=self.pk)
|
||||
self.object.delete()
|
||||
messages.success(self.request, _('DID delete successfully'))
|
||||
|
||||
return redirect(self.success_url)
|
||||
|
||||
|
||||
class AdminWalletCredentialsView(Credentials):
|
||||
template_name = "idhub/admin/wallet_credentials.html"
|
||||
|
@ -435,22 +535,136 @@ class AdminWalletConfigIssuesView(Credentials):
|
|||
wallet = True
|
||||
|
||||
|
||||
class AdminSchemesView(Schemes):
|
||||
template_name = "idhub/admin/schemes.html"
|
||||
subtitle = _('Schemes List')
|
||||
class AdminSchemasView(SchemasMix):
|
||||
template_name = "idhub/admin/schemas.html"
|
||||
subtitle = _('Template List')
|
||||
icon = ''
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'schemas': Schemas.objects,
|
||||
})
|
||||
return context
|
||||
|
||||
class AdminSchemesImportView(Schemes):
|
||||
template_name = "idhub/admin/schemes_import.html"
|
||||
subtitle = _('Import Schemes')
|
||||
|
||||
class AdminSchemasDeleteView(SchemasMix):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(Schemas, pk=self.pk)
|
||||
self.object.delete()
|
||||
|
||||
return redirect('idhub:admin_schemas')
|
||||
|
||||
|
||||
class AdminSchemasDownloadView(SchemasMix):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(Schemas, pk=self.pk)
|
||||
|
||||
response = HttpResponse(self.object.data, content_type="application/json")
|
||||
response['Content-Disposition'] = 'inline; filename={}'.format(self.object.file_schema)
|
||||
return response
|
||||
|
||||
|
||||
class AdminSchemasNewView(SchemasMix):
|
||||
template_name = "idhub/admin/schemas_new.html"
|
||||
subtitle = _('Upload Template')
|
||||
icon = ''
|
||||
success_url = reverse_lazy('idhub:admin_schemas')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'form': SchemaForm(),
|
||||
})
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = SchemaForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
schema = self.handle_uploaded_file()
|
||||
if not schema:
|
||||
messages.error(request, _("There are some errors in the file"))
|
||||
return super().get(request, *args, **kwargs)
|
||||
return redirect(self.success_url)
|
||||
else:
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
def handle_uploaded_file(self):
|
||||
f = self.request.FILES.get('file_template')
|
||||
if not f:
|
||||
return
|
||||
file_name = f.name
|
||||
if Schemas.objects.filter(file_schema=file_name).exists():
|
||||
messages.error(self.request, _("This template already exists!"))
|
||||
return
|
||||
try:
|
||||
data = f.read().decode('utf-8')
|
||||
json.loads(data)
|
||||
except Exception:
|
||||
messages.error(self.request, _('This is not a schema valid!'))
|
||||
return
|
||||
schema = Schemas.objects.create(file_schema=file_name, data=data)
|
||||
schema.save()
|
||||
return schema
|
||||
|
||||
|
||||
class AdminSchemasImportView(SchemasMix):
|
||||
template_name = "idhub/admin/schemas_import.html"
|
||||
subtitle = _('Import Template')
|
||||
icon = ''
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'schemas': self.get_schemas(),
|
||||
})
|
||||
return context
|
||||
|
||||
class AdminSchemesExportView(Schemes):
|
||||
template_name = "idhub/admin/schemes_export.html"
|
||||
subtitle = _('Export Schemes')
|
||||
icon = ''
|
||||
def get_schemas(self):
|
||||
schemas_files = os.listdir(settings.SCHEMAS_DIR)
|
||||
schemas = [x for x in schemas_files
|
||||
if not Schemas.objects.filter(file_schema=x).exists()]
|
||||
return schemas
|
||||
|
||||
|
||||
class AdminSchemasImportAddView(SchemasMix):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
file_name = kwargs['file_schema']
|
||||
schemas_files = os.listdir(settings.SCHEMAS_DIR)
|
||||
if not file_name in schemas_files:
|
||||
messages.error(self.request, f"The schema {file_name} not exist!")
|
||||
return redirect('idhub:admin_schemas_import')
|
||||
|
||||
schema = self.create_schema(file_name)
|
||||
if schema:
|
||||
messages.success(self.request, _("The schema add successfully!"))
|
||||
return redirect('idhub:admin_schemas_import')
|
||||
|
||||
def create_schema(self, file_name):
|
||||
data = self.open_file(file_name)
|
||||
try:
|
||||
json.loads(data)
|
||||
except Exception:
|
||||
messages.error(self.request, _('This is not a schema valid!'))
|
||||
return
|
||||
schema = Schemas.objects.create(file_schema=file_name, data=data)
|
||||
schema.save()
|
||||
return schema
|
||||
|
||||
def open_file(self, file_name):
|
||||
data = ''
|
||||
filename = Path(settings.SCHEMAS_DIR).joinpath(file_name)
|
||||
with filename.open() as schema_file:
|
||||
data = schema_file.read()
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class AdminImportView(ImportExport):
|
||||
|
@ -458,8 +672,114 @@ class AdminImportView(ImportExport):
|
|||
subtitle = _('Import')
|
||||
icon = ''
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'dates': File_datas.objects,
|
||||
})
|
||||
return context
|
||||
|
||||
class AdminExportView(ImportExport):
|
||||
template_name = "idhub/admin/export.html"
|
||||
subtitle = _('Export')
|
||||
|
||||
class AdminImportStep2View(ImportExport):
|
||||
template_name = "idhub/admin/import_step2.html"
|
||||
subtitle = _('Import')
|
||||
icon = ''
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'schemas': Schemas.objects,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class AdminImportStep3View(ImportExport):
|
||||
template_name = "idhub/admin/import_step3.html"
|
||||
subtitle = _('Import')
|
||||
icon = ''
|
||||
success_url = reverse_lazy('idhub:admin_import')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'form': ImportForm(),
|
||||
})
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.schema = get_object_or_404(Schemas, pk=self.pk)
|
||||
form = ImportForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
result = self.handle_uploaded_file()
|
||||
if not result:
|
||||
messages.error(request, _("There are some errors in the file"))
|
||||
return super().get(request, *args, **kwargs)
|
||||
return redirect(self.success_url)
|
||||
else:
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
def handle_uploaded_file(self):
|
||||
f = self.request.FILES.get('file_import')
|
||||
if not f:
|
||||
messages.error(self.request, _("There aren't file"))
|
||||
return
|
||||
|
||||
file_name = f.name
|
||||
if File_datas.objects.filter(file_name=file_name, success=True).exists():
|
||||
messages.error(self.request, _("This file already exists!"))
|
||||
return
|
||||
|
||||
self.json_schema = json.loads(self.schema.data)
|
||||
df = pd.read_csv (f, delimiter="\t", quotechar='"', quoting=csv.QUOTE_ALL)
|
||||
data_pd = df.fillna('').to_dict()
|
||||
rows = {}
|
||||
|
||||
if not data_pd:
|
||||
File_datas.objects.create(file_name=file_name, success=False)
|
||||
return
|
||||
|
||||
for n in range(df.last_valid_index()+1):
|
||||
row = {}
|
||||
for k in data_pd.keys():
|
||||
row[k] = data_pd[k][n]
|
||||
|
||||
user = self.validate(n, row)
|
||||
if not user:
|
||||
File_datas.objects.create(file_name=file_name, success=False)
|
||||
return
|
||||
|
||||
rows[user] = row
|
||||
|
||||
File_datas.objects.create(file_name=file_name)
|
||||
for k, v in rows.items():
|
||||
self.create_credential(k, v)
|
||||
|
||||
return True
|
||||
|
||||
def validate(self, line, row):
|
||||
try:
|
||||
validate(instance=row, schema=self.json_schema)
|
||||
except Exception as e:
|
||||
messages.error(self.request, "line {}: {}".format(line+1, e))
|
||||
return
|
||||
|
||||
user = User.objects.filter(email=row.get('email'))
|
||||
if not user:
|
||||
txt = _('The user not exist!')
|
||||
messages.error(self.request, "line {}: {}".format(line+1, txt))
|
||||
return
|
||||
|
||||
return user.first()
|
||||
|
||||
def create_credential(self, user, row):
|
||||
d = copy.copy(self.json_schema)
|
||||
d['instance'] = row
|
||||
return VerificableCredential.objects.create(
|
||||
verified=False,
|
||||
user=user,
|
||||
data=json.dumps(d)
|
||||
)
|
||||
|
||||
|
|
|
@ -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.db import migrations, models
|
||||
|
@ -14,115 +14,247 @@ class Migration(migrations.Migration):
|
|||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="VCTemplate",
|
||||
name='File_datas',
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
("wkit_template_id", models.CharField(max_length=250)),
|
||||
("data", models.TextField()),
|
||||
('file_name', models.CharField(max_length=250)),
|
||||
('success', models.BooleanField(default=True)),
|
||||
('created_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="VerifiableCredential",
|
||||
name='Organization',
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
("id_string", models.CharField(max_length=250)),
|
||||
("verified", models.BooleanField()),
|
||||
("created_on", models.DateTimeField()),
|
||||
("did_issuer", models.CharField(max_length=250)),
|
||||
("did_subject", models.CharField(max_length=250)),
|
||||
("data", models.TextField()),
|
||||
('name', models.CharField(max_length=250)),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="vcredentials",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
'url',
|
||||
models.CharField(
|
||||
help_text='Url where to send the presentation', max_length=250
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Membership",
|
||||
name='Rol',
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
('name', models.CharField(max_length=250)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Schemas',
|
||||
fields=[
|
||||
(
|
||||
"type",
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
('file_schema', models.CharField(max_length=250)),
|
||||
('data', models.TextField()),
|
||||
('created_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Service',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
('domain', models.CharField(max_length=250)),
|
||||
('description', models.CharField(max_length=250)),
|
||||
('rol', models.ManyToManyField(to='idhub.rol')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VCTemplate',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
('wkit_template_id', models.CharField(max_length=250)),
|
||||
('data', models.TextField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VerificableCredential',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
('id_string', models.CharField(max_length=250)),
|
||||
('verified', models.BooleanField()),
|
||||
('created_on', models.DateTimeField(auto_now=True)),
|
||||
('issuer_on', models.DateTimeField(null=True)),
|
||||
('did_issuer', models.CharField(max_length=250)),
|
||||
('did_subject', models.CharField(max_length=250)),
|
||||
('data', models.TextField()),
|
||||
(
|
||||
'status',
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[(1, "Beneficiary"), (2, "Employee"), (3, "Partner")],
|
||||
verbose_name="Type of membership",
|
||||
choices=[
|
||||
(1, 'Enabled'),
|
||||
(2, 'Issued'),
|
||||
(3, 'Revoked'),
|
||||
(4, 'Expired'),
|
||||
],
|
||||
default=1,
|
||||
),
|
||||
),
|
||||
(
|
||||
"start_date",
|
||||
models.DateField(
|
||||
blank=True,
|
||||
help_text="What date did the membership start?",
|
||||
null=True,
|
||||
verbose_name="Start date",
|
||||
),
|
||||
),
|
||||
(
|
||||
"end_date",
|
||||
models.DateField(
|
||||
blank=True,
|
||||
help_text="What date did the membership end?",
|
||||
null=True,
|
||||
verbose_name="End date",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="memberships",
|
||||
related_name='vcredentials',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="DID",
|
||||
name='UserRol',
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
("did_string", models.CharField(max_length=250)),
|
||||
("label", models.CharField(max_length=50)),
|
||||
(
|
||||
"user",
|
||||
'service',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="dids",
|
||||
related_name='users',
|
||||
to='idhub.service',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='roles',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Membership',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
(
|
||||
'type',
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[(1, 'Beneficiary'), (2, 'Employee'), (3, 'Partner')],
|
||||
verbose_name='Type of membership',
|
||||
),
|
||||
),
|
||||
(
|
||||
'start_date',
|
||||
models.DateField(
|
||||
blank=True,
|
||||
help_text='What date did the membership start?',
|
||||
null=True,
|
||||
verbose_name='Start date',
|
||||
),
|
||||
),
|
||||
(
|
||||
'end_date',
|
||||
models.DateField(
|
||||
blank=True,
|
||||
help_text='What date did the membership end?',
|
||||
null=True,
|
||||
verbose_name='End date',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='memberships',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DID',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID',
|
||||
),
|
||||
),
|
||||
('created_at', models.DateTimeField(auto_now=True)),
|
||||
('did', models.CharField(max_length=250, unique=True)),
|
||||
('label', models.CharField(max_length=50)),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='dids',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not request.user.is_superuser:
|
||||
if not request.user.is_admin:
|
||||
url = reverse_lazy('idhub:user_dashboard')
|
||||
return redirect(url)
|
||||
|
||||
|
|
106
idhub/models.py
106
idhub/models.py
|
@ -1,15 +1,8 @@
|
|||
import json
|
||||
import requests
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
# class AppUser(models.Model):
|
||||
# Ya incluye "first_name", "last_name", "email", y "date_joined" heredando de la clase User de django.
|
||||
# Falta ver que más información hay que añadir a nuestros usuarios, como los roles etc.
|
||||
# django_user = models.OneToOneField(DjangoUser, on_delete=models.CASCADE)
|
||||
|
||||
# Extra data, segun entidad/organizacion
|
||||
# pass
|
||||
from idhub_auth.models import User
|
||||
|
||||
|
||||
# class Event(models.Model):
|
||||
|
@ -20,35 +13,103 @@ from django.contrib.auth.models import User
|
|||
|
||||
|
||||
class DID(models.Model):
|
||||
did_string = models.CharField(max_length=250)
|
||||
created_at = models.DateTimeField(auto_now=True)
|
||||
did = models.CharField(max_length=250, unique=True)
|
||||
label = models.CharField(max_length=50)
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='dids',
|
||||
null=True,
|
||||
)
|
||||
# kind = "KEY|WEB"
|
||||
|
||||
@property
|
||||
def is_organization_did(self):
|
||||
if not self.user:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Schemas(models.Model):
|
||||
file_schema = models.CharField(max_length=250)
|
||||
data = models.TextField()
|
||||
created_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
@property
|
||||
def get_schema(self):
|
||||
if not self.data:
|
||||
return {}
|
||||
return json.loads(self.data)
|
||||
|
||||
def name(self):
|
||||
return self.get_schema.get('name', '')
|
||||
|
||||
def description(self):
|
||||
return self.get_schema.get('description', '')
|
||||
|
||||
|
||||
class VerificableCredential(models.Model):
|
||||
"""
|
||||
Definition of Verificable Credentials
|
||||
"""
|
||||
class Status(models.IntegerChoices):
|
||||
ENABLED = 1, _("Enabled")
|
||||
ISSUED = 2, _("Issued")
|
||||
REVOKED = 3, _("Revoked")
|
||||
EXPIRED = 4, _("Expired")
|
||||
|
||||
class VerifiableCredential(models.Model):
|
||||
id_string = models.CharField(max_length=250)
|
||||
verified = models.BooleanField()
|
||||
created_on = models.DateTimeField()
|
||||
created_on = models.DateTimeField(auto_now=True)
|
||||
issuer_on = models.DateTimeField(null=True)
|
||||
did_issuer = models.CharField(max_length=250)
|
||||
did_subject = models.CharField(max_length=250)
|
||||
data = models.TextField()
|
||||
status = models.PositiveSmallIntegerField(
|
||||
choices=Status.choices,
|
||||
default=Status.ENABLED
|
||||
)
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='vcredentials',
|
||||
)
|
||||
data = models.TextField()
|
||||
|
||||
@property
|
||||
def get_schema(self):
|
||||
if not self.data:
|
||||
return {}
|
||||
return json.loads(self.data)
|
||||
|
||||
def type(self):
|
||||
return self.get_schema.get('name', '')
|
||||
|
||||
def description(self):
|
||||
return self.get_schema.get('description', '')
|
||||
|
||||
def get_status(self):
|
||||
return self.Status(self.status).label
|
||||
|
||||
def get_datas(self):
|
||||
data = json.loads(self.data).get('instance').items()
|
||||
return data
|
||||
|
||||
def get_issued(self, did):
|
||||
self.status = self.Status.ISSUED
|
||||
self.did_subject = did
|
||||
|
||||
class VCTemplate(models.Model):
|
||||
wkit_template_id = models.CharField(max_length=250)
|
||||
data = models.TextField()
|
||||
|
||||
|
||||
class File_datas(models.Model):
|
||||
file_name = models.CharField(max_length=250)
|
||||
success = models.BooleanField(default=True)
|
||||
created_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
||||
class Membership(models.Model):
|
||||
"""
|
||||
This model represent the relation of this user with the ecosystem.
|
||||
|
@ -100,7 +161,7 @@ class Service(models.Model):
|
|||
return ", ".join([x.name for x in self.rol.all()])
|
||||
|
||||
def __str__(self):
|
||||
return "{} -> {}".format(self.domain, self.rol.name)
|
||||
return "{} -> {}".format(self.domain, self.get_roles())
|
||||
|
||||
|
||||
class UserRol(models.Model):
|
||||
|
@ -114,3 +175,18 @@ class UserRol(models.Model):
|
|||
on_delete=models.CASCADE,
|
||||
related_name='users',
|
||||
)
|
||||
|
||||
|
||||
class Organization(models.Model):
|
||||
name = models.CharField(max_length=250)
|
||||
url = models.CharField(
|
||||
help_text=_("Url where to send the presentation"),
|
||||
max_length=250
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def send(self, cred):
|
||||
return
|
||||
requests.post(self.url, data=cred.data)
|
|
@ -6,4 +6,34 @@
|
|||
<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"><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 %}
|
||||
|
|
|
@ -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>
|
||||
{{ 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 '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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>
|
||||
<i class="{{ icon }}"></i>
|
||||
{{ subtitle }}
|
||||
</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 %}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<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-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 'Role' %}</button></th>
|
||||
<th scope="col"></th>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<tr>
|
||||
<td>{{ user.last_name }}</td>
|
||||
<td>{{ user.first_name }}</td>
|
||||
<td>{{ user.username }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
{% for m in user.memberships.all %}
|
||||
{{ 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-content">
|
||||
<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>
|
||||
</div>
|
||||
<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>
|
||||
<ul class="flex-column mb-2 ul_sidebar">
|
||||
<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)
|
||||
</a>
|
||||
</li>
|
||||
|
@ -110,8 +110,8 @@
|
|||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if path == 'user_credentials_required' %}active2{% endif %}" href="{% url 'idhub:user_credentials_required' %}">
|
||||
Credentials required
|
||||
<a class="nav-link {% if path == 'user_credentials_request' %}active2{% endif %}" href="{% url 'idhub:user_credentials_request' %}">
|
||||
Credentials request
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
|
@ -144,10 +144,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<h3>
|
||||
<i class="{{ icon }}"></i>
|
||||
{{ subtitle }}
|
||||
</h3>
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
||||
|
|
|
@ -117,23 +117,13 @@
|
|||
Credentials list
|
||||
</a>
|
||||
</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">
|
||||
<a id="wallet" class="nav-link" data-bs-toggle="collapse" data-bs-target="#lwallet" aria-expanded="false" aria-controls="lwallet" href="javascript:void()">
|
||||
Wallet
|
||||
</a>
|
||||
<ul class="flex-column mb-2 accordion-collapse {% if wallet %}expanded{% else %}collapse{% endif %}" id="lwallet" data-bs-parent="#wallet">
|
||||
<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)
|
||||
</a>
|
||||
</li>
|
||||
|
@ -152,45 +142,16 @@
|
|||
</ul>
|
||||
</li>
|
||||
<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>
|
||||
Schemes
|
||||
</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
|
||||
Templates
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_schemes_import' %} active2{% endif %}" href="{% url 'idhub:admin_schemes_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()">
|
||||
<a class="admin nav-link {% if section == 'ImportExport' %}active {% endif %}fw-bold" href="{% url 'idhub:admin_import' %}">
|
||||
<i class="bi bi-arrow-down-square icon_sidebar"></i>
|
||||
Imports/Exports
|
||||
Import Datas
|
||||
</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>
|
||||
</ul>
|
||||
</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 %}
|
||||
|
||||
{% 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 %}
|
||||
|
|
|
@ -2,4 +2,33 @@
|
|||
{% 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 'Send' %}" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% 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 %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
<i class="{{ icon }}"></i>
|
||||
{{ subtitle }}
|
||||
</h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<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 %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
<i class="{{ icon }}"></i>
|
||||
{{ subtitle }}
|
||||
</h3>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{% extends "idhub/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
|
@ -2,6 +2,18 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% 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 %}
|
||||
<form role="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
@ -25,4 +37,36 @@
|
|||
</div>
|
||||
|
||||
</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 %}
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
<i class="{{ icon }}"></i>
|
||||
{{ subtitle }}
|
||||
</h3>
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
<div class="table-responsive">
|
||||
|
@ -16,7 +20,7 @@
|
|||
<tbody>
|
||||
{% for rol in user.roles.all %}
|
||||
<tr>
|
||||
<td>{{ rol.service.rol.name }}</td>
|
||||
<td>{{ rol.service.get_roles }}</td>
|
||||
<td>{{ rol.service.description }}</td>
|
||||
<td>{{ rol.service.domain }}</td>
|
||||
</tr>
|
||||
|
|
|
@ -67,13 +67,23 @@ urlpatterns = [
|
|||
name='user_roles'),
|
||||
path('user/gdpr/', views_user.UserGDPRView.as_view(),
|
||||
name='user_gdpr'),
|
||||
path('user/identities/', views_user.UserIdentitiesView.as_view(),
|
||||
name='user_identities'),
|
||||
path('user/identities/', views_user.UserDidsView.as_view(),
|
||||
name='user_dids'),
|
||||
path('user/dids/new/', views_user.UserDidRegisterView.as_view(),
|
||||
name='user_dids_new'),
|
||||
path('user/dids/<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(),
|
||||
name='user_credentials'),
|
||||
path('user/credentials_required/',
|
||||
views_user.UserCredentialsRequiredView.as_view(),
|
||||
name='user_credentials_required'),
|
||||
path('user/credentials/<int:pk>', views_user.UserCredentialView.as_view(),
|
||||
name='user_credential'),
|
||||
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/',
|
||||
views_user.UserCredentialsPresentationView.as_view(),
|
||||
name='user_credentials_presentation'),
|
||||
|
@ -123,26 +133,40 @@ urlpatterns = [
|
|||
name='admin_service_del'),
|
||||
path('admin/credentials/', views_admin.AdminCredentialsView.as_view(),
|
||||
name='admin_credentials'),
|
||||
path('admin/credentials/new/', views_admin.AdminIssueCredentialsView.as_view(),
|
||||
name='admin_credentials_new'),
|
||||
path('admin/credentials/<int:pk>/', views_admin.AdminCredentialView.as_view(),
|
||||
name='admin_credential'),
|
||||
path('admin/credentials/revoke/', views_admin.AdminRevokeCredentialsView.as_view(),
|
||||
name='admin_credentials_revoke'),
|
||||
path('admin/wallet/identities/', views_admin.AdminWalletIdentitiesView.as_view(),
|
||||
name='admin_wallet_identities'),
|
||||
path('admin/wallet/identities/', views_admin.AdminDidsView.as_view(),
|
||||
name='admin_dids'),
|
||||
path('admin/dids/new/', views_admin.AdminDidRegisterView.as_view(),
|
||||
name='admin_dids_new'),
|
||||
path('admin/dids/<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(),
|
||||
name='admin_wallet_credentials'),
|
||||
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
|
||||
name='admin_wallet_config_issue'),
|
||||
path('admin/wallet/config/issue/', views_admin.AdminWalletConfigIssuesView.as_view(),
|
||||
name='admin_wallet_config_issue'),
|
||||
path('admin/schemes/', views_admin.AdminSchemesView.as_view(),
|
||||
name='admin_schemes'),
|
||||
path('admin/schemes/import', views_admin.AdminSchemesImportView.as_view(),
|
||||
name='admin_schemes_import'),
|
||||
path('admin/schemes/export/', views_admin.AdminSchemesExportView.as_view(),
|
||||
name='admin_schemes_export'),
|
||||
path('admin/schemas/', views_admin.AdminSchemasView.as_view(),
|
||||
name='admin_schemas'),
|
||||
path('admin/schemas/<int:pk>/del/', views_admin.AdminSchemasDeleteView.as_view(),
|
||||
name='admin_schemas_del'),
|
||||
path('admin/schemas/<int:pk>/', views_admin.AdminSchemasDownloadView.as_view(),
|
||||
name='admin_schemas_download'),
|
||||
path('admin/schemas/new', views_admin.AdminSchemasNewView.as_view(),
|
||||
name='admin_schemas_new'),
|
||||
path('admin/schemas/import', views_admin.AdminSchemasImportView.as_view(),
|
||||
name='admin_schemas_import'),
|
||||
path('admin/schemas/import/<str:file_schema>', views_admin.AdminSchemasImportAddView.as_view(),
|
||||
name='admin_schemas_import_add'),
|
||||
path('admin/import', views_admin.AdminImportView.as_view(),
|
||||
name='admin_import'),
|
||||
path('admin/export/', views_admin.AdminExportView.as_view(),
|
||||
name='admin_export'),
|
||||
path('admin/import/new', views_admin.AdminImportStep2View.as_view(),
|
||||
name='admin_import_step2'),
|
||||
path('admin/import/<int:pk>/', views_admin.AdminImportStep3View.as_view(),
|
||||
name='admin_import_step3'),
|
||||
]
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from idhub_auth.models import User
|
||||
from idhub.models import DID, VerificableCredential, Organization
|
||||
|
||||
|
||||
|
||||
class ProfileForm(forms.ModelForm):
|
||||
|
@ -8,3 +10,85 @@ class ProfileForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = User
|
||||
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
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.edit import UpdateView
|
||||
from django.views.generic.edit import (
|
||||
UpdateView,
|
||||
CreateView,
|
||||
DeleteView,
|
||||
FormView
|
||||
)
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.http import HttpResponse
|
||||
from django.contrib import messages
|
||||
from idhub.user.forms import ProfileForm
|
||||
from apiregiter import iota
|
||||
from idhub.user.forms import ProfileForm, RequestCredentialForm, CredentialPresentationForm
|
||||
from idhub.mixins import UserView
|
||||
from idhub.models import DID, VerificableCredential
|
||||
|
||||
|
||||
class MyProfile(UserView):
|
||||
|
@ -14,7 +23,7 @@ class MyProfile(UserView):
|
|||
section = "MyProfile"
|
||||
|
||||
|
||||
class MyWallet(UserView, TemplateView):
|
||||
class MyWallet(UserView):
|
||||
title = _("My Wallet")
|
||||
section = "MyWallet"
|
||||
|
||||
|
@ -51,25 +60,178 @@ class UserGDPRView(MyProfile, TemplateView):
|
|||
icon = 'bi bi-file-earmark-medical'
|
||||
|
||||
|
||||
class UserIdentitiesView(MyWallet):
|
||||
template_name = "idhub/user/identities.html"
|
||||
subtitle = _('Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
|
||||
|
||||
class UserCredentialsView(MyWallet):
|
||||
class UserCredentialsView(MyWallet, TemplateView):
|
||||
template_name = "idhub/user/credentials.html"
|
||||
subtitle = _('Credentials')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'credentials': VerificableCredential.objects,
|
||||
})
|
||||
return context
|
||||
|
||||
class UserCredentialsRequiredView(MyWallet):
|
||||
template_name = "idhub/user/credentials_required.html"
|
||||
subtitle = _('Credentials required')
|
||||
|
||||
class UserCredentialView(MyWallet, TemplateView):
|
||||
template_name = "idhub/user/credential.html"
|
||||
subtitle = _('Credential')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(
|
||||
VerificableCredential,
|
||||
pk=self.pk,
|
||||
user=self.request.user
|
||||
)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
class UserCredentialsPresentationView(MyWallet):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'object': self.object,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class UserCredentialJsonView(MyWallet, TemplateView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
pk = kwargs['pk']
|
||||
self.object = get_object_or_404(
|
||||
VerificableCredential,
|
||||
pk=pk,
|
||||
user=self.request.user
|
||||
)
|
||||
response = HttpResponse(self.object.data, content_type="application/json")
|
||||
response['Content-Disposition'] = 'attachment; filename={}'.format("credential.json")
|
||||
return response
|
||||
|
||||
|
||||
class UserCredentialsRequestView(MyWallet, FormView):
|
||||
template_name = "idhub/user/credentials_request.html"
|
||||
subtitle = _('Credentials request')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
form_class = RequestCredentialForm
|
||||
success_url = reverse_lazy('idhub:user_credentials')
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['user'] = self.request.user
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
cred = form.save()
|
||||
if cred:
|
||||
messages.success(self.request, _("The credential was required successfully!"))
|
||||
else:
|
||||
messages.error(self.request, _("Not exists the credential!"))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class UserCredentialsPresentationView(MyWallet, FormView):
|
||||
template_name = "idhub/user/credentials_presentation.html"
|
||||
subtitle = _('Credentials Presentation')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
form_class = CredentialPresentationForm
|
||||
success_url = reverse_lazy('idhub:user_credentials')
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['user'] = self.request.user
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
cred = form.save()
|
||||
if cred:
|
||||
messages.success(self.request, _("The credential was presented successfully!"))
|
||||
else:
|
||||
messages.error(self.request, _("Error sending credential!"))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class UserDidsView(MyWallet, TemplateView):
|
||||
template_name = "idhub/user/dids.html"
|
||||
subtitle = _('Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'dids': self.request.user.dids,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class UserDidRegisterView(MyWallet, CreateView):
|
||||
template_name = "idhub/user/did_register.html"
|
||||
subtitle = _('Add a new Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
fields = ('did', 'label')
|
||||
success_url = reverse_lazy('idhub:user_dids')
|
||||
object = None
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['initial'] = {
|
||||
'did': iota.issue_did(),
|
||||
'user': self.request.user
|
||||
}
|
||||
return kwargs
|
||||
|
||||
def get_form(self):
|
||||
form = super().get_form()
|
||||
form.fields['did'].required = False
|
||||
form.fields['did'].disabled = True
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.save()
|
||||
messages.success(self.request, _('DID created successfully'))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class UserDidEditView(MyWallet, UpdateView):
|
||||
template_name = "idhub/user/did_register.html"
|
||||
subtitle = _('Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
fields = ('did', 'label')
|
||||
success_url = reverse_lazy('idhub:user_dids')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(self.model, pk=self.pk)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_form(self):
|
||||
form = super().get_form()
|
||||
form.fields['did'].required = False
|
||||
form.fields['did'].disabled = True
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
user = form.save()
|
||||
messages.success(self.request, _('DID updated successfully'))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class UserDidDeleteView(MyWallet, DeleteView):
|
||||
subtitle = _('Identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
success_url = reverse_lazy('idhub:user_dids')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.pk = kwargs['pk']
|
||||
self.object = get_object_or_404(self.model, pk=self.pk)
|
||||
self.object.delete()
|
||||
messages.success(self.request, _('DID delete successfully'))
|
||||
|
||||
return redirect(self.success_url)
|
||||
|
|
|
@ -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
|
||||
black==23.9.1
|
||||
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_extensions',
|
||||
'django_bootstrap5',
|
||||
'idhub_auth',
|
||||
'idhub'
|
||||
]
|
||||
|
||||
|
@ -160,6 +161,7 @@ MEDIA_URL = '/media/'
|
|||
STATIC_ROOT = config('STATIC_ROOT')
|
||||
MEDIA_ROOT = config('MEDIA_ROOT', default="idhub/upload")
|
||||
FIXTURE_DIRS = (os.path.join(BASE_DIR, 'fixtures'),)
|
||||
SCHEMAS_DIR = os.path.join(BASE_DIR, 'schemas')
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||
|
@ -176,3 +178,4 @@ MESSAGE_TAGS = {
|
|||
messages.ERROR: 'alert-danger',
|
||||
}
|
||||
|
||||
AUTH_USER_MODEL = 'idhub_auth.User'
|
||||
|
|
Loading…
Reference in New Issue