feature/90-implement-public-website-for-device #17

Merged
cayop merged 32 commits from feature/90-implement-public-website-for-device into main 2024-10-30 15:02:18 +00:00
10 changed files with 317 additions and 43 deletions
Showing only changes of commit 2636e80ece - Show all commits

View File

@ -70,10 +70,17 @@ class SearchView(InventaryMixin):
return self.search_hids(query, offset, limit) return self.search_hids(query, offset, limit)
devices = [] devices = []
dev_id = []
for x in matches: for x in matches:
devices.append(self.get_annotations(x)) # devices.append(self.get_annotations(x))
dev = self.get_annotations(x)
if dev.id not in dev_id:
devices.append(dev)
dev_id.append(dev.id)
count = matches.size() count = matches.size()
# TODO fix of pagination, the count is not correct
return devices, count return devices, count
def get_annotations(self, xp): def get_annotations(self, xp):

View File

@ -109,6 +109,22 @@ class Device:
annotation = annotations.first() annotation = annotations.first()
self.last_evidence = Evidence(annotation.uuid) self.last_evidence = Evidence(annotation.uuid)
def is_eraseserver(self):
if not self.uuids:
self.get_uuids()
if not self.uuids:
return False
annotation = Annotation.objects.filter(
uuid__in=self.uuids,
owner=self.owner,
type=Annotation.Type.ERASE_SERVER
).first()
if annotation:
return True
return False
def last_uuid(self): def last_uuid(self):
return self.uuids[0] return self.uuids[0]

View File

@ -2,38 +2,126 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h3>{{ object.shortid }}</h3> <h3>{{ object.shortid }}</h3>
</div>
</div>
<div class="row">
<div class="col">
<ul class="nav nav-tabs nav-tabs-bordered">
<li class="nav-items">
<a href="#details" class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">{% trans "General details" %}</a>
</li>
<li class="nav-items">
<a href="#annotations" class="nav-link" data-bs-toggle="tab" data-bs-target="#annotations">{% trans "User annotations" %}</a>
</li>
<li class="nav-items">
<a href="#documents" class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">{% trans "Documents" %}</a>
</li>
<li class="nav-items">
<a href="#lots" class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">{% trans "Lots" %}</a>
</li>
<li class="nav-items">
<a href="#components" class="nav-link" data-bs-toggle="tab" data-bs-target="#components">{% trans "Components" %}</a>
</li>
<li class="nav-items">
<a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">{% trans "Evidences" %}</a>
</li>
<li class="nav-items">
<a href="#web" class="nav-link" href="">Web</a>
</li>
</ul>
</div>
</div>
<div class="tab-content pt-2">
<div class="tab-pane fade show active" id="details">
<h5 class="card-title">{% trans "Details" %}</h5>
<div class="row mb-3">
<div class="col-lg-3 col-md-4 label ">Phid</div>
<div class="col-lg-9 col-md-8">{{ object.id }}</div>
</div> </div>
{% if object.is_eraseserver %}
<div class="row mb-3">
<div class="col-lg-3 col-md-4 label">{% trans "Is a erase server" %}</div>
<div class="col-lg-9 col-md-8"></div>
</div>
{% endif %}
<div class="row">
<div class="col-lg-3 col-md-4 label ">{% trans "Type" %}</div>
<div class="col-lg-9 col-md-8">{{ object.type }}</div>
</div>
{% if object.is_websnapshot %}
{% for k, v in object.last_user_evidence %}
<div class="row">
<div class="col-lg-3 col-md-4 label">{{ k }}</div>
<div class="col-lg-9 col-md-8">{{ v|default:"" }}</div>
</div>
{% endfor %}
{% else %}
<div class="row">
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
<div class="col-lg-9 col-md-8">{{ object.manufacturer|default:"" }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label">Model</div>
<div class="col-lg-9 col-md-8">{{ object.model|default:"" }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label">Serial Number</div>
<div class="col-lg-9 col-md-8">{{ object.last_evidence.doc.device.serialNumber|default:"" }}</div>
</div>
{% endif %}
<div class="row">
<div class="col-lg-3 col-md-4 label">Identifiers</div>
</div>
{% for chid in object.hids %}
<div class="row">
<div class="col">{{ chid |default:"" }}</div>
</div>
{% endfor %}
</div> </div>
<div class="row"> <div class="tab-pane fade profile-overview" id="annotations">
<div class="col"> <div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
<ul class="nav nav-tabs nav-tabs-bordered"> <a href="{% url 'device:add_annotation' object.pk %}" class="btn btn-primary">
<li class="nav-items"> <i class="bi bi-plus"></i>
<a href="#details" class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">General details</a> {% trans "Add new annotation" %}
</li> <span class="caret"></span>
<li class="nav-items"> </a>
<a href="#annotations" class="nav-link" data-bs-toggle="tab" data-bs-target="#annotations">User annotations</a>
</li>
<li class="nav-items">
<a href="#documents" class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</a>
</li>
<li class="nav-items">
<a href="#lots" class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</a>
</li>
<li class="nav-items">
<a href="#components" class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</a>
</li>
<li class="nav-items">
<a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">Evidences</a>
</li>
<li class="nav-items">
<a class="nav-link" href="{% url 'device:device_web' object.id %}">Web</a>
</li>
</ul>
</div> </div>
<h5 class="card-title mt-2">{% trans "Annotations" %}</h5>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Key</th>
<th scope="col">Value</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created on</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for a in object.get_user_annotations %}
<tr>
<td>{{ a.key }}</td>
<td>{{ a.value }}</td>
<td>{{ a.created }}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
<div class="tab-content pt-2"> <div class="tab-content pt-2">
<div class="tab-pane fade show active" id="details"> <div class="tab-pane fade show active" id="details">

View File

@ -162,3 +162,56 @@ class ImportForm(forms.Form):
return table return table
return return
class EraseServerForm(forms.Form):
erase_server = forms.BooleanField(label=_("Is a Erase Server"), required=False)
def __init__(self, *args, **kwargs):
self.pk = None
self.uuid = kwargs.pop('uuid', None)
self.user = kwargs.pop('user')
instance = Annotation.objects.filter(
uuid=self.uuid,
type=Annotation.Type.ERASE_SERVER,
key='ERASE_SERVER',
owner=self.user.institution
).first()
if instance:
kwargs["initial"]["erase_server"] = instance.value
self.pk = instance.pk
super().__init__(*args, **kwargs)
def clean(self):
self.erase_server = self.cleaned_data.get('erase_server', False)
self.instance = Annotation.objects.filter(
uuid=self.uuid,
type=Annotation.Type.ERASE_SERVER,
key='ERASE_SERVER',
owner=self.user.institution
).first()
return True
def save(self, user, commit=True):
if not commit:
return
if not self.erase_server:
if self.instance:
self.instance.delete()
return
if self.instance:
return
Annotation.objects.create(
uuid=self.uuid,
type=Annotation.Type.ERASE_SERVER,
key='ERASE_SERVER',
value=self.erase_server,
owner=self.user.institution,
user=self.user
)

View File

@ -0,0 +1,25 @@
# Generated by Django 5.0.6 on 2024-10-28 12:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("evidence", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="annotation",
name="type",
field=models.SmallIntegerField(
choices=[
(0, "System"),
(1, "User"),
(2, "Document"),
(3, "EraseServer"),
]
),
),
]

View File

@ -14,6 +14,7 @@ class Annotation(models.Model):
SYSTEM= 0, "System" SYSTEM= 0, "System"
USER = 1, "User" USER = 1, "User"
DOCUMENT = 2, "Document" DOCUMENT = 2, "Document"
ERASE_SERVER = 3, "EraseServer"
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
uuid = models.UUIDField() uuid = models.UUIDField()

View File

