admin-users #7
0
admin/__init__.py
Normal file
0
admin/__init__.py
Normal file
3
admin/admin.py
Normal file
3
admin/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
admin/apps.py
Normal file
6
admin/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AdminConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "admin"
|
0
admin/migrations/__init__.py
Normal file
0
admin/migrations/__init__.py
Normal file
3
admin/models.py
Normal file
3
admin/models.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
12
admin/templates/admin_panel.html
Normal file
12
admin/templates/admin_panel.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>{{ subtitle }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
39
admin/templates/admin_users.html
Normal file
39
admin/templates/admin_users.html
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>{{ subtitle }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<a href="{% url 'admin:new_user' %}" class="btn btn-green-admin">{% translate "Add new user" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Email</th>
|
||||||
|
<th>is Admin</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
{% for u in users %}
|
||||||
|
<td>{{ u.email }}</td>
|
||||||
|
<td>{{ u.is_admin }}</td>
|
||||||
|
<td><a href="{% url 'admin:edit_user' u.pk %}"><i class="bi bi-eye"></i></td>
|
||||||
|
<td><a href="{% url 'admin:delete_user' u.pk %}" class="text-danger" title="Remove"><i class="bi bi-trash"></i></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
38
admin/templates/delete_user.html
Normal file
38
admin/templates/delete_user.html
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>{{ subtitle }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
Are you sure than want remove the lot {{ object.name }} with {{ object.devices.count }} devices.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'admin:users' %}">{% translate "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Delete' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
32
admin/templates/user.html
Normal file
32
admin/templates/user.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>{{ subtitle }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% load django_bootstrap5 %}
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
|
||||||
|
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
|
||||||
|
<div class="message">
|
||||||
|
{% for field, error in form.errors.items %}
|
||||||
|
{{ error }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<div class="form-actions-no-box">
|
||||||
|
<a class="btn btn-grey" href="{% url 'admin:users' %}">{% translate "Cancel" %}</a>
|
||||||
|
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
3
admin/tests.py
Normal file
3
admin/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
12
admin/urls.py
Normal file
12
admin/urls.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from django.urls import path
|
||||||
|
from admin import views
|
||||||
|
|
||||||
|
app_name = 'admin'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("panel/", views.PanelView.as_view(), name="panel"),
|
||||||
|
path("users/", views.UsersView.as_view(), name="users"),
|
||||||
|
path("users/new", views.CreateUserView.as_view(), name="new_user"),
|
||||||
|
path("users/edit/<int:pk>", views.EditUserView.as_view(), name="edit_user"),
|
||||||
|
path("users/delete/<int:pk>", views.DeleteUserView.as_view(), name="delete_user"),
|
||||||
|
]
|
89
admin/views.py
Normal file
89
admin/views.py
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views.generic.base import TemplateView
|
||||||
|
from django.views.generic.edit import (
|
||||||
|
CreateView,
|
||||||
|
UpdateView,
|
||||||
|
DeleteView,
|
||||||
|
)
|
||||||
|
from dashboard.mixins import DashboardView
|
||||||
|
from user.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class PanelView(DashboardView, TemplateView):
|
||||||
|
template_name = "admin_panel.html"
|
||||||
|
title = _("Admin")
|
||||||
|
breadcrumb = _("admin") + " /"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class UsersView(DashboardView, TemplateView):
|
||||||
|
template_name = "admin_users.html"
|
||||||
|
title = _("Users")
|
||||||
|
breadcrumb = _("admin / Users") + " /"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({
|
||||||
|
"users": User.objects.filter()
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class CreateUserView(DashboardView, CreateView):
|
||||||
|
template_name = "user.html"
|
||||||
|
title = _("User")
|
||||||
|
breadcrumb = _("admin / User") + " /"
|
||||||
|
success_url = reverse_lazy('admin:users')
|
||||||
|
model = User
|
||||||
|
fields = (
|
||||||
|
"email",
|
||||||
|
"password",
|
||||||
|
"is_admin",
|
||||||
|
)
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
form.instance.institution = self.request.user.institution
|
||||||
|
form.instance.set_password(form.instance.password)
|
||||||
|
response = super().form_valid(form)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteUserView(DashboardView, DeleteView):
|
||||||
|
template_name = "delete_user.html"
|
||||||
|
title = _("Delete user")
|
||||||
|
breadcrumb = "admin / Delete user"
|
||||||
|
success_url = reverse_lazy('admin:users')
|
||||||
|
model = User
|
||||||
|
fields = (
|
||||||
|
"email",
|
||||||
|
"password",
|
||||||
|
"is_admin",
|
||||||
|
)
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
response = super().form_valid(form)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class EditUserView(DashboardView, UpdateView):
|
||||||
|
template_name = "user.html"
|
||||||
|
title = _("Edit user")
|
||||||
|
breadcrumb = "admin / Edit user"
|
||||||
|
success_url = reverse_lazy('admin:users')
|
||||||
|
model = User
|
||||||
|
fields = (
|
||||||
|
"email",
|
||||||
|
"is_admin",
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
pk = self.kwargs.get('pk')
|
||||||
|
self.object = get_object_or_404(self.model, pk=pk)
|
||||||
|
#self.object.set_password(self.object.password)
|
||||||
|
kwargs = super().get_form_kwargs()
|
||||||
|
return kwargs
|
|
@ -47,7 +47,9 @@ class DashboardView(LoginRequiredMixin):
|
||||||
dev_ids = self.request.session.pop("devices", [])
|
dev_ids = self.request.session.pop("devices", [])
|
||||||
|
|
||||||
self._devices = []
|
self._devices = []
|
||||||
for x in Annotation.objects.filter(value__in=dev_ids).filter(owner=self.request.user).distinct():
|
for x in Annotation.objects.filter(value__in=dev_ids).filter(
|
||||||
|
owner=self.request.user.institution
|
||||||
|
).distinct():
|
||||||
self._devices.append(Device(id=x.value))
|
self._devices.append(Device(id=x.value))
|
||||||
return self._devices
|
return self._devices
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,26 @@
|
||||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||||
<div class="position-sticky pt-5">
|
<div class="position-sticky pt-5">
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
|
{% if user.is_admin %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="admin {% if path in 'panel users' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_admin" aria-expanded="false" aria-controls="ul_admin" href="javascript:void()">
|
||||||
|
<i class="bi bi-person-fill-gear icon_sidebar"></i>
|
||||||
|
{% trans 'Admin' %}
|
||||||
|
</a>
|
||||||
|
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if path in 'panel users' %}expanded{% else %}collapse{% endif %}" id="ul_admin" data-bs-parent="#sidebarMenu">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link{% if path == 'panel' %} active2{% endif %}" href="{% url 'admin:panel' %}">
|
||||||
|
{% trans 'Panel' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link{% if path == 'users' %} active2{% endif %}" href="{% url 'admin:users' %}">
|
||||||
|
{% trans 'Users' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="admin {% if path == 'unassigned_devices' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_devices" aria-expanded="false" aria-controls="ul_devices" href="javascript:void()">
|
<a class="admin {% if path == 'unassigned_devices' %}active {% endif %}nav-link fw-bold" data-bs-toggle="collapse" data-bs-target="#ul_devices" aria-expanded="false" aria-controls="ul_devices" href="javascript:void()">
|
||||||
<i class="bi bi-laptop icon_sidebar"></i>
|
<i class="bi bi-laptop icon_sidebar"></i>
|
||||||
|
|
|
@ -13,7 +13,7 @@ class UnassignedDevicesView(InventaryMixin):
|
||||||
breadcrumb = "Devices / Unassigned Devices"
|
breadcrumb = "Devices / Unassigned Devices"
|
||||||
|
|
||||||
def get_devices(self, user, offset, limit):
|
def get_devices(self, user, offset, limit):
|
||||||
return Device.get_unassigned(self.request.user, offset, limit)
|
return Device.get_unassigned(self.request.user.institution, offset, limit)
|
||||||
|
|
||||||
|
|
||||||
class LotDashboardView(InventaryMixin, DetailsMixin):
|
class LotDashboardView(InventaryMixin, DetailsMixin):
|
||||||
|
|
|
@ -56,7 +56,7 @@ class BaseDeviceFormSet(forms.BaseFormSet):
|
||||||
if not commit:
|
if not commit:
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
create_index(doc)
|
create_index(doc, self.user)
|
||||||
create_annotation(doc, user, commit=commit)
|
create_annotation(doc, user, commit=commit)
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,8 @@ from django.views.generic.edit import (
|
||||||
FormView,
|
FormView,
|
||||||
)
|
)
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from dashboard.mixins import DashboardView
|
from dashboard.mixins import DashboardView, Http403
|
||||||
from evidence.models import Annotation
|
from evidence.models import Annotation
|
||||||
from evidence.xapian import search
|
|
||||||
from lot.models import LotTag
|
from lot.models import LotTag
|
||||||
from device.models import Device
|
from device.models import Device
|
||||||
from device.forms import DeviceFormSet
|
from device.forms import DeviceFormSet
|
||||||
|
@ -72,7 +71,11 @@ class EditDeviceView(DashboardView, UpdateView):
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
self.object = get_object_or_404(self.model, pk=pk)
|
self.object = get_object_or_404(
|
||||||
|
self.model,
|
||||||
|
pk=pk,
|
||||||
|
owner=self.request.user.institution
|
||||||
|
)
|
||||||
self.success_url = reverse_lazy('device:details', args=[pk])
|
self.success_url = reverse_lazy('device:details', args=[pk])
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
@ -87,6 +90,9 @@ class DetailsView(DashboardView, TemplateView):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.pk = kwargs['pk']
|
self.pk = kwargs['pk']
|
||||||
self.object = Device(id=self.pk)
|
self.object = Device(id=self.pk)
|
||||||
|
if self.object.owner != self.request.user.institution:
|
||||||
|
raise Http403
|
||||||
|
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
@ -110,7 +116,9 @@ class AddAnnotationView(DashboardView, CreateView):
|
||||||
fields = ("key", "value")
|
fields = ("key", "value")
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
form.instance.owner = self.request.user
|
form.instance.owner = self.request.user.institution
|
||||||
|
form.instance.user = self.request.user
|
||||||
|
form.instance.uuid = self.annotation.uuid
|
||||||
form.instance.uuid = self.annotation.uuid
|
form.instance.uuid = self.annotation.uuid
|
||||||
form.instance.type = Annotation.Type.USER
|
form.instance.type = Annotation.Type.USER
|
||||||
response = super().form_valid(form)
|
response = super().form_valid(form)
|
||||||
|
@ -119,10 +127,12 @@ class AddAnnotationView(DashboardView, CreateView):
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
self.annotation = Annotation.objects.filter(
|
self.annotation = Annotation.objects.filter(
|
||||||
owner=self.request.user, value=pk, type=Annotation.Type.SYSTEM
|
owner=self.request.user.institution,
|
||||||
|
value=pk,
|
||||||
|
type=Annotation.Type.SYSTEM
|
||||||
).first()
|
).first()
|
||||||
if not self.annotation:
|
if not self.annotation:
|
||||||
get_object_or_404(Annotation, pk=0, owner=self.request.user)
|
get_object_or_404(Annotation, pk=0, owner=self.request.user.institution)
|
||||||
self.success_url = reverse_lazy('device:details', args=[pk])
|
self.success_url = reverse_lazy('device:details', args=[pk])
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
@ -137,7 +147,8 @@ class AddDocumentView(DashboardView, CreateView):
|
||||||
fields = ("key", "value")
|
fields = ("key", "value")
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
form.instance.owner = self.request.user
|
form.instance.owner = self.request.user.institution
|
||||||
|
form.instance.user = self.request.user
|
||||||
form.instance.uuid = self.annotation.uuid
|
form.instance.uuid = self.annotation.uuid
|
||||||
form.instance.type = Annotation.Type.DOCUMENT
|
form.instance.type = Annotation.Type.DOCUMENT
|
||||||
response = super().form_valid(form)
|
response = super().form_valid(form)
|
||||||
|
@ -146,10 +157,10 @@ class AddDocumentView(DashboardView, CreateView):
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
self.annotation = Annotation.objects.filter(
|
self.annotation = Annotation.objects.filter(
|
||||||
owner=self.request.user, value=pk, type=Annotation.Type.SYSTEM
|
owner=self.request.user.institution, value=pk, type=Annotation.Type.SYSTEM
|
||||||
).first()
|
).first()
|
||||||
if not self.annotation:
|
if not self.annotation:
|
||||||
get_object_or_404(Annotation, pk=0, owner=self.request.user)
|
get_object_or_404(Annotation, pk=0, owner=self.request.user.institution)
|
||||||
self.success_url = reverse_lazy('device:details', args=[pk])
|
self.success_url = reverse_lazy('device:details', args=[pk])
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
|
@ -35,7 +35,7 @@ ALLOWED_HOSTS = []
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
"django.contrib.admin",
|
# "django.contrib.admin",
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
"django.contrib.sessions",
|
"django.contrib.sessions",
|
||||||
|
@ -53,6 +53,7 @@ INSTALLED_APPS = [
|
||||||
"lot",
|
"lot",
|
||||||
"documents",
|
"documents",
|
||||||
"dashboard",
|
"dashboard",
|
||||||
|
"admin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,5 +23,6 @@ urlpatterns = [
|
||||||
path("dashboard/", include("dashboard.urls")),
|
path("dashboard/", include("dashboard.urls")),
|
||||||
path("evidence/", include("evidence.urls")),
|
path("evidence/", include("evidence.urls")),
|
||||||
path("device/", include("device.urls")),
|
path("device/", include("device.urls")),
|
||||||
|
path("admin/", include("admin.urls")),
|
||||||
path("lot/", include("lot.urls")),
|
path("lot/", include("lot.urls")),
|
||||||
]
|
]
|
||||||
|
|
|
@ -57,10 +57,12 @@ class UserTagForm(forms.Form):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.pk = None
|
self.pk = None
|
||||||
self.uuid = kwargs.pop('uuid', None)
|
self.uuid = kwargs.pop('uuid', None)
|
||||||
|
self.user = kwargs.pop('user')
|
||||||
instance = Annotation.objects.filter(
|
instance = Annotation.objects.filter(
|
||||||
uuid=self.uuid,
|
uuid=self.uuid,
|
||||||
type=Annotation.Type.SYSTEM,
|
type=Annotation.Type.SYSTEM,
|
||||||
key='CUSTOM_ID'
|
key='CUSTOM_ID',
|
||||||
|
owner=self.user.institution
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
if instance:
|
if instance:
|
||||||
|
@ -77,7 +79,8 @@ class UserTagForm(forms.Form):
|
||||||
self.instance = Annotation.objects.filter(
|
self.instance = Annotation.objects.filter(
|
||||||
uuid=self.uuid,
|
uuid=self.uuid,
|
||||||
type=Annotation.Type.SYSTEM,
|
type=Annotation.Type.SYSTEM,
|
||||||
key='CUSTOM_ID'
|
key='CUSTOM_ID',
|
||||||
|
owner=self.user.institution
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -95,10 +98,11 @@ class UserTagForm(forms.Form):
|
||||||
|
|
||||||
Annotation.objects.create(
|
Annotation.objects.create(
|
||||||
uuid=self.uuid,
|
uuid=self.uuid,
|
||||||
owner=user,
|
|
||||||
type=Annotation.Type.SYSTEM,
|
type=Annotation.Type.SYSTEM,
|
||||||
key='CUSTOM_ID',
|
key='CUSTOM_ID',
|
||||||
value=self.tag
|
value=self.tag,
|
||||||
|
owner=self.user.institution,
|
||||||
|
user=self.user
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,7 +152,7 @@ class ImportForm(forms.Form):
|
||||||
if commit:
|
if commit:
|
||||||
for doc, cred in table:
|
for doc, cred in table:
|
||||||
cred.save()
|
cred.save()
|
||||||
create_index(doc)
|
create_index(doc, self.user)
|
||||||
return table
|
return table
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.0.6 on 2024-07-27 16:23
|
# Generated by Django 5.0.6 on 2024-10-07 11:38
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -10,6 +10,7 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
("user", "0001_initial"),
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -30,7 +31,9 @@ class Migration(migrations.Migration):
|
||||||
("uuid", models.UUIDField()),
|
("uuid", models.UUIDField()),
|
||||||
(
|
(
|
||||||
"type",
|
"type",
|
||||||
models.SmallIntegerField(choices=[(0, "System"), (1, "User")]),
|
models.SmallIntegerField(
|
||||||
|
choices=[(0, "System"), (1, "User"), (2, "Document")]
|
||||||
|
),
|
||||||
),
|
),
|
||||||
("key", models.CharField(max_length=256)),
|
("key", models.CharField(max_length=256)),
|
||||||
("value", models.CharField(max_length=256)),
|
("value", models.CharField(max_length=256)),
|
||||||
|
@ -38,6 +41,15 @@ class Migration(migrations.Migration):
|
||||||
"owner",
|
"owner",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="user.institution",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"user",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
to=settings.AUTH_USER_MODEL,
|
to=settings.AUTH_USER_MODEL,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Generated by Django 5.0.6 on 2024-07-29 14:58
|
|
||||||
|
|
||||||
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, "Action")]
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Generated by Django 5.0.6 on 2024-07-29 15:37
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("evidence", "0002_alter_annotation_type"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="annotation",
|
|
||||||
name="type",
|
|
||||||
field=models.SmallIntegerField(
|
|
||||||
choices=[(0, "System"), (1, "User"), (2, "Document")]
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -4,7 +4,7 @@ from django.db import models
|
||||||
|
|
||||||
from utils.constants import STR_SM_SIZE, STR_EXTEND_SIZE
|
from utils.constants import STR_SM_SIZE, STR_EXTEND_SIZE
|
||||||
from evidence.xapian import search
|
from evidence.xapian import search
|
||||||
from user.models import User
|
from user.models import User, Institution
|
||||||
|
|
||||||
|
|
||||||
class Annotation(models.Model):
|
class Annotation(models.Model):
|
||||||
|
@ -15,7 +15,8 @@ class Annotation(models.Model):
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
uuid = models.UUIDField()
|
uuid = models.UUIDField()
|
||||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
owner = models.ForeignKey(Institution, on_delete=models.CASCADE)
|
||||||
|
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
type = models.SmallIntegerField(choices=Type)
|
type = models.SmallIntegerField(choices=Type)
|
||||||
key = models.CharField(max_length=STR_EXTEND_SIZE)
|
key = models.CharField(max_length=STR_EXTEND_SIZE)
|
||||||
value = models.CharField(max_length=STR_EXTEND_SIZE)
|
value = models.CharField(max_length=STR_EXTEND_SIZE)
|
||||||
|
@ -51,8 +52,10 @@ class Evidence:
|
||||||
|
|
||||||
def get_doc(self):
|
def get_doc(self):
|
||||||
self.doc = {}
|
self.doc = {}
|
||||||
|
if not self.owner:
|
||||||
|
self.get_owner()
|
||||||
qry = 'uuid:"{}"'.format(self.uuid)
|
qry = 'uuid:"{}"'.format(self.uuid)
|
||||||
matches = search(qry, limit=1)
|
matches = search(self.owner, qry, limit=1)
|
||||||
if matches.size() < 0:
|
if matches.size() < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -73,6 +76,6 @@ class Evidence:
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all(cls, user):
|
def get_all(cls, user):
|
||||||
return Annotation.objects.filter(
|
return Annotation.objects.filter(
|
||||||
owner=user,
|
owner=user.institution,
|
||||||
type=Annotation.Type.SYSTEM,
|
type=Annotation.Type.SYSTEM,
|
||||||
).order_by("-created").values_list("uuid", flat=True).distinct()
|
).order_by("-created").values_list("uuid", flat=True).distinct()
|
||||||
|
|
|
@ -4,7 +4,7 @@ import shutil
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from evidence.xapian import search, index
|
from evidence.xapian import index
|
||||||
from evidence.models import Evidence, Annotation
|
from evidence.models import Evidence, Annotation
|
||||||
from utils.constants import ALGOS
|
from utils.constants import ALGOS
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class Build:
|
||||||
|
|
||||||
def index(self):
|
def index(self):
|
||||||
snap = json.dumps(self.json)
|
snap = json.dumps(self.json)
|
||||||
index(self.uuid, snap)
|
index(self.user.institution, self.uuid, snap)
|
||||||
|
|
||||||
def generate_chids(self):
|
def generate_chids(self):
|
||||||
self.algorithms = {
|
self.algorithms = {
|
||||||
|
@ -47,7 +47,8 @@ class Build:
|
||||||
for k, v in self.algorithms.items():
|
for k, v in self.algorithms.items():
|
||||||
Annotation.objects.create(
|
Annotation.objects.create(
|
||||||
uuid=self.uuid,
|
uuid=self.uuid,
|
||||||
owner=self.user,
|
owner=self.user.institution,
|
||||||
|
user=self.user,
|
||||||
type=Annotation.Type.SYSTEM,
|
type=Annotation.Type.SYSTEM,
|
||||||
key=k,
|
key=k,
|
||||||
value=v
|
value=v
|
||||||
|
|
|
@ -92,7 +92,7 @@ class EvidenceView(DashboardView, FormView):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.pk = kwargs['pk']
|
self.pk = kwargs['pk']
|
||||||
self.object = Evidence(self.pk)
|
self.object = Evidence(self.pk)
|
||||||
if self.object.owner != self.request.user:
|
if self.object.owner != self.request.user.institution:
|
||||||
raise Http403
|
raise Http403
|
||||||
|
|
||||||
self.object.get_annotations()
|
self.object.get_annotations()
|
||||||
|
@ -109,6 +109,7 @@ class EvidenceView(DashboardView, FormView):
|
||||||
self.pk = self.kwargs.get('pk')
|
self.pk = self.kwargs.get('pk')
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs['uuid'] = self.pk
|
kwargs['uuid'] = self.pk
|
||||||
|
kwargs['user'] = self.request.user
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
@ -130,7 +131,7 @@ class DownloadEvidenceView(DashboardView, TemplateView):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
pk = kwargs['pk']
|
pk = kwargs['pk']
|
||||||
evidence = Evidence(pk)
|
evidence = Evidence(pk)
|
||||||
if evidence.owner != self.request.user:
|
if evidence.owner != self.request.user.institution:
|
||||||
raise Http403()
|
raise Http403()
|
||||||
|
|
||||||
evidence.get_doc()
|
evidence.get_doc()
|
||||||
|
@ -156,7 +157,11 @@ class AnnotationDeleteView(DashboardView, DeleteView):
|
||||||
# if is not possible resolve the reference path return 404
|
# if is not possible resolve the reference path return 404
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
self.object = get_object_or_404(self.model, pk=self.pk, owner=self.request.user)
|
self.object = get_object_or_404(
|
||||||
|
self.model,
|
||||||
|
pk=self.pk,
|
||||||
|
owner=self.request.user.institution
|
||||||
|
)
|
||||||
self.object.delete()
|
self.object.delete()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import xapian
|
||||||
# indexer.set_stemmer(stemmer)
|
# indexer.set_stemmer(stemmer)
|
||||||
|
|
||||||
|
|
||||||
def search(qs, offset=0, limit=10):
|
def search(institution, qs, offset=0, limit=10):
|
||||||
database = xapian.Database("db")
|
database = xapian.Database("db")
|
||||||
|
|
||||||
qp = xapian.QueryParser()
|
qp = xapian.QueryParser()
|
||||||
|
@ -20,16 +20,20 @@ def search(qs, offset=0, limit=10):
|
||||||
qp.add_prefix("uuid", "uuid")
|
qp.add_prefix("uuid", "uuid")
|
||||||
# qp.add_prefix("snapshot", "snapshot")
|
# qp.add_prefix("snapshot", "snapshot")
|
||||||
query = qp.parse_query(qs)
|
query = qp.parse_query(qs)
|
||||||
|
institution_term = "U{}".format(institution.id)
|
||||||
|
final_query = xapian.Query(
|
||||||
|
xapian.Query.OP_AND, query, xapian.Query(institution_term)
|
||||||
|
)
|
||||||
enquire = xapian.Enquire(database)
|
enquire = xapian.Enquire(database)
|
||||||
enquire.set_query(query)
|
enquire.set_query(final_query)
|
||||||
matches = enquire.get_mset(offset, limit)
|
matches = enquire.get_mset(offset, limit)
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
|
||||||
def index(uuid, snap):
|
def index(institution, uuid, snap):
|
||||||
uuid = 'uuid:"{}"'.format(uuid)
|
uuid = 'uuid:"{}"'.format(uuid)
|
||||||
try:
|
try:
|
||||||
matches = search(uuid, limit=1)
|
matches = search(institution, uuid, limit=1)
|
||||||
if matches.size() > 0:
|
if matches.size() > 0:
|
||||||
return
|
return
|
||||||
except (xapian.DatabaseNotFoundError, xapian.DatabaseOpeningError):
|
except (xapian.DatabaseNotFoundError, xapian.DatabaseOpeningError):
|
||||||
|
@ -47,5 +51,7 @@ def index(uuid, snap):
|
||||||
indexer.index_text(snap)
|
indexer.index_text(snap)
|
||||||
indexer.index_text(uuid, 10, "uuid")
|
indexer.index_text(uuid, 10, "uuid")
|
||||||
# indexer.index_text(snap, 1, "snapshot")
|
# indexer.index_text(snap, 1, "snapshot")
|
||||||
|
institution_term = "U{}".format(institution.id)
|
||||||
|
doc.add_term(institution_term)
|
||||||
|
|
||||||
database.add_document(doc)
|
database.add_document(doc)
|
||||||
|
|
2
reset.sh
2
reset.sh
|
@ -1,5 +1,5 @@
|
||||||
rm db/*
|
rm db/*
|
||||||
python3 manage.py migrate
|
python3 manage.py migrate
|
||||||
python3 manage.py add_institution Pangea
|
python3 manage.py add_institution Pangea
|
||||||
python3 manage.py add_user Pangea user@example.org 1234
|
python3 manage.py add_user Pangea user@example.org 1234 True
|
||||||
python3 manage.py up_snapshots example/snapshots/ user@example.org
|
python3 manage.py up_snapshots example/snapshots/ user@example.org
|
||||||
|
|
|
@ -14,19 +14,22 @@ class Command(BaseCommand):
|
||||||
parser.add_argument('institution', type=str, help='institution')
|
parser.add_argument('institution', type=str, help='institution')
|
||||||
parser.add_argument('email', type=str, help='email')
|
parser.add_argument('email', type=str, help='email')
|
||||||
parser.add_argument('password', type=str, help='password')
|
parser.add_argument('password', type=str, help='password')
|
||||||
|
parser.add_argument('is_admin', nargs='?', default=False, type=str, help='is admin')
|
||||||
|
|
||||||
def handle(self, *args, **kwargs):
|
def handle(self, *args, **kwargs):
|
||||||
email = kwargs['email']
|
email = kwargs['email']
|
||||||
password = kwargs['password']
|
password = kwargs['password']
|
||||||
|
is_admin = kwargs['is_admin']
|
||||||
institution = Institution.objects.get(name=kwargs['institution'])
|
institution = Institution.objects.get(name=kwargs['institution'])
|
||||||
self.create_user(institution, email, password)
|
self.create_user(institution, email, password, is_admin)
|
||||||
self.create_lot_tags()
|
self.create_lot_tags()
|
||||||
|
|
||||||
def create_user(self, institution, email, password):
|
def create_user(self, institution, email, password, is_admin):
|
||||||
self.u = User.objects.create(
|
self.u = User.objects.create(
|
||||||
institution=institution,
|
institution=institution,
|
||||||
email=email,
|
email=email,
|
||||||
password=password
|
password=password,
|
||||||
|
is_admin=is_admin,
|
||||||
)
|
)
|
||||||
self.u.set_password(password)
|
self.u.set_password(password)
|
||||||
self.u.save()
|
self.u.save()
|
||||||
|
|
|
@ -69,7 +69,8 @@ def create_annotation(doc, user, commit=False):
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'uuid': doc['uuid'],
|
'uuid': doc['uuid'],
|
||||||
'owner': user,
|
'owner': user.institution,
|
||||||
|
'user': user,
|
||||||
'type': Annotation.Type.SYSTEM,
|
'type': Annotation.Type.SYSTEM,
|
||||||
'key': 'CUSTOMER_ID',
|
'key': 'CUSTOMER_ID',
|
||||||
'value': doc['CUSTOMER_ID'],
|
'value': doc['CUSTOMER_ID'],
|
||||||
|
@ -80,10 +81,10 @@ def create_annotation(doc, user, commit=False):
|
||||||
return Annotation(**data)
|
return Annotation(**data)
|
||||||
|
|
||||||
|
|
||||||
def create_index(doc):
|
def create_index(doc, user):
|
||||||
if not doc or not doc.get('uuid'):
|
if not doc or not doc.get('uuid'):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
_uuid = doc['uuid']
|
_uuid = doc['uuid']
|
||||||
ev = json.dumps(doc)
|
ev = json.dumps(doc)
|
||||||
index(_uuid, ev)
|
index(user, _uuid, ev)
|
||||||
|
|
Loading…
Reference in a new issue