Merge branch 'release'
This commit is contained in:
commit
8c5d77acf6
52
.gitea/workflows/ci-pipeline.yaml
Normal file
52
.gitea/workflows/ci-pipeline.yaml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
name: Django CI Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- release
|
||||||
|
- testing-pipeline
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
env:
|
||||||
|
SECRET_KEY: "t3st-dummy-s3cr3t-k3y"
|
||||||
|
STATIC_ROOT: "tmp/static/"
|
||||||
|
MEDIA_ROOT: "tmp/media/"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install python3-venv
|
||||||
|
id: install
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install python3 python3-venv python3-pip -y
|
||||||
|
|
||||||
|
- name: Check Python version
|
||||||
|
run: |
|
||||||
|
python3 --version
|
||||||
|
echo "Python version: $(python3 --version)"
|
||||||
|
|
||||||
|
- name: Create virtual environment
|
||||||
|
run: |
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
echo "Virtual environment created successfully"
|
||||||
|
# https://docs.github.com/en/actions/learn-github-actions/contexts#steps-context
|
||||||
|
if: steps.install.outcome == 'success'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
source venv/bin/activate
|
||||||
|
python manage.py test
|
||||||
|
|
|
@ -74,7 +74,7 @@ class ImportForm(forms.Form):
|
||||||
(x.did, x.label) for x in dids.filter(eidas1=False)
|
(x.did, x.label) for x in dids.filter(eidas1=False)
|
||||||
]
|
]
|
||||||
self.fields['schema'].choices = [
|
self.fields['schema'].choices = [
|
||||||
(x.id, x.name()) for x in Schemas.objects.filter()
|
(x.id, x.name) for x in Schemas.objects.filter()
|
||||||
]
|
]
|
||||||
if dids.filter(eidas1=True).exists():
|
if dids.filter(eidas1=True).exists():
|
||||||
choices = [("", "")]
|
choices = [("", "")]
|
||||||
|
|
|
@ -1,25 +1,255 @@
|
||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.html import format_html
|
||||||
from idhub.models import Rol, Event
|
|
||||||
|
from idhub.models import (
|
||||||
|
Rol,
|
||||||
|
Event,
|
||||||
|
Service,
|
||||||
|
VerificableCredential,
|
||||||
|
DID,
|
||||||
|
File_datas,
|
||||||
|
Schemas
|
||||||
|
)
|
||||||
from idhub_auth.models import User
|
from idhub_auth.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class ButtonColumn(tables.Column):
|
||||||
|
attrs = {
|
||||||
|
"a": {
|
||||||
|
"type": "button",
|
||||||
|
"class": "text-primary",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# it makes no sense to order a column of buttons
|
||||||
|
orderable = False
|
||||||
|
# django_tables will only call the render function if it doesn't find
|
||||||
|
# any empty values in the data, so we stop it from matching the data
|
||||||
|
# to any value considered empty
|
||||||
|
empty_values = ()
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
return format_html('<i class="bi bi-eye"></i>')
|
||||||
|
|
||||||
|
|
||||||
class UserTable(tables.Table):
|
class UserTable(tables.Table):
|
||||||
|
view_user = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_people",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
membership = tables.Column(empty_values=())
|
||||||
|
role = tables.Column(empty_values=())
|
||||||
|
|
||||||
|
def render_view_user(self):
|
||||||
|
return format_html('<i class="bi bi-eye"></i>')
|
||||||
|
|
||||||
|
def render_membership(self, record):
|
||||||
|
return record.get_memberships()
|
||||||
|
|
||||||
|
def order_membership(self, queryset, is_descending):
|
||||||
|
# TODO: Test that this doesn't return more rows than it should
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "memberships__type"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
def render_role(self, record):
|
||||||
|
return record.get_roles()
|
||||||
|
|
||||||
|
def order_role(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "roles"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
template_name = "idhub/custom_table.html"
|
template_name = "idhub/custom_table.html"
|
||||||
fields = ("first_name", "last_name", "email", "is_active", "is_admin")
|
fields = ("last_name", "first_name", "email", "membership", "role",
|
||||||
|
"view_user")
|
||||||
|
|
||||||
|
|
||||||
class RolesTable(tables.Table):
|
class RolesTable(tables.Table):
|
||||||
|
view_role = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_rol_edit",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
delete_role = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_rol_del",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def render_view_role(self):
|
||||||
|
return format_html('<i class="bi bi-pencil-square"></i>')
|
||||||
|
|
||||||
|
def render_delete_role(self):
|
||||||
|
return format_html('<i class="bi bi-trash">')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Rol
|
model = Rol
|
||||||
template_name = "idhub/custom_table.html"
|
template_name = "idhub/custom_table.html"
|
||||||
fields = ("name", "description")
|
fields = ("name", "description")
|
||||||
|
|
||||||
|
|
||||||
|
class ServicesTable(tables.Table):
|
||||||
|
domain = tables.Column(verbose_name="Service")
|
||||||
|
role = tables.Column(empty_values=())
|
||||||
|
edit_service = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_service_edit",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
delete_service = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_service_del",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def render_role(self, record):
|
||||||
|
return record.get_roles()
|
||||||
|
|
||||||
|
def render_edit_service(self):
|
||||||
|
return format_html('<i class="bi bi-pencil-square"></i>')
|
||||||
|
|
||||||
|
def render_delete_service(self):
|
||||||
|
return format_html('<i class="bi bi-trash">')
|
||||||
|
|
||||||
|
def order_role(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "rol"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Service
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("domain", "description", "role",
|
||||||
|
"edit_service", "delete_service")
|
||||||
|
|
||||||
|
|
||||||
class DashboardTable(tables.Table):
|
class DashboardTable(tables.Table):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Event
|
model = Event
|
||||||
template_name = "idhub/custom_table.html"
|
template_name = "idhub/custom_table.html"
|
||||||
fields = ("type", "message", "created")
|
fields = ("type", "message", "created")
|
||||||
|
|
||||||
|
|
||||||
|
class CredentialTable(tables.Table):
|
||||||
|
type = tables.Column(empty_values=())
|
||||||
|
# Pending VerificableCredential description fix
|
||||||
|
details = tables.Column(empty_values=(), orderable=False)
|
||||||
|
issued_on = tables.Column(verbose_name="Issued")
|
||||||
|
view_credential = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_credential",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def render_type(self, record):
|
||||||
|
return record.type()
|
||||||
|
|
||||||
|
def render_details(self, record):
|
||||||
|
return record.description()
|
||||||
|
|
||||||
|
def render_view_credential(self):
|
||||||
|
return format_html('<i class="bi bi-eye"></i>')
|
||||||
|
|
||||||
|
def order_type(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "schema__type"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = VerificableCredential
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("type", "details", "issued_on", "status", "user")
|
||||||
|
|
||||||
|
|
||||||
|
class DIDTable(tables.Table):
|
||||||
|
created_at = tables.Column(verbose_name="Date")
|
||||||
|
did = tables.Column(verbose_name="ID")
|
||||||
|
edit_did = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_dids_edit",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False,
|
||||||
|
verbose_name="Edit DID"
|
||||||
|
)
|
||||||
|
delete_template_code = """<a class="text-danger"
|
||||||
|
href="javascript:void()"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#confirm-delete-{{ record.id }}"
|
||||||
|
title="Remove"
|
||||||
|
><i class="bi bi-trash"></i></a>"""
|
||||||
|
delete_did = tables.TemplateColumn(template_code=delete_template_code,
|
||||||
|
orderable=False,
|
||||||
|
verbose_name="Delete DID")
|
||||||
|
|
||||||
|
def render_edit_did(self):
|
||||||
|
return format_html('<i class="bi bi-pencil-square"></i>')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = DID
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("created_at", "label", "did", "edit_did", "delete_did")
|
||||||
|
|
||||||
|
|
||||||
|
class DataTable(tables.Table):
|
||||||
|
created_at = tables.Column(verbose_name="Date")
|
||||||
|
file_name = tables.Column(verbose_name="File")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = File_datas
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("created_at", "file_name", "success")
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateTable(tables.Table):
|
||||||
|
view_schema = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:admin_schemas_download",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
delete_template_code = """<a class="text-danger"
|
||||||
|
href="javascript:void()"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#confirm-delete-{{ record.id }}"
|
||||||
|
title="Remove"
|
||||||
|
><i class="bi bi-trash"></i></a>"""
|
||||||
|
delete_schema = tables.TemplateColumn(template_code=delete_template_code,
|
||||||
|
orderable=False,
|
||||||
|
verbose_name="Delete schema")
|
||||||
|
|
||||||
|
_name = tables.Column(verbose_name="Name")
|
||||||
|
_description = tables.Column(verbose_name="Description")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Schemas
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("created_at", "file_schema", "_name", "_description",
|
||||||
|
"view_schema", "delete_schema")
|
||||||
|
|
|
@ -8,6 +8,7 @@ from smtplib import SMTPException
|
||||||
from django_tables2 import SingleTableView
|
from django_tables2 import SingleTableView
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.template.loader import get_template
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic.base import TemplateView, View
|
from django.views.generic.base import TemplateView, View
|
||||||
from django.views.generic.edit import (
|
from django.views.generic.edit import (
|
||||||
|
@ -35,7 +36,14 @@ from idhub.admin.forms import (
|
||||||
ImportCertificateForm,
|
ImportCertificateForm,
|
||||||
)
|
)
|
||||||
from idhub.admin.tables import (
|
from idhub.admin.tables import (
|
||||||
DashboardTable
|
DashboardTable,
|
||||||
|
UserTable,
|
||||||
|
RolesTable,
|
||||||
|
ServicesTable,
|
||||||
|
CredentialTable,
|
||||||
|
DIDTable,
|
||||||
|
DataTable,
|
||||||
|
TemplateTable
|
||||||
)
|
)
|
||||||
from idhub.models import (
|
from idhub.models import (
|
||||||
DID,
|
DID,
|
||||||
|
@ -120,10 +128,12 @@ class ImportExport(AdminView):
|
||||||
section = "ImportExport"
|
section = "ImportExport"
|
||||||
|
|
||||||
|
|
||||||
class PeopleListView(People, TemplateView):
|
class PeopleListView(People, SingleTableView):
|
||||||
template_name = "idhub/admin/people.html"
|
template_name = "idhub/admin/people.html"
|
||||||
subtitle = _('View users')
|
subtitle = _('View users')
|
||||||
icon = 'bi bi-person'
|
icon = 'bi bi-person'
|
||||||
|
table_class = UserTable
|
||||||
|
model = User
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
@ -132,6 +142,11 @@ class PeopleListView(People, TemplateView):
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
queryset = super().get_queryset(**kwargs)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class PeopleView(People, TemplateView):
|
class PeopleView(People, TemplateView):
|
||||||
template_name = "idhub/admin/user.html"
|
template_name = "idhub/admin/user.html"
|
||||||
|
@ -440,17 +455,20 @@ class PeopleRolDeleteView(PeopleView):
|
||||||
return redirect('idhub:admin_people_edit', user.id)
|
return redirect('idhub:admin_people_edit', user.id)
|
||||||
|
|
||||||
|
|
||||||
class RolesView(AccessControl):
|
class RolesView(AccessControl, SingleTableView):
|
||||||
template_name = "idhub/admin/roles.html"
|
template_name = "idhub/admin/roles.html"
|
||||||
subtitle = _('Manage roles')
|
subtitle = _('Manage roles')
|
||||||
|
table_class = RolesTable
|
||||||
icon = ''
|
icon = ''
|
||||||
|
model = Rol
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
queryset = kwargs.pop('object_list', None)
|
||||||
context.update({
|
if queryset is None:
|
||||||
'roles': Rol.objects,
|
self.object_list = self.model.objects.all()
|
||||||
})
|
|
||||||
return context
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class RolRegisterView(AccessControl, CreateView):
|
class RolRegisterView(AccessControl, CreateView):
|
||||||
template_name = "idhub/admin/rol_register.html"
|
template_name = "idhub/admin/rol_register.html"
|
||||||
|
@ -504,17 +522,20 @@ class RolDeleteView(AccessControl):
|
||||||
return redirect('idhub:admin_roles')
|
return redirect('idhub:admin_roles')
|
||||||
|
|
||||||
|
|
||||||
class ServicesView(AccessControl):
|
class ServicesView(AccessControl, SingleTableView):
|
||||||
template_name = "idhub/admin/services.html"
|
template_name = "idhub/admin/services.html"
|
||||||
|
table_class = ServicesTable
|
||||||
subtitle = _('Manage services')
|
subtitle = _('Manage services')
|
||||||
icon = ''
|
icon = ''
|
||||||
|
model = Service
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
queryset = kwargs.pop('object_list', None)
|
||||||
context.update({
|
if queryset is None:
|
||||||
'services': Service.objects,
|
self.object_list = self.model.objects.all()
|
||||||
})
|
|
||||||
return context
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ServiceRegisterView(AccessControl, CreateView):
|
class ServiceRegisterView(AccessControl, CreateView):
|
||||||
template_name = "idhub/admin/service_register.html"
|
template_name = "idhub/admin/service_register.html"
|
||||||
|
@ -578,17 +599,19 @@ class ServiceDeleteView(AccessControl):
|
||||||
return redirect('idhub:admin_services')
|
return redirect('idhub:admin_services')
|
||||||
|
|
||||||
|
|
||||||
class CredentialsView(Credentials):
|
class CredentialsView(Credentials, SingleTableView):
|
||||||
template_name = "idhub/admin/credentials.html"
|
template_name = "idhub/admin/credentials.html"
|
||||||
|
table_class = CredentialTable
|
||||||
subtitle = _('View credentials')
|
subtitle = _('View credentials')
|
||||||
icon = ''
|
icon = ''
|
||||||
|
model = VerificableCredential
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
queryset = kwargs.pop('object_list', None)
|
||||||
context.update({
|
if queryset is None:
|
||||||
'credentials': VerificableCredential.objects,
|
self.object_list = self.model.objects.all()
|
||||||
})
|
|
||||||
return context
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CredentialView(Credentials):
|
class CredentialView(Credentials):
|
||||||
|
@ -667,19 +690,26 @@ class DeleteCredentialsView(Credentials):
|
||||||
return redirect(self.success_url)
|
return redirect(self.success_url)
|
||||||
|
|
||||||
|
|
||||||
class DidsView(Credentials):
|
class DidsView(Credentials, SingleTableView):
|
||||||
template_name = "idhub/admin/dids.html"
|
template_name = "idhub/admin/dids.html"
|
||||||
|
table_class = DIDTable
|
||||||
subtitle = _('Manage identities (DID)')
|
subtitle = _('Manage identities (DID)')
|
||||||
icon = 'bi bi-patch-check-fill'
|
icon = 'bi bi-patch-check-fill'
|
||||||
wallet = True
|
wallet = True
|
||||||
|
model = DID
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
queryset = kwargs.pop('object_list', None)
|
||||||
|
if queryset is None:
|
||||||
|
self.object_list = self.model.objects.all()
|
||||||
|
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context.update({
|
context.update({
|
||||||
'dids': DID.objects.filter(user=self.request.user),
|
'dids': DID.objects.filter(user=self.request.user),
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class DidRegisterView(Credentials, CreateView):
|
class DidRegisterView(Credentials, CreateView):
|
||||||
template_name = "idhub/admin/did_register.html"
|
template_name = "idhub/admin/did_register.html"
|
||||||
subtitle = _('Add a new organizational identity (DID)')
|
subtitle = _('Add a new organizational identity (DID)')
|
||||||
|
@ -699,7 +729,6 @@ class DidRegisterView(Credentials, CreateView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DidEditView(Credentials, UpdateView):
|
class DidEditView(Credentials, UpdateView):
|
||||||
template_name = "idhub/admin/did_register.html"
|
template_name = "idhub/admin/did_register.html"
|
||||||
subtitle = _('Organization Identities (DID)')
|
subtitle = _('Organization Identities (DID)')
|
||||||
|
@ -767,17 +796,19 @@ class WalletConfigIssuesView(Credentials, FormView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class SchemasView(SchemasMix):
|
class SchemasView(SchemasMix, SingleTableView):
|
||||||
template_name = "idhub/admin/schemas.html"
|
template_name = "idhub/admin/schemas.html"
|
||||||
|
table_class = TemplateTable
|
||||||
subtitle = _('View credential templates')
|
subtitle = _('View credential templates')
|
||||||
icon = ''
|
icon = ''
|
||||||
|
model = Schemas
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
queryset = kwargs.pop('object_list', None)
|
||||||
context.update({
|
if queryset is None:
|
||||||
'schemas': Schemas.objects,
|
self.object_list = self.model.objects.all()
|
||||||
})
|
|
||||||
return context
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SchemasDeleteView(SchemasMix):
|
class SchemasDeleteView(SchemasMix):
|
||||||
|
@ -876,7 +907,7 @@ class SchemasImportAddView(SchemasMix):
|
||||||
self.check_valid_user()
|
self.check_valid_user()
|
||||||
file_name = kwargs['file_schema']
|
file_name = kwargs['file_schema']
|
||||||
schemas_files = os.listdir(settings.SCHEMAS_DIR)
|
schemas_files = os.listdir(settings.SCHEMAS_DIR)
|
||||||
if not file_name in schemas_files:
|
if file_name not in schemas_files:
|
||||||
messages.error(self.request, f"The schema {file_name} not exist!")
|
messages.error(self.request, f"The schema {file_name} not exist!")
|
||||||
return redirect('idhub:admin_schemas_import')
|
return redirect('idhub:admin_schemas_import')
|
||||||
|
|
||||||
|
@ -897,7 +928,19 @@ class SchemasImportAddView(SchemasMix):
|
||||||
except Exception:
|
except Exception:
|
||||||
messages.error(self.request, _('This is not a valid schema!'))
|
messages.error(self.request, _('This is not a valid schema!'))
|
||||||
return
|
return
|
||||||
schema = Schemas.objects.create(file_schema=file_name, data=data, type=title)
|
|
||||||
|
_name = json.dumps(ldata.get('name', ''))
|
||||||
|
_description = json.dumps(ldata.get('description', ''))
|
||||||
|
|
||||||
|
schema = Schemas.objects.create(
|
||||||
|
file_schema=file_name,
|
||||||
|
data=data,
|
||||||
|
type=title,
|
||||||
|
_name=_name,
|
||||||
|
_description=_description,
|
||||||
|
# template_description=_description
|
||||||
|
template_description=self.get_description()
|
||||||
|
)
|
||||||
schema.save()
|
schema.save()
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
|
@ -909,11 +952,27 @@ class SchemasImportAddView(SchemasMix):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_template_description(self):
|
||||||
|
context = {}
|
||||||
|
template_name = 'credentials/{}'.format(
|
||||||
|
self.schema.file_schema
|
||||||
|
)
|
||||||
|
tmpl = get_template(template_name)
|
||||||
|
return tmpl.render(context)
|
||||||
|
|
||||||
class ImportView(ImportExport, TemplateView):
|
def get_description(self):
|
||||||
|
for des in json.loads(self.get_template_description()).get('description', []):
|
||||||
|
if settings.LANGUAGE_CODE == des.get('lang'):
|
||||||
|
return des.get('value', '')
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
class ImportView(ImportExport, SingleTableView):
|
||||||
template_name = "idhub/admin/import.html"
|
template_name = "idhub/admin/import.html"
|
||||||
|
table_class = DataTable
|
||||||
subtitle = _('Import data')
|
subtitle = _('Import data')
|
||||||
icon = ''
|
icon = ''
|
||||||
|
model = File_datas
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
@ -965,4 +1024,3 @@ class ImportAddView(NotifyActivateUserByEmail, ImportExport, FormView):
|
||||||
messages.error(self.request, e)
|
messages.error(self.request, e)
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
293
idhub/management/commands/create_example_data.py
Normal file
293
idhub/management/commands/create_example_data.py
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
import random
|
||||||
|
from typing import Type, Callable, List
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import models, IntegrityError
|
||||||
|
|
||||||
|
from idhub.models import Event, Rol, Service, UserRol
|
||||||
|
from idhub_auth.models import User
|
||||||
|
|
||||||
|
from faker import Faker
|
||||||
|
|
||||||
|
DEFAULT_OBJECTS_CREATED: int = 30
|
||||||
|
RANDOM_STRING_LENGTH: int = 30
|
||||||
|
EMAIL_RANDOM_STRING_LENGTH: int = 10
|
||||||
|
EXISTING_EVENTS: int = 30
|
||||||
|
|
||||||
|
fake = Faker()
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""
|
||||||
|
Populate the database with dummy values.
|
||||||
|
You can either specify which model to create objects for,
|
||||||
|
or create objects for all models.
|
||||||
|
If no data is specified it will create 30 events, users,
|
||||||
|
services, roles, and user roles.
|
||||||
|
"""
|
||||||
|
|
||||||
|
help = 'Populate the database with dummy values for testing.'
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
In the context of a Django management command,
|
||||||
|
initializing lists like created_users in the constructor ensures
|
||||||
|
that each run of the command has its own set of users, services,
|
||||||
|
roles, etc., and does not unintentionally share or retain state
|
||||||
|
across different invocations of the command.
|
||||||
|
"""
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.created_users = []
|
||||||
|
self.created_services = []
|
||||||
|
self.created_roles = []
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
any_option_used = self.process_options(options)
|
||||||
|
|
||||||
|
if not any_option_used:
|
||||||
|
self.create_all()
|
||||||
|
|
||||||
|
def process_options(self, input_options):
|
||||||
|
option_methods = {
|
||||||
|
'events': self.create_events,
|
||||||
|
'users': self.create_users,
|
||||||
|
'superusers': self.create_superusers,
|
||||||
|
'services': self.create_services,
|
||||||
|
'roles': self.create_roles,
|
||||||
|
'userroles': self.create_user_roles,
|
||||||
|
'userrole': self.create_specific_user_role,
|
||||||
|
'register': self.register_user,
|
||||||
|
'register_superuser': self.register_superuser,
|
||||||
|
'amount': self.create_all
|
||||||
|
}
|
||||||
|
|
||||||
|
any_option_used = self.match_input_to_options(input_options,
|
||||||
|
option_methods)
|
||||||
|
|
||||||
|
return any_option_used
|
||||||
|
|
||||||
|
def match_input_to_options(self, input_options, option_methods):
|
||||||
|
any_option_used = False
|
||||||
|
|
||||||
|
for option, method in option_methods.items():
|
||||||
|
is_valid_option = option in input_options and input_options[
|
||||||
|
option] is not None
|
||||||
|
if is_valid_option:
|
||||||
|
self.call_selected_method(input_options, method, option)
|
||||||
|
any_option_used = True
|
||||||
|
|
||||||
|
return any_option_used
|
||||||
|
|
||||||
|
def call_selected_method(self, input_options, method, option):
|
||||||
|
args = self.create_argument_list(input_options, option)
|
||||||
|
method(*args)
|
||||||
|
|
||||||
|
def create_argument_list(self, input_options, option):
|
||||||
|
if isinstance(input_options[option], list):
|
||||||
|
args = input_options[option]
|
||||||
|
else:
|
||||||
|
args = [input_options[option]]
|
||||||
|
return args
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
'--amount', type=int, action='store',
|
||||||
|
help='Create N objects (includes events, users, services, roles, and user roles)'
|
||||||
|
)
|
||||||
|
parser.add_argument('--events', type=int,
|
||||||
|
help='Create the specified number of events')
|
||||||
|
parser.add_argument('--users', type=int,
|
||||||
|
help='Create the specified number of users')
|
||||||
|
parser.add_argument('--superusers', type=int,
|
||||||
|
help='Create the specified number of superusers')
|
||||||
|
parser.add_argument('--services', type=int,
|
||||||
|
help='Create the specified number of services')
|
||||||
|
parser.add_argument('--roles', type=int,
|
||||||
|
help='Create the specified number of roles')
|
||||||
|
parser.add_argument('--userroles', type=int,
|
||||||
|
help='Create the specified number of user roles')
|
||||||
|
parser.add_argument(
|
||||||
|
'--userrole', nargs=2, type=str,
|
||||||
|
help='Create a user role for user U and service S',
|
||||||
|
metavar=('U', 'S'),
|
||||||
|
)
|
||||||
|
parser.add_argument('--register', nargs=2, type=str,
|
||||||
|
help='Create a user with email EMAIL and password PW',
|
||||||
|
metavar=('EMAIL', 'PW'))
|
||||||
|
parser.add_argument('--register-superuser', nargs=2, type=str,
|
||||||
|
help='Create a superuser with email EMAIL and '
|
||||||
|
'password PW',
|
||||||
|
metavar=('EMAIL', 'PW'))
|
||||||
|
|
||||||
|
def register_user(self, email: str, password: str):
|
||||||
|
"""
|
||||||
|
Register a new user with the given email and password from the command line.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.create_user(email, password)
|
||||||
|
self.stdout.write(f"Successfully registered user: {email}")
|
||||||
|
except IntegrityError:
|
||||||
|
self.stdout.write(f"Failed to register user: {email}")
|
||||||
|
|
||||||
|
def register_superuser(self, email: str, password: str):
|
||||||
|
"""
|
||||||
|
Register a new superuser with the given email and password from the command line.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.create_superuser(email, password)
|
||||||
|
self.stdout.write(f"Successfully registered superuser: {email}")
|
||||||
|
except IntegrityError:
|
||||||
|
self.stdout.write(f"Failed to register superuser: {email}")
|
||||||
|
|
||||||
|
def create_all(self, amount=DEFAULT_OBJECTS_CREATED):
|
||||||
|
self.create_events(amount)
|
||||||
|
self.create_users(amount)
|
||||||
|
self.create_roles(amount)
|
||||||
|
self.create_services(amount)
|
||||||
|
self.create_user_roles(amount)
|
||||||
|
|
||||||
|
def create_objects(self, model: Type[models.Model],
|
||||||
|
data_generator: Callable, amount: int) -> List[
|
||||||
|
models.Model]:
|
||||||
|
"""
|
||||||
|
Generic method to create objects for a given model and keep track of them.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model: The Django model class for which objects are to be created.
|
||||||
|
data_generator: A function that returns a dictionary of attributes for creating a model instance.
|
||||||
|
amount: The number of objects to create.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of successfully created model instances.
|
||||||
|
"""
|
||||||
|
created_objects = []
|
||||||
|
for _ in range(amount):
|
||||||
|
try:
|
||||||
|
model_instance = self.create_from_data(data_generator, model)
|
||||||
|
created_objects.append(model_instance)
|
||||||
|
except IntegrityError:
|
||||||
|
self.print_failure_message(model)
|
||||||
|
|
||||||
|
self.print_amount_created(created_objects, model)
|
||||||
|
return created_objects
|
||||||
|
|
||||||
|
def create_users(self, amount: int):
|
||||||
|
def user_data():
|
||||||
|
return {
|
||||||
|
'email': fake.email(),
|
||||||
|
'first_name': fake.first_name(),
|
||||||
|
'last_name': fake.last_name()
|
||||||
|
}
|
||||||
|
created_users = self.create_objects(User, user_data, amount)
|
||||||
|
self.created_users.extend(created_users)
|
||||||
|
|
||||||
|
def create_events(self, amount: int, user=None):
|
||||||
|
def event_data():
|
||||||
|
return {
|
||||||
|
'type': random.randint(1, EXISTING_EVENTS),
|
||||||
|
'message': fake.paragraph(nb_sentences=3),
|
||||||
|
'user': user
|
||||||
|
}
|
||||||
|
self.create_objects(Event, event_data, amount)
|
||||||
|
|
||||||
|
def create_superusers(self, amount=0):
|
||||||
|
"""Superusers can only be created from the specific command"""
|
||||||
|
created_superuser_amount = 0
|
||||||
|
for value in range(0, amount):
|
||||||
|
email = fake.email()
|
||||||
|
try:
|
||||||
|
User.objects.create_superuser(email)
|
||||||
|
created_superuser_amount += 1
|
||||||
|
except IntegrityError:
|
||||||
|
self.stdout.write("Couldn't create superuser " + email)
|
||||||
|
self.stdout.write(f"Created {created_superuser_amount} users")
|
||||||
|
|
||||||
|
def create_services(self, amount: int):
|
||||||
|
def service_data():
|
||||||
|
domain = fake.text(max_nb_chars=200)
|
||||||
|
description = fake.text(max_nb_chars=250)
|
||||||
|
return {
|
||||||
|
'domain': domain,
|
||||||
|
'description': description,
|
||||||
|
}
|
||||||
|
|
||||||
|
created_services = self.create_objects(Service, service_data, amount)
|
||||||
|
self.associate_random_roles(created_services)
|
||||||
|
self.created_services.extend(created_services)
|
||||||
|
|
||||||
|
def create_roles(self, amount: int):
|
||||||
|
def role_data():
|
||||||
|
name = fake.job()
|
||||||
|
description = fake.text(max_nb_chars=250)
|
||||||
|
return {'name': name, 'description': description}
|
||||||
|
|
||||||
|
created_roles = self.create_objects(Rol, role_data, amount)
|
||||||
|
self.created_roles.extend(created_roles)
|
||||||
|
|
||||||
|
def create_user_roles(self, amount: int, user_id=None, service_id=None):
|
||||||
|
def user_role_data():
|
||||||
|
user = self.get_or_create_user(user_id)
|
||||||
|
service = self.get_or_create_service(service_id)
|
||||||
|
return {"user": user, "service": service}
|
||||||
|
|
||||||
|
self.create_objects(UserRol, user_role_data, amount)
|
||||||
|
|
||||||
|
def create_specific_user_role(self, user, service):
|
||||||
|
self.create_user_roles(1, user, service)
|
||||||
|
|
||||||
|
def create_user(self, email: str, password: str):
|
||||||
|
User.objects.create_user(email, password)
|
||||||
|
|
||||||
|
def create_superuser(self, email: str, password: str):
|
||||||
|
User.objects.create_superuser(email, password)
|
||||||
|
|
||||||
|
def print_failure_message(self, model):
|
||||||
|
self.stdout.write(f"Couldn't create {model.__name__} object.")
|
||||||
|
|
||||||
|
def print_amount_created(self, created_objects, model):
|
||||||
|
self.stdout.write(f"Created {len(created_objects)} "
|
||||||
|
f"{model.__name__} objects")
|
||||||
|
|
||||||
|
def create_from_data(self, data_generator, model):
|
||||||
|
model_instance = model.objects.create(**data_generator())
|
||||||
|
return model_instance
|
||||||
|
|
||||||
|
def associate_random_roles(self, created_services):
|
||||||
|
for service in created_services:
|
||||||
|
self.associate_service_to_random_roles(service)
|
||||||
|
|
||||||
|
def associate_service_to_random_roles(self, service):
|
||||||
|
associated_roles = [self.get_or_create_role() for _ in range(
|
||||||
|
random.randint(0, 2))]
|
||||||
|
service.rol.set(associated_roles)
|
||||||
|
|
||||||
|
def get_or_create_user(self, user_id):
|
||||||
|
if user_id is not None:
|
||||||
|
user = User.objects.get(user_id=user_id)
|
||||||
|
elif len(self.created_users) != 0:
|
||||||
|
user = random.choice(self.created_users)
|
||||||
|
else:
|
||||||
|
self.create_users(1)
|
||||||
|
user = self.created_users[0]
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
def get_or_create_service(self, service_id):
|
||||||
|
if service_id is not None:
|
||||||
|
service = Service.objects.get(service_id=service_id)
|
||||||
|
elif len(self.created_services) != 0:
|
||||||
|
service = random.choice(self.created_services)
|
||||||
|
else:
|
||||||
|
self.create_services(1)
|
||||||
|
service = self.created_services[0]
|
||||||
|
|
||||||
|
return service
|
||||||
|
|
||||||
|
def get_or_create_role(self):
|
||||||
|
if len(self.created_roles) != 0:
|
||||||
|
role = random.choice(self.created_roles)
|
||||||
|
else:
|
||||||
|
self.create_roles(1)
|
||||||
|
role = self.created_roles[0]
|
||||||
|
|
||||||
|
return role
|
|
@ -95,16 +95,18 @@ class Command(BaseCommand):
|
||||||
assert title
|
assert title
|
||||||
except Exception:
|
except Exception:
|
||||||
title = ''
|
title = ''
|
||||||
return
|
_name = ''
|
||||||
name = ''
|
|
||||||
try:
|
|
||||||
for x in dname:
|
|
||||||
if settings.LANGUAGE_CODE in x['lang']:
|
|
||||||
name = x.get('value', '')
|
|
||||||
except Exception:
|
|
||||||
return
|
|
||||||
|
|
||||||
Schemas.objects.create(file_schema=file_name, data=data, type=title)
|
_name = json.dumps(ldata.get('name', ''))
|
||||||
|
_description = json.dumps(ldata.get('description', ''))
|
||||||
|
|
||||||
|
Schemas.objects.create(
|
||||||
|
file_schema=file_name,
|
||||||
|
data=data,
|
||||||
|
type=title,
|
||||||
|
_name=_name,
|
||||||
|
_description=_description
|
||||||
|
)
|
||||||
|
|
||||||
def open_file(self, file_name):
|
def open_file(self, file_name):
|
||||||
data = ''
|
data = ''
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2024-01-20 14:29
|
# Generated by Django 4.2.5 on 2024-01-22 15:44
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -102,6 +102,14 @@ class Migration(migrations.Migration):
|
||||||
('file_schema', models.CharField(max_length=250)),
|
('file_schema', models.CharField(max_length=250)),
|
||||||
('data', models.TextField()),
|
('data', models.TextField()),
|
||||||
('created_at', models.DateTimeField(auto_now=True)),
|
('created_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('_name', models.TextField(db_column='name', null=True)),
|
||||||
|
(
|
||||||
|
'_description',
|
||||||
|
models.CharField(
|
||||||
|
db_column='description', max_length=250, null=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('template_description', models.TextField(null=True)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
@ -315,6 +323,7 @@ class Migration(migrations.Migration):
|
||||||
(28, 'Organisational DID deleted by admin'),
|
(28, 'Organisational DID deleted by admin'),
|
||||||
(29, 'User deactivated'),
|
(29, 'User deactivated'),
|
||||||
(30, 'User activated'),
|
(30, 'User activated'),
|
||||||
|
(31, 'User send Verificable Presentation'),
|
||||||
],
|
],
|
||||||
verbose_name='Event',
|
verbose_name='Event',
|
||||||
),
|
),
|
||||||
|
|
|
@ -473,6 +473,9 @@ class Schemas(models.Model):
|
||||||
file_schema = models.CharField(max_length=250)
|
file_schema = models.CharField(max_length=250)
|
||||||
data = models.TextField()
|
data = models.TextField()
|
||||||
created_at = models.DateTimeField(auto_now=True)
|
created_at = models.DateTimeField(auto_now=True)
|
||||||
|
_name = models.TextField(null=True, db_column='name')
|
||||||
|
_description = models.CharField(max_length=250, null=True, db_column='description')
|
||||||
|
template_description = models.TextField(null=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def get_schema(self):
|
def get_schema(self):
|
||||||
|
@ -480,22 +483,62 @@ class Schemas(models.Model):
|
||||||
return {}
|
return {}
|
||||||
return json.loads(self.data)
|
return json.loads(self.data)
|
||||||
|
|
||||||
|
def _update_and_get_field(self, field_attr, schema_key, is_json=False):
|
||||||
|
field_value = getattr(self, field_attr)
|
||||||
|
if not field_value:
|
||||||
|
field_value = self.get_schema.get(schema_key, [] if is_json else '')
|
||||||
|
self._update_model_field(field_attr, field_value)
|
||||||
|
try:
|
||||||
|
if is_json:
|
||||||
|
return json.loads(field_value)
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
return field_value
|
||||||
|
return field_value
|
||||||
|
|
||||||
|
def _update_model_field(self, field_attr, field_value):
|
||||||
|
if field_value:
|
||||||
|
setattr(self, field_attr, field_value)
|
||||||
|
self.save(update_fields=[field_attr])
|
||||||
|
|
||||||
|
@property
|
||||||
def name(self, request=None):
|
def name(self, request=None):
|
||||||
names = {}
|
names = self._update_and_get_field('_name', 'name',
|
||||||
for name in self.get_schema.get('name', []):
|
is_json=True)
|
||||||
lang = name.get('lang')
|
language_code = self._get_language_code(request)
|
||||||
if 'ca' in lang:
|
name = self._get_name_by_language(names, language_code)
|
||||||
lang = 'ca'
|
|
||||||
names[lang]= name.get('value')
|
|
||||||
|
|
||||||
if request and request.LANGUAGE_CODE in names.keys():
|
return name
|
||||||
return names[request.LANGUAGE_CODE]
|
|
||||||
|
|
||||||
return names[settings.LANGUAGE_CODE]
|
def _get_language_code(self, request=None):
|
||||||
|
language_code = settings.LANGUAGE_CODE
|
||||||
|
if request:
|
||||||
|
language_code = request.LANGUAGE_CODE
|
||||||
|
if self._is_catalan_code(language_code):
|
||||||
|
language_code = 'ca'
|
||||||
|
|
||||||
|
return language_code
|
||||||
|
|
||||||
|
def _get_name_by_language(self, names, lang_code):
|
||||||
|
for name in names:
|
||||||
|
if name.get('lang') == lang_code:
|
||||||
|
return name.get('value')
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _is_catalan_code(self, language_code):
|
||||||
|
return language_code == 'ca_ES'
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, value):
|
||||||
|
self._name = json.dumps(value)
|
||||||
|
|
||||||
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return self.get_schema.get('description', '')
|
return self._update_and_get_field('_description', 'description')
|
||||||
|
|
||||||
|
@description.setter
|
||||||
|
def description(self, value):
|
||||||
|
self._description = value
|
||||||
|
|
||||||
class VerificableCredential(models.Model):
|
class VerificableCredential(models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -559,6 +602,9 @@ class VerificableCredential(models.Model):
|
||||||
def type(self):
|
def type(self):
|
||||||
return self.schema.type
|
return self.schema.type
|
||||||
|
|
||||||
|
def get_description(self):
|
||||||
|
return self.schema._description or ''
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
for des in json.loads(self.render("")).get('description', []):
|
for des in json.loads(self.render("")).get('description', []):
|
||||||
if settings.LANGUAGE_CODE in des.get('lang'):
|
if settings.LANGUAGE_CODE in des.get('lang'):
|
||||||
|
@ -652,7 +698,6 @@ class VerificableCredential(models.Model):
|
||||||
d_minimum = self.filter_dict(d_ordered)
|
d_minimum = self.filter_dict(d_ordered)
|
||||||
return ujson.dumps(d_minimum)
|
return ujson.dumps(d_minimum)
|
||||||
|
|
||||||
|
|
||||||
def get_issued_on(self):
|
def get_issued_on(self):
|
||||||
if self.issued_on:
|
if self.issued_on:
|
||||||
return self.issued_on.strftime("%m/%d/%Y")
|
return self.issued_on.strftime("%m/%d/%Y")
|
||||||
|
@ -732,7 +777,7 @@ class Service(models.Model):
|
||||||
|
|
||||||
def get_roles(self):
|
def get_roles(self):
|
||||||
if self.rol.exists():
|
if self.rol.exists():
|
||||||
return ", ".join([x.name for x in self.rol.all()])
|
return ", ".join([x.name for x in self.rol.order_by("name")])
|
||||||
return _("None")
|
return _("None")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -1,39 +1,11 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
{% render_table table %}
|
||||||
<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 'Issued' %}</button></th>
|
|
||||||
<th scope="col" class="text-center"><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.get_type }}</td>
|
|
||||||
<td>{{ f.description }}</td>
|
|
||||||
<td>{{ f.get_issued_on }}</td>
|
|
||||||
<td class="text-center">{{ f.get_status }}</td>
|
|
||||||
<td>{{ f.user.email }}</td>
|
|
||||||
<td><a href="{% url 'idhub:admin_credential' f.id %}" class="text-primary" title="{% trans 'View' %}"><i class="bi bi-eye"></i></a></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -8,6 +9,8 @@
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
<div class="row mt-5">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
{% render_table table %}
|
||||||
|
{% comment %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-striped table-sm">
|
<table class="table table-striped table-sm">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -31,6 +34,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{% endcomment %}
|
||||||
<div class="form-actions-no-box">
|
<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>
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_dids_new' %}">{% translate "Add identity" %} <i class="bi bi-plus"></i></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,36 +1,14 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
{% render_table table %}
|
||||||
<div class="col">
|
<div class="form-actions-no-box">
|
||||||
<div class="table-responsive">
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_import_add' %}">{% translate "Import data" %} <i class="bi bi-plus"></i></a>
|
||||||
<table class="table table-striped table-sm">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Created' %}</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_add' %}">{% translate "Import data" %} <i class="bi bi-plus"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,39 +1,11 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="table-responsive">
|
{% render_table table %}
|
||||||
<table class="table table-striped table-sm">
|
|
||||||
<thead>
|
|
||||||
<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">Email</button></th>
|
|
||||||
<th scope="col" class="text-center"><button type="button" class="btn btn-grey border border-dark">{% trans 'Membership' %}</button></th>
|
|
||||||
<th scope="col" class="text-center"><button type="button" class="btn btn-grey border border-dark">{% trans 'Role' %}</button></th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for user in users %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ user.last_name|default:'' }}</td>
|
|
||||||
<td>{{ user.first_name|default:'' }}</td>
|
|
||||||
<td>{{ user.email }}</td>
|
|
||||||
<td class="text-center">
|
|
||||||
{{ user.get_memberships }}
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
{{ user.get_roles }}
|
|
||||||
</td>
|
|
||||||
<td><a type="button" class="text-primary" href="{% url 'idhub:admin_people' user.id %}" title="{% trans 'View' %}"><i class="bi bi-eye"></i></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -8,31 +9,10 @@
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
<div class="row mt-5">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="table-responsive">
|
{% render_table table %}
|
||||||
<table class="table table-striped table-sm">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Role' %}</button></th>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Description' %}</button></th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for rol in roles.all %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ rol.name }}</td>
|
|
||||||
<td>{{ rol.description|default:""}}</td>
|
|
||||||
<td><a href="{% url 'idhub:admin_rol_edit' rol.id %}" title="{% trans 'Edit' %}"><i class="bi bi-pencil-square"></i></a></td>
|
|
||||||
<td><a class="text-danger" href="{% url 'idhub:admin_rol_del' rol.id %}" title="{% trans 'Delete' %}"><i class="bi bi-trash"></i></a></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="form-actions-no-box">
|
<div class="form-actions-no-box">
|
||||||
<a class="btn btn-green-admin" href="{% url 'idhub:admin_rol_new' %}">{% translate "Add Role" %} <i class="bi bi-plus"></i></a>
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_rol_new' %}">{% translate "Add Role" %} <i class="bi bi-plus"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,47 +1,19 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
{% render_table table %}
|
||||||
<div class="col">
|
<div class="form-actions-no-box">
|
||||||
<div class="table-responsive">
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_schemas_import' %}">{% translate "Add template" %} <i class="bi bi-plus"></i></a>
|
||||||
<table class="table table-striped table-sm">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Created' %}</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="text-primary" href="{% url 'idhub:admin_schemas_download' schema.id %}" target="_blank" title="{% trans 'View' %}"><i class="bi bi-eye"></i></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-trash"></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>
|
</div>
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
{% for schema in schemas.all %}
|
{% for schema in object_list %}
|
||||||
<div class="modal" id="confirm-delete-{{ schema.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
<div class="modal" id="confirm-delete-{{ schema.id }}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "idhub/base_admin.html" %}
|
{% extends "idhub/base_admin.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -8,33 +9,10 @@
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
<div class="row mt-5">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="table-responsive">
|
{% render_table table %}
|
||||||
<table class="table table-striped table-sm">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Service' %}</button></th>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Description' %}</button></th>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Role' %}</button></th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for service in services.all %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ service.domain }}</td>
|
|
||||||
<td>{{ service.description }}</td>
|
|
||||||
<td>{{ service.get_roles }}</td>
|
|
||||||
<td><a href="{% url 'idhub:admin_service_edit' service.id %}" title="{% trans 'Edit' %}"><i class="bi bi-pencil-square"></i></a></td>
|
|
||||||
<td><a class="text-danger" href="{% url 'idhub:admin_service_del' service.id %}" title="{% trans 'Delete' %}"><i class="bi bi-trash"></i></a></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="form-actions-no-box">
|
<div class="form-actions-no-box">
|
||||||
<a class="btn btn-green-admin" href="{% url 'idhub:admin_service_new' %}">{% translate "Add service" %} <i class="bi bi-plus"></i></a>
|
<a class="btn btn-green-admin" href="{% url 'idhub:admin_service_new' %}">{% translate "Add service" %} <i class="bi bi-plus"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,39 +1,11 @@
|
||||||
{% extends "idhub/base.html" %}
|
{% extends "idhub/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
{% render_table table %}
|
||||||
<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 'Issued' %}</button></th>
|
|
||||||
<th scope="col" class="text-center"><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.get_type }}</td>
|
|
||||||
<td>{{ f.description }}</td>
|
|
||||||
<td>{{ f.get_issued_on }}</td>
|
|
||||||
<td class="text-center">{{ f.get_status }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'idhub:user_credential' f.id %}" class="text-primary" title="{% trans 'View' %}"><i class="bi bi-eye"></i></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,29 +1,12 @@
|
||||||
{% extends "idhub/base.html" %}
|
{% extends "idhub/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="table-responsive">
|
{% render_table table %}
|
||||||
<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 'Description' %}</button></th>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Date' %}</button></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for ev in user.events.all %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ ev.get_type_name }}</td>
|
|
||||||
<td>{{ ev.message }}</td>
|
|
||||||
<td>{{ ev.created }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,41 +1,15 @@
|
||||||
{% extends "idhub/base.html" %}
|
{% extends "idhub/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
{% render_table table %}
|
||||||
<div class="col">
|
<div class="form-actions-no-box">
|
||||||
<div class="table-responsive">
|
<a class="btn btn-green-user" href="{% url 'idhub:user_dids_new' %}">{% translate "Add Identity" %} <i class="bi bi-plus"></i></a>
|
||||||
<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-trash"></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>
|
</div>
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
{% for d in dids.all %}
|
{% for d in dids.all %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "idhub/base.html" %}
|
{% extends "idhub/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -33,33 +34,6 @@
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
</form>
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
|
{% render_table table %}
|
||||||
|
|
||||||
<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" title="{% trans 'View' %}"><i class="bi bi-eye"></i></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,35 +1,12 @@
|
||||||
{% extends "idhub/base.html" %}
|
{% extends "idhub/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>
|
<h3>
|
||||||
<i class="{{ icon }}"></i>
|
<i class="{{ icon }}"></i>
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row mt-5">
|
{% render_table table %}
|
||||||
<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 'Role' %}</button></th>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Description' %}</button></th>
|
|
||||||
<th scope="col"><button type="button" class="btn btn-grey border border-dark">{% trans 'Service' %}</button></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for rol in user.roles.all %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ rol.service.get_roles }}</td>
|
|
||||||
<td>{{ rol.service.description }}</td>
|
|
||||||
<td>{{ rol.service.domain }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from idhub.models import Event
|
from idhub.models import Event, Membership, Rol, UserRol, Service
|
||||||
from idhub_auth.models import User
|
from idhub_auth.models import User
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,4 +14,60 @@ class EventModelTest(TestCase):
|
||||||
self.assertEqual(event.message, 'Test Event')
|
self.assertEqual(event.message, 'Test Event')
|
||||||
self.assertEqual(event.get_type_name(), 'User registered')
|
self.assertEqual(event.get_type_name(), 'User registered')
|
||||||
|
|
||||||
# Add more tests for other model methods and properties
|
|
||||||
|
class UserTest(TestCase):
|
||||||
|
"""
|
||||||
|
Tests the very basic aspects of the User model,
|
||||||
|
like field properties and methods behaving as expected.
|
||||||
|
Further testing is recommended.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.user = User.objects.create(
|
||||||
|
email="test@example.com",
|
||||||
|
is_admin=True,
|
||||||
|
first_name="Dummy",
|
||||||
|
last_name="Dummyson"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_field_properties(self):
|
||||||
|
user = User.objects.get(email="test@example.com")
|
||||||
|
self.assertEqual(user._meta.get_field('email').max_length, 255)
|
||||||
|
self.assertTrue(user._meta.get_field('email').unique)
|
||||||
|
self.assertTrue(user._meta.get_field('is_active').default)
|
||||||
|
self.assertFalse(user._meta.get_field('is_admin').default)
|
||||||
|
|
||||||
|
def test_string_representation(self):
|
||||||
|
self.assertEqual(str(self.user), "test@example.com")
|
||||||
|
|
||||||
|
def test_has_perm(self):
|
||||||
|
self.assertTrue(self.user.has_perm(None))
|
||||||
|
|
||||||
|
def test_has_module_perms(self):
|
||||||
|
self.assertTrue(self.user.has_module_perms(None))
|
||||||
|
|
||||||
|
def test_is_staff_property(self):
|
||||||
|
self.assertTrue(self.user.is_staff)
|
||||||
|
|
||||||
|
def test_get_memberships(self):
|
||||||
|
Membership.objects.create(user=self.user,
|
||||||
|
type=Membership.Types.BENEFICIARY)
|
||||||
|
Membership.objects.create(user=self.user,
|
||||||
|
type=Membership.Types.EMPLOYEE)
|
||||||
|
|
||||||
|
# We test for the length because the order in which the string
|
||||||
|
# is given in get_memberships is non-deterministic
|
||||||
|
self.assertEqual(len(self.user.get_memberships()),
|
||||||
|
len("Beneficiary, Employee"))
|
||||||
|
|
||||||
|
def test_get_roles(self):
|
||||||
|
user = User.objects.get(email="test@example.com")
|
||||||
|
service = Service.objects.create(domain="Test Service")
|
||||||
|
role1 = Rol.objects.create(name="Role 1")
|
||||||
|
role2 = Rol.objects.create(name="Role 2")
|
||||||
|
service.rol.add(role1, role2)
|
||||||
|
UserRol.objects.create(user=user, service=service)
|
||||||
|
|
||||||
|
# We test for the length because the order in which the string
|
||||||
|
# is given in get_roles is non-deterministic
|
||||||
|
self.assertEqual(len(user.get_roles()), len("Role 1, Role 2"))
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.core.exceptions import FieldError
|
||||||
|
|
||||||
from idhub_auth.models import User
|
from idhub_auth.models import User
|
||||||
from idhub.admin.tables import DashboardTable
|
from idhub.admin.tables import DashboardTable, UserTable, TemplateTable
|
||||||
from idhub.models import Event
|
from idhub.models import Event, Membership, Rol, UserRol, Service, Schemas
|
||||||
|
|
||||||
|
|
||||||
class AdminDashboardTableTest(TestCase):
|
class AdminDashboardTableTest(TestCase):
|
||||||
|
@ -63,3 +65,82 @@ class AdminDashboardTableTest(TestCase):
|
||||||
def test_pagination(self):
|
def test_pagination(self):
|
||||||
# TODO
|
# TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UserTableTest(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.user1 = User.objects.create(email="user1@example.com")
|
||||||
|
self.user2 = User.objects.create(email="user2@example.com")
|
||||||
|
Membership.objects.create(user=self.user1,
|
||||||
|
type=Membership.Types.BENEFICIARY)
|
||||||
|
|
||||||
|
# Set up roles and services
|
||||||
|
service = Service.objects.create(domain="Test Service")
|
||||||
|
role = Rol.objects.create(name="Role 1")
|
||||||
|
service.rol.add(role)
|
||||||
|
UserRol.objects.create(user=self.user1, service=service)
|
||||||
|
|
||||||
|
self.table = UserTable(User.objects.all())
|
||||||
|
|
||||||
|
def test_membership_column_render(self):
|
||||||
|
# Get the user instance for the first row
|
||||||
|
user = self.table.rows[0].record
|
||||||
|
# Use the render_membership method of UserTable
|
||||||
|
rendered_column = self.table.columns['membership'].render(user)
|
||||||
|
self.assertIn("Beneficiary", str(rendered_column))
|
||||||
|
|
||||||
|
def test_role_column_render(self):
|
||||||
|
# Get the user instance for the first row
|
||||||
|
user = self.table.rows[0].record
|
||||||
|
# Use the render_role method of UserTable
|
||||||
|
rendered_column = self.table.columns['role'].render(user)
|
||||||
|
self.assertIn("Role 1", str(rendered_column))
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateTableTest(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.table = TemplateTable(Schemas.objects.all())
|
||||||
|
self.create_schemas(amount=3)
|
||||||
|
|
||||||
|
def create_schemas(self, amount):
|
||||||
|
for i in range(amount):
|
||||||
|
self.create_schemas_object("testname" + str(i), "testdesc" + str(i))
|
||||||
|
|
||||||
|
def create_schemas_object(self, name, description):
|
||||||
|
data = self.format_data_for_json_reader(name, description)
|
||||||
|
Schemas.objects.create(
|
||||||
|
type="testy",
|
||||||
|
file_schema="filey",
|
||||||
|
data=data,
|
||||||
|
created_at=datetime.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
def format_data_for_json_reader(self, name, description):
|
||||||
|
return '{"name": "'+name+'", "description": "'+description+'"}'
|
||||||
|
|
||||||
|
def test_order_table_by_name_throws_no_exception(self):
|
||||||
|
try:
|
||||||
|
# Apply sorting
|
||||||
|
self.table.order_by = 'name'
|
||||||
|
except FieldError:
|
||||||
|
self.fail("Ordering template table by name raised FieldError")
|
||||||
|
|
||||||
|
def test_order_table_by_name_correctly_orders(self):
|
||||||
|
table = TemplateTable(Schemas.objects.all(), order_by="name")
|
||||||
|
# Fetch the sorted records
|
||||||
|
sorted_records = list(table.rows)
|
||||||
|
|
||||||
|
# Verify the order is as expected
|
||||||
|
self.assertLess(sorted_records[0].record.name,
|
||||||
|
sorted_records[1].record.name)
|
||||||
|
self.assertLess(sorted_records[1].record.name,
|
||||||
|
sorted_records[2].record.name)
|
||||||
|
|
||||||
|
def test_order_table_by_description_works(self):
|
||||||
|
try:
|
||||||
|
# Apply sorting
|
||||||
|
self.table.order_by = 'description'
|
||||||
|
except FieldError:
|
||||||
|
self.fail("Ordering template table by description raised FieldError")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.test import TestCase
|
from django.test import TestCase, RequestFactory
|
||||||
|
|
||||||
from idhub_auth.models import User
|
from idhub_auth.models import User
|
||||||
|
from idhub.admin.views import PeopleListView
|
||||||
|
|
||||||
|
|
||||||
class AdminDashboardViewTest(TestCase):
|
class AdminDashboardViewTest(TestCase):
|
||||||
|
@ -38,13 +39,55 @@ class AdminDashboardViewTest(TestCase):
|
||||||
self.assertTemplateUsed(response, 'auth/login.html')
|
self.assertTemplateUsed(response, 'auth/login.html')
|
||||||
|
|
||||||
def test_login_admin_user(self):
|
def test_login_admin_user(self):
|
||||||
self.client.login(email='adminuser@example.org', password='adminpass12')
|
self.client.login(email='adminuser@example.org',
|
||||||
|
password='adminpass12')
|
||||||
response = self.client.get(reverse('idhub:admin_dashboard'))
|
response = self.client.get(reverse('idhub:admin_dashboard'))
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_view_uses_correct_template(self):
|
def test_view_uses_correct_template(self):
|
||||||
self.client.login(email='adminuser@example.org', password='adminpass12')
|
self.client.login(email='adminuser@example.org',
|
||||||
|
password='adminpass12')
|
||||||
response = self.client.get(reverse('idhub:admin_dashboard'))
|
response = self.client.get(reverse('idhub:admin_dashboard'))
|
||||||
|
|
||||||
self.assertTemplateUsed(response, 'idhub/admin/dashboard.html')
|
self.assertTemplateUsed(response, 'idhub/admin/dashboard.html')
|
||||||
|
|
||||||
|
|
||||||
|
class PeopleListViewTest(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# Set up a RequestFactory to create mock requests
|
||||||
|
self.factory = RequestFactory()
|
||||||
|
|
||||||
|
# Create some user instances for testing
|
||||||
|
self.user = User.objects.create_user(email='normaluser@example.org',
|
||||||
|
password='testpass12')
|
||||||
|
self.admin_user = User.objects.create_superuser(
|
||||||
|
email='adminuser@example.org',
|
||||||
|
password='adminpass12')
|
||||||
|
|
||||||
|
# Create a request object for the view
|
||||||
|
self.request = self.factory.get(reverse('idhub:admin_people_list'))
|
||||||
|
|
||||||
|
self.request.user = self.admin_user
|
||||||
|
|
||||||
|
def test_template_used(self):
|
||||||
|
response = PeopleListView.as_view()(self.request)
|
||||||
|
|
||||||
|
self.assertEqual(response.template_name[0], "idhub/admin/people.html")
|
||||||
|
|
||||||
|
def test_context_data(self):
|
||||||
|
response = PeopleListView.as_view()(self.request)
|
||||||
|
|
||||||
|
self.assertIn('users', response.context_data)
|
||||||
|
|
||||||
|
# Assuming 2 users were created
|
||||||
|
self.assertEqual(len(response.context_data['users']), 2)
|
||||||
|
|
||||||
|
def test_get_queryset(self):
|
||||||
|
view = PeopleListView()
|
||||||
|
view.setup(self.request)
|
||||||
|
queryset = view.get_queryset()
|
||||||
|
|
||||||
|
# Assuming 2 users in the database
|
||||||
|
self.assertEqual(queryset.count(), 2)
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import requests
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from idhub_auth.models import User
|
|
||||||
from idhub.models import DID, VerificableCredential
|
from idhub.models import DID, VerificableCredential
|
||||||
from oidc4vp.models import Organization
|
from oidc4vp.models import Organization
|
||||||
|
from idhub_auth.models import User
|
||||||
|
|
||||||
|
|
||||||
class ProfileForm(forms.ModelForm):
|
class ProfileForm(forms.ModelForm):
|
||||||
|
|
144
idhub/user/tables.py
Normal file
144
idhub/user/tables.py
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
from django.utils.html import format_html
|
||||||
|
import django_tables2 as tables
|
||||||
|
from idhub.models import Event, Membership, UserRol, DID, VerificableCredential
|
||||||
|
|
||||||
|
|
||||||
|
class ButtonColumn(tables.Column):
|
||||||
|
attrs = {
|
||||||
|
"a": {
|
||||||
|
"type": "button",
|
||||||
|
"class": "text-primary",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# it makes no sense to order a column of buttons
|
||||||
|
orderable = False
|
||||||
|
# django_tables will only call the render function if it doesn't find
|
||||||
|
# any empty values in the data, so we stop it from matching the data
|
||||||
|
# to any value considered empty
|
||||||
|
empty_values = ()
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardTable(tables.Table):
|
||||||
|
type = tables.Column(verbose_name="Event")
|
||||||
|
message = tables.Column(verbose_name="Description")
|
||||||
|
created = tables.Column(verbose_name="Date")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("type", "message", "created")
|
||||||
|
|
||||||
|
|
||||||
|
class PersonalInfoTable(tables.Table):
|
||||||
|
type = tables.Column(verbose_name="Membership")
|
||||||
|
credential = ButtonColumn(
|
||||||
|
# TODO: See where this should actually link
|
||||||
|
linkify="idhub:user_credentials",
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def render_credential(self):
|
||||||
|
return format_html('<i class="bi bi-eye"></i>')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Membership
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("type", "start_date", "end_date", "credential")
|
||||||
|
|
||||||
|
|
||||||
|
class RolesTable(tables.Table):
|
||||||
|
name = tables.Column(verbose_name="Role", empty_values=())
|
||||||
|
description = tables.Column(empty_values=())
|
||||||
|
service = tables.Column()
|
||||||
|
|
||||||
|
def render_name(self, record):
|
||||||
|
return record.service.get_roles()
|
||||||
|
|
||||||
|
def render_description(self, record):
|
||||||
|
return record.service.description
|
||||||
|
|
||||||
|
def render_service(self, record):
|
||||||
|
return record.service.domain
|
||||||
|
|
||||||
|
def order_name(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "service__rol__name"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
def order_description(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "service__description"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
def order_service(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "service__domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = UserRol
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("name", "description", "service")
|
||||||
|
|
||||||
|
|
||||||
|
class DIDTable(tables.Table):
|
||||||
|
created_at = tables.Column(verbose_name="Date")
|
||||||
|
did = tables.Column(verbose_name="ID")
|
||||||
|
edit = ButtonColumn(
|
||||||
|
linkify={
|
||||||
|
"viewname": "idhub:user_dids_edit",
|
||||||
|
"args": [tables.A("pk")]
|
||||||
|
},
|
||||||
|
orderable=False
|
||||||
|
)
|
||||||
|
delete_template_code = """<a class="text-danger"
|
||||||
|
href="javascript:void()"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#confirm-delete-{{ record.id }}"
|
||||||
|
title="Remove"
|
||||||
|
><i class="bi bi-trash"></i></a>"""
|
||||||
|
delete = tables.TemplateColumn(template_code=delete_template_code,
|
||||||
|
orderable=False)
|
||||||
|
|
||||||
|
def render_edit(self):
|
||||||
|
return format_html('<i class="bi bi-pencil-square"></i>')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = DID
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("created_at", "label", "did", "edit", "delete")
|
||||||
|
|
||||||
|
|
||||||
|
class CredentialsTable(tables.Table):
|
||||||
|
description = tables.Column(verbose_name="Details", empty_values=())
|
||||||
|
|
||||||
|
def render_description(self, record):
|
||||||
|
return record.get_description()
|
||||||
|
|
||||||
|
def render_status(self, record):
|
||||||
|
return record.get_status()
|
||||||
|
|
||||||
|
def order_type(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "schema__type"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
def order_description(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(
|
||||||
|
("-" if is_descending else "") + "schema__template_description"
|
||||||
|
)
|
||||||
|
|
||||||
|
return (queryset, True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = VerificableCredential
|
||||||
|
template_name = "idhub/custom_table.html"
|
||||||
|
fields = ("type", "description", "issued_on", "status")
|
|
@ -26,6 +26,14 @@ from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django_tables2 import SingleTableView
|
||||||
|
from idhub.user.tables import (
|
||||||
|
DashboardTable,
|
||||||
|
PersonalInfoTable,
|
||||||
|
RolesTable,
|
||||||
|
DIDTable,
|
||||||
|
CredentialsTable
|
||||||
|
)
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from idhub.user.forms import (
|
from idhub.user.forms import (
|
||||||
|
@ -36,7 +44,8 @@ from idhub.user.forms import (
|
||||||
)
|
)
|
||||||
from utils import certs
|
from utils import certs
|
||||||
from idhub.mixins import UserView
|
from idhub.mixins import UserView
|
||||||
from idhub.models import DID, VerificableCredential, Event
|
from idhub.models import DID, VerificableCredential, Event, Membership
|
||||||
|
from idhub_auth.models import User
|
||||||
|
|
||||||
|
|
||||||
class MyProfile(UserView):
|
class MyProfile(UserView):
|
||||||
|
@ -49,21 +58,35 @@ class MyWallet(UserView):
|
||||||
section = "MyWallet"
|
section = "MyWallet"
|
||||||
|
|
||||||
|
|
||||||
class DashboardView(UserView, TemplateView):
|
class DashboardView(UserView, SingleTableView):
|
||||||
template_name = "idhub/user/dashboard.html"
|
template_name = "idhub/user/dashboard.html"
|
||||||
|
table_class = DashboardTable
|
||||||
title = _('Dashboard')
|
title = _('Dashboard')
|
||||||
subtitle = _('Events')
|
subtitle = _('Events')
|
||||||
icon = 'bi bi-bell'
|
icon = 'bi bi-bell'
|
||||||
section = "Home"
|
section = "Home"
|
||||||
|
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
queryset = Event.objects.select_related('user').filter(
|
||||||
|
user=self.request.user)
|
||||||
|
|
||||||
class ProfileView(MyProfile, UpdateView):
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class ProfileView(MyProfile, UpdateView, SingleTableView):
|
||||||
template_name = "idhub/user/profile.html"
|
template_name = "idhub/user/profile.html"
|
||||||
|
table_class = PersonalInfoTable
|
||||||
subtitle = _('My personal data')
|
subtitle = _('My personal data')
|
||||||
icon = 'bi bi-person-gear'
|
icon = 'bi bi-person-gear'
|
||||||
from_class = ProfileForm
|
|
||||||
fields = ('first_name', 'last_name', 'email')
|
fields = ('first_name', 'last_name', 'email')
|
||||||
success_url = reverse_lazy('idhub:user_profile')
|
success_url = reverse_lazy('idhub:user_profile')
|
||||||
|
model = User
|
||||||
|
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
queryset = Membership.objects.select_related('user').filter(
|
||||||
|
user=self.request.user)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self.request.user
|
return self.request.user
|
||||||
|
@ -79,11 +102,17 @@ class ProfileView(MyProfile, UpdateView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class RolesView(MyProfile, TemplateView):
|
class RolesView(MyProfile, SingleTableView):
|
||||||
template_name = "idhub/user/roles.html"
|
template_name = "idhub/user/roles.html"
|
||||||
|
table_class = RolesTable
|
||||||
subtitle = _('My roles')
|
subtitle = _('My roles')
|
||||||
icon = 'fa-brands fa-critical-role'
|
icon = 'fa-brands fa-critical-role'
|
||||||
|
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
queryset = self.request.user.roles.all()
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class GDPRView(MyProfile, TemplateView):
|
class GDPRView(MyProfile, TemplateView):
|
||||||
template_name = "idhub/user/gdpr.html"
|
template_name = "idhub/user/gdpr.html"
|
||||||
|
@ -91,20 +120,17 @@ class GDPRView(MyProfile, TemplateView):
|
||||||
icon = 'bi bi-file-earmark-medical'
|
icon = 'bi bi-file-earmark-medical'
|
||||||
|
|
||||||
|
|
||||||
class CredentialsView(MyWallet, TemplateView):
|
class CredentialsView(MyWallet, SingleTableView):
|
||||||
template_name = "idhub/user/credentials.html"
|
template_name = "idhub/user/credentials.html"
|
||||||
|
table_class = CredentialsTable
|
||||||
subtitle = _('Credential management')
|
subtitle = _('Credential management')
|
||||||
icon = 'bi bi-patch-check-fill'
|
icon = 'bi bi-patch-check-fill'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_queryset(self):
|
||||||
context = super().get_context_data(**kwargs)
|
queryset = VerificableCredential.objects.filter(
|
||||||
creds = VerificableCredential.objects.filter(
|
user=self.request.user)
|
||||||
user=self.request.user
|
|
||||||
)
|
return queryset
|
||||||
context.update({
|
|
||||||
'credentials': creds,
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class TermsAndConditionsView(UserView, FormView):
|
class TermsAndConditionsView(UserView, FormView):
|
||||||
|
@ -399,8 +425,9 @@ class DemandAuthorizationView(MyWallet, FormView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class DidsView(MyWallet, TemplateView):
|
class DidsView(MyWallet, SingleTableView):
|
||||||
template_name = "idhub/user/dids.html"
|
template_name = "idhub/user/dids.html"
|
||||||
|
table_class = DIDTable
|
||||||
subtitle = _('Identities (DIDs)')
|
subtitle = _('Identities (DIDs)')
|
||||||
icon = 'bi bi-patch-check-fill'
|
icon = 'bi bi-patch-check-fill'
|
||||||
|
|
||||||
|
@ -411,6 +438,11 @@ class DidsView(MyWallet, TemplateView):
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
queryset = DID.objects.filter(user=self.request.user)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class DidRegisterView(MyWallet, CreateView):
|
class DidRegisterView(MyWallet, CreateView):
|
||||||
template_name = "idhub/user/did_register.html"
|
template_name = "idhub/user/did_register.html"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2024-01-20 14:29
|
# Generated by Django 4.2.5 on 2024-01-22 15:44
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2024-01-20 14:29
|
# Generated by Django 4.2.5 on 2024-01-22 15:44
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.5 on 2024-01-20 14:29
|
# Generated by Django 4.2.5 on 2024-01-22 15:44
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
|
@ -15,6 +15,7 @@ pyld==2.0.3
|
||||||
pynacl==1.5.0
|
pynacl==1.5.0
|
||||||
more-itertools==10.1.0
|
more-itertools==10.1.0
|
||||||
dj-database-url==2.1.0
|
dj-database-url==2.1.0
|
||||||
|
faker==21.0.0
|
||||||
PyPDF2
|
PyPDF2
|
||||||
svg2rlg
|
svg2rlg
|
||||||
svglib
|
svglib
|
||||||
|
|
|
@ -33,8 +33,8 @@ SECRET_KEY = config('SECRET_KEY')
|
||||||
DEBUG = config('DEBUG', default=False, cast=bool)
|
DEBUG = config('DEBUG', default=False, cast=bool)
|
||||||
DEVELOPMENT = config('DEVELOPMENT', default=False, cast=bool)
|
DEVELOPMENT = config('DEVELOPMENT', default=False, cast=bool)
|
||||||
|
|
||||||
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[], cast=Csv())
|
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='', cast=Csv())
|
||||||
CSRF_TRUSTED_ORIGINS = config('CSRF_TRUSTED_ORIGINS', default=[], cast=Csv())
|
CSRF_TRUSTED_ORIGINS = config('CSRF_TRUSTED_ORIGINS', default='', cast=Csv())
|
||||||
|
|
||||||
DOMAIN = config("DOMAIN", "http://localhost")
|
DOMAIN = config("DOMAIN", "http://localhost")
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ LOCALE_PATHS = [
|
||||||
]
|
]
|
||||||
# LANGUAGE_CODE="en"
|
# LANGUAGE_CODE="en"
|
||||||
# LANGUAGE_CODE="es"
|
# LANGUAGE_CODE="es"
|
||||||
LANGUAGE_CODE="ca"
|
LANGUAGE_CODE="en"
|
||||||
gettext = lambda s: s
|
gettext = lambda s: s
|
||||||
LANGUAGES = (
|
LANGUAGES = (
|
||||||
('de', gettext('German')),
|
('de', gettext('German')),
|
||||||
|
|
Loading…
Reference in a new issue