@ -12,13 +12,16 @@
<div class="col"> <div class="col">
<ul class="nav nav-tabs nav-tabs-bordered"> <ul class="nav nav-tabs nav-tabs-bordered">
<li class="nav-items"> <li class="nav-items">
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#device">Devices</button> <button class="nav-link active" data-bs-toggle="tab" data-bs-target="#device">{% trans "Devices" %}</button>
</li> </li>
<li class="nav-items"> <li class="nav-items">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tag">Tag</button> <a href="#tag" class="nav-link" data-bs-toggle="tab" data-bs-target="#tag">{% trans "Tag" %}</a>
<li class="nav-items">
<a href="{% url 'evidence:download' object.uuid %}" class="nav-link">Download File</a>
</li> </li>
<li class="nav-items">
<a href="{% url 'evidence:erase_server' object.uuid %}" class="nav-link">{% trans "Erase Server" %}</a>
</li>
<li class="nav-items">
<a href="{% url 'evidence:download' object.uuid %}" class="nav-link">{% trans "Download File" %}</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -83,3 +86,24 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block extrascript %}
<script>
document.addEventListener("DOMContentLoaded", function() {
// Obtener el hash de la URL (ejemplo: #components)
const hash = window.location.hash;
// Verificar si hay un hash en la URL
if (hash) {
// Buscar el botón o enlace que corresponde al hash y activarlo
const tabTrigger = document.querySelector(`[data-bs-target="${hash}"]`);
if (tabTrigger) {
// Crear una instancia de tab de Bootstrap para activar el tab
const tab = new bootstrap.Tab(tabTrigger);
tab.show();
}
}
});
</script>
{% endblock %}

View File

@ -18,6 +18,7 @@ urlpatterns = [
path("upload", views.UploadView.as_view(), name="upload"), path("upload", views.UploadView.as_view(), name="upload"),
path("import", views.ImportView.as_view(), name="import"), path("import", views.ImportView.as_view(), name="import"),
path("<uuid:pk>", views.EvidenceView.as_view(), name="details"), path("<uuid:pk>", views.EvidenceView.as_view(), name="details"),
path("<uuid:pk>/eraseserver", views.EraseServerView.as_view(), name="erase_server"),
path("<uuid:pk>/download", views.DownloadEvidenceView.as_view(), name="download"), path("<uuid:pk>/download", views.DownloadEvidenceView.as_view(), name="download"),
path('annotation/<int:pk>/del', views.AnnotationDeleteView.as_view(), name='delete_annotation'), path('annotation/<int:pk>/del', views.AnnotationDeleteView.as_view(), name='delete_annotation'),
] ]

View File

@ -11,18 +11,14 @@ from django.views.generic.edit import (
FormView, FormView,
) )
from dashboard.mixins import DashboardView, Http403 from dashboard.mixins import DashboardView, Http403
from evidence.models import Evidence, Annotation from evidence.models import Evidence, Annotation
from evidence.forms import UploadForm, UserTagForm, ImportForm from evidence.forms import (
# from django.shortcuts import render UploadForm,
# from rest_framework import viewsets UserTagForm,
# from snapshot.serializers import SnapshotSerializer ImportForm,
EraseServerForm
)
# class SnapshotViewSet(viewsets.ModelViewSet):
# queryset = Snapshot.objects.all()
# serializer_class = SnapshotSerializer
class ListEvidencesView(DashboardView, TemplateView): class ListEvidencesView(DashboardView, TemplateView):
@ -167,3 +163,48 @@ class AnnotationDeleteView(DashboardView, DeleteView):
return redirect(url_name, **kwargs_view) return redirect(url_name, **kwargs_view)
class EraseServerView(DashboardView, FormView):
template_name = "ev_eraseserver.html"
section = "evidences"
title = _("Evidences")
breadcrumb = "Evidences / Details"
success_url = reverse_lazy('evidence:list')
form_class = EraseServerForm
def get(self, request, *args, **kwargs):
self.pk = kwargs['pk']
self.object = Evidence(self.pk)
if self.object.owner != self.request.user.institution:
raise Http403
self.object.get_annotations()
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'object': self.object,
})
return context
def get_form_kwargs(self):
self.pk = self.kwargs.get('pk')
kwargs = super().get_form_kwargs()
kwargs['uuid'] = self.pk
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
form.save(self.request.user)
response = super().form_valid(form)
return response
def form_invalid(self, form):
response = super().form_invalid(form)
return response
def get_success_url(self):
success_url = reverse_lazy('evidence:details', args=[self.pk])
return success_url

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2024-10-28 12:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("lot", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="lot",
name="closed",
field=models.BooleanField(default=False),
),
]