Merge pull request 'Added pagination and sorting by column to the admin tables' (#87) from extend-tables into release
Reviewed-on: https://gitea.pangea.org/trustchain-oc1-orchestral/IdHub/pulls/87
This commit is contained in:
commit
8316e6d5a0
|
@ -34,7 +34,7 @@ class ImportForm(forms.Form):
|
|||
(x.did, x.label) for x in DID.objects.filter(user=self.user)
|
||||
]
|
||||
self.fields['schema'].choices = [
|
||||
(x.id, x.name()) for x in Schemas.objects.filter()
|
||||
(x.id, x.name) for x in Schemas.objects.filter()
|
||||
]
|
||||
|
||||
def clean_did(self):
|
||||
|
|
|
@ -1,25 +1,255 @@
|
|||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from idhub.models import Rol, Event
|
||||
from django.utils.html import format_html
|
||||
|
||||
from idhub.models import (
|
||||
Rol,
|
||||
Event,
|
||||
Service,
|
||||
VerificableCredential,
|
||||
DID,
|
||||
File_datas,
|
||||
Schemas
|
||||
)
|
||||
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):
|
||||
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:
|
||||
model = User
|
||||
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):
|
||||
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:
|
||||
model = Rol
|
||||
template_name = "idhub/custom_table.html"
|
||||
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 Meta:
|
||||
model = Event
|
||||
template_name = "idhub/custom_table.html"
|
||||
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")
|
||||
|
|
|
@ -32,7 +32,14 @@ from idhub.admin.forms import (
|
|||
UserRolForm,
|
||||
)
|
||||
from idhub.admin.tables import (
|
||||
DashboardTable
|
||||
DashboardTable,
|
||||
UserTable,
|
||||
RolesTable,
|
||||
ServicesTable,
|
||||
CredentialTable,
|
||||
DIDTable,
|
||||
DataTable,
|
||||
TemplateTable
|
||||
)
|
||||
from idhub.models import (
|
||||
DID,
|
||||
|
@ -82,10 +89,12 @@ class ImportExport(AdminView):
|
|||
section = "ImportExport"
|
||||
|
||||
|
||||
class PeopleListView(People, TemplateView):
|
||||
class PeopleListView(People, SingleTableView):
|
||||
template_name = "idhub/admin/people.html"
|
||||
subtitle = _('View users')
|
||||
icon = 'bi bi-person'
|
||||
table_class = UserTable
|
||||
model = User
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
@ -94,6 +103,11 @@ class PeopleListView(People, TemplateView):
|
|||
})
|
||||
return context
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
queryset = super().get_queryset(**kwargs)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
class PeopleView(People, TemplateView):
|
||||
template_name = "idhub/admin/user.html"
|
||||
|
@ -398,17 +412,20 @@ class PeopleRolDeleteView(PeopleView):
|
|||
return redirect('idhub:admin_people_edit', user.id)
|
||||
|
||||
|
||||
class RolesView(AccessControl):
|
||||
class RolesView(AccessControl, SingleTableView):
|
||||
template_name = "idhub/admin/roles.html"
|
||||
subtitle = _('Manage roles')
|
||||
table_class = RolesTable
|
||||
icon = ''
|
||||
model = Rol
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'roles': Rol.objects,
|
||||
})
|
||||
return context
|
||||
queryset = kwargs.pop('object_list', None)
|
||||
if queryset is None:
|
||||
self.object_list = self.model.objects.all()
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class RolRegisterView(AccessControl, CreateView):
|
||||
template_name = "idhub/admin/rol_register.html"
|
||||
|
@ -461,17 +478,20 @@ class RolDeleteView(AccessControl):
|
|||
return redirect('idhub:admin_roles')
|
||||
|
||||
|
||||
class ServicesView(AccessControl):
|
||||
class ServicesView(AccessControl, SingleTableView):
|
||||
template_name = "idhub/admin/services.html"
|
||||
table_class = ServicesTable
|
||||
subtitle = _('Manage services')
|
||||
icon = ''
|
||||
model = Service
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'services': Service.objects,
|
||||
})
|
||||
return context
|
||||
queryset = kwargs.pop('object_list', None)
|
||||
if queryset is None:
|
||||
self.object_list = self.model.objects.all()
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ServiceRegisterView(AccessControl, CreateView):
|
||||
template_name = "idhub/admin/service_register.html"
|
||||
|
@ -534,17 +554,19 @@ class ServiceDeleteView(AccessControl):
|
|||
return redirect('idhub:admin_services')
|
||||
|
||||
|
||||
class CredentialsView(Credentials):
|
||||
class CredentialsView(Credentials, SingleTableView):
|
||||
template_name = "idhub/admin/credentials.html"
|
||||
table_class = CredentialTable
|
||||
subtitle = _('View credentials')
|
||||
icon = ''
|
||||
model = VerificableCredential
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'credentials': VerificableCredential.objects,
|
||||
})
|
||||
return context
|
||||
queryset = kwargs.pop('object_list', None)
|
||||
if queryset is None:
|
||||
self.object_list = self.model.objects.all()
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class CredentialView(Credentials):
|
||||
|
@ -620,19 +642,26 @@ class DeleteCredentialsView(Credentials):
|
|||
return redirect(self.success_url)
|
||||
|
||||
|
||||
class DidsView(Credentials):
|
||||
class DidsView(Credentials, SingleTableView):
|
||||
template_name = "idhub/admin/dids.html"
|
||||
table_class = DIDTable
|
||||
subtitle = _('Manage identities (DID)')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
wallet = True
|
||||
model = DID
|
||||
|
||||
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.update({
|
||||
'dids': DID.objects.filter(user=self.request.user),
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class DidRegisterView(Credentials, CreateView):
|
||||
template_name = "idhub/admin/did_register.html"
|
||||
subtitle = _('Add a new organizational identity (DID)')
|
||||
|
@ -702,19 +731,21 @@ class WalletConfigIssuesView(Credentials):
|
|||
wallet = True
|
||||
|
||||
|
||||
class SchemasView(SchemasMix):
|
||||
class SchemasView(SchemasMix, SingleTableView):
|
||||
template_name = "idhub/admin/schemas.html"
|
||||
table_class = TemplateTable
|
||||
subtitle = _('View credential templates')
|
||||
icon = ''
|
||||
model = Schemas
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'schemas': Schemas.objects,
|
||||
})
|
||||
return context
|
||||
queryset = kwargs.pop('object_list', None)
|
||||
if queryset is None:
|
||||
self.object_list = self.model.objects.all()
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
||||
class SchemasDeleteView(SchemasMix):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
@ -840,10 +871,12 @@ class SchemasImportAddView(SchemasMix):
|
|||
return data
|
||||
|
||||
|
||||
class ImportView(ImportExport, TemplateView):
|
||||
class ImportView(ImportExport, SingleTableView):
|
||||
template_name = "idhub/admin/import.html"
|
||||
table_class = DataTable
|
||||
subtitle = _('Import data')
|
||||
icon = ''
|
||||
model = File_datas
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
@ -888,4 +921,3 @@ class ImportAddView(ImportExport, FormView):
|
|||
else:
|
||||
messages.error(self.request, _("Error importing the file!"))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
# Generated by Django 4.2.5 on 2024-01-03 18:04
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('idhub', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='schemas',
|
||||
name='description',
|
||||
field=models.CharField(max_length=250, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='schemas',
|
||||
name='name',
|
||||
field=models.CharField(max_length=250, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='did',
|
||||
name='label',
|
||||
field=models.CharField(max_length=50, verbose_name='Label'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='created',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='Date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='message',
|
||||
field=models.CharField(max_length=350, verbose_name='Description'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='type',
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(1, 'User registered'),
|
||||
(2, 'User welcomed'),
|
||||
(3, 'Data update requested by user'),
|
||||
(4, 'Data update requested. Pending approval by administrator'),
|
||||
(5, "User's data updated by admin"),
|
||||
(6, 'Your data updated by admin'),
|
||||
(7, 'User deactivated by admin'),
|
||||
(8, 'DID created by user'),
|
||||
(9, 'DID created'),
|
||||
(10, 'DID deleted'),
|
||||
(11, 'Credential deleted by user'),
|
||||
(12, 'Credential deleted'),
|
||||
(13, 'Credential issued for user'),
|
||||
(14, 'Credential issued'),
|
||||
(15, 'Credential presented by user'),
|
||||
(16, 'Credential presented'),
|
||||
(17, 'Credential enabled'),
|
||||
(18, 'Credential available'),
|
||||
(19, 'Credential revoked by admin'),
|
||||
(20, 'Credential revoked'),
|
||||
(21, 'Role created by admin'),
|
||||
(22, 'Role modified by admin'),
|
||||
(23, 'Role deleted by admin'),
|
||||
(24, 'Service created by admin'),
|
||||
(25, 'Service modified by admin'),
|
||||
(26, 'Service deleted by admin'),
|
||||
(27, 'Organisational DID created by admin'),
|
||||
(28, 'Organisational DID deleted by admin'),
|
||||
(29, 'User deactivated'),
|
||||
(30, 'User activated'),
|
||||
],
|
||||
verbose_name='Event',
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userrol',
|
||||
name='service',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='users',
|
||||
to='idhub.service',
|
||||
verbose_name='Service',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -436,6 +436,8 @@ class Schemas(models.Model):
|
|||
file_schema = models.CharField(max_length=250)
|
||||
data = models.TextField()
|
||||
created_at = models.DateTimeField(auto_now=True)
|
||||
_name = models.CharField(max_length=250, null=True, db_column='name')
|
||||
_description = models.CharField(max_length=250, null=True, db_column='description')
|
||||
|
||||
@property
|
||||
def get_schema(self):
|
||||
|
@ -443,12 +445,33 @@ class Schemas(models.Model):
|
|||
return {}
|
||||
return json.loads(self.data)
|
||||
|
||||
def _update_and_get_field(self, field_attr, schema_key):
|
||||
field_value = getattr(self, field_attr)
|
||||
if not field_value:
|
||||
field_value = self.get_schema.get(schema_key, '')
|
||||
self._update_model_field(field_attr, 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):
|
||||
return self.get_schema.get('name', '')
|
||||
return self._update_and_get_field('_name', 'name')
|
||||
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
self._name = value
|
||||
|
||||
@property
|
||||
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):
|
||||
"""
|
||||
|
|
|
@ -1,39 +1,11 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% 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 '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.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>
|
||||
{% render_table table %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
|
@ -8,6 +9,8 @@
|
|||
</h3>
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
{% render_table table %}
|
||||
{% comment %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
|
@ -31,6 +34,7 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endcomment %}
|
||||
<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>
|
||||
|
|
|
@ -1,36 +1,14 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% 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' %}</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>
|
||||
{% render_table 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>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,39 +1,11 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
<i class="{{ icon }}"></i>
|
||||
{{ subtitle }}
|
||||
</h3>
|
||||
<div class="table-responsive">
|
||||
<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>
|
||||
{% render_table table %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
|
@ -8,31 +9,10 @@
|
|||
</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 '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>
|
||||
{% render_table table %}
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,47 +1,19 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% 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' %}</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>
|
||||
{% render_table 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>
|
||||
<!-- Modal -->
|
||||
{% for schema in schemas.all %}
|
||||
<div class="modal" id="confirm-delete-{{ schema.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
{% for schema in object_list %}
|
||||
<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">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{% extends "idhub/base_admin.html" %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block content %}
|
||||
<h3>
|
||||
|
@ -8,33 +9,10 @@
|
|||
</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 '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>
|
||||
{% render_table table %}
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
||||
|
||||
|
@ -14,4 +14,60 @@ class EventModelTest(TestCase):
|
|||
self.assertEqual(event.message, 'Test Event')
|
||||
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 unittest.mock import MagicMock
|
||||
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.core.exceptions import FieldError
|
||||
|
||||
from idhub_auth.models import User
|
||||
from idhub.admin.tables import DashboardTable
|
||||
from idhub.models import Event
|
||||
from idhub.admin.tables import DashboardTable, UserTable, TemplateTable
|
||||
from idhub.models import Event, Membership, Rol, UserRol, Service, Schemas
|
||||
|
||||
|
||||
class AdminDashboardTableTest(TestCase):
|
||||
|
@ -63,3 +65,82 @@ class AdminDashboardTableTest(TestCase):
|
|||
def test_pagination(self):
|
||||
# TODO
|
||||
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.test import TestCase
|
||||
from django.test import TestCase, RequestFactory
|
||||
|
||||
from idhub_auth.models import User
|
||||
from idhub.admin.views import PeopleListView
|
||||
|
||||
|
||||
class AdminDashboardViewTest(TestCase):
|
||||
|
@ -38,13 +39,55 @@ class AdminDashboardViewTest(TestCase):
|
|||
self.assertTemplateUsed(response, 'auth/login.html')
|
||||
|
||||
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'))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
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'))
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue