diff options
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/admin.py | 45 | ||||
-rw-r--r-- | ishtar_common/migrations/0217_auto_20211006_1526.py | 177 | ||||
-rw-r--r-- | ishtar_common/models.py | 5 | ||||
-rw-r--r-- | ishtar_common/models_rest.py | 32 | ||||
-rw-r--r-- | ishtar_common/rest.py | 31 |
5 files changed, 288 insertions, 2 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index 07750ffe7..0b73f5708 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -554,8 +554,12 @@ admin_site.register(models.Person, PersonAdmin) class AuthorAdmin(admin.ModelAdmin): list_display = ["person", "author_type"] list_filter = ("author_type",) - search_fields = ("person__name", "person__surname", "person__attached_to__name", - "author_type__label") + search_fields = ( + "person__name", + "person__surname", + "person__attached_to__name", + "author_type__label", + ) model = models.Author autocomplete_fields = ["person"] @@ -2082,3 +2086,40 @@ class DocumentTemplateAdmin(admin.ModelAdmin): admin_site.register(models.DocumentTemplate, DocumentTemplateAdmin) + +class ApiUserAdmin(admin.ModelAdmin): + list_display = ("user_ptr", "ip") + + +admin_site.register(models.ApiUser, ApiUserAdmin) + + +def get_main_content_types_query(): + CONTENT_TYPES = ( + ("archaeological_operations", "operation"), + ) + pks = [] + for app_label, model_name in CONTENT_TYPES: + try: + ct = ContentType.objects.get(app_label=app_label, model=model_name) + pks.append(ct.pk) + except ContentType.DoesNotExist: + pass + return ContentType.objects.filter(pk__in=pks) + + +class ApiSearchModelAdminForm(forms.ModelForm): + class Meta: + model = models.ApiUser + exclude = [] + content_type = forms.ModelChoiceField( + label=_("Content type"), queryset=get_main_content_types_query() + ) + + +class ApiSearchModelAdmin(admin.ModelAdmin): + form = ApiSearchModelAdminForm + list_display = ("user", "content_type") + + +admin_site.register(models.ApiSearchModel, ApiSearchModelAdmin) diff --git a/ishtar_common/migrations/0217_auto_20211006_1526.py b/ishtar_common/migrations/0217_auto_20211006_1526.py new file mode 100644 index 000000000..33299b4c3 --- /dev/null +++ b/ishtar_common/migrations/0217_auto_20211006_1526.py @@ -0,0 +1,177 @@ +# Generated by Django 2.2.24 on 2021-10-06 15:26 + +from django.conf import settings +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('auth', '0011_update_proxy_permissions'), + ('ishtar_common', '0216_auto_20210805_1703'), + ] + + operations = [ + migrations.CreateModel( + name='ApiUser', + fields=[ + ('user_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='apiuser', serialize=False, to=settings.AUTH_USER_MODEL)), + ('ip', models.GenericIPAddressField(verbose_name='IP')), + ], + options={ + 'verbose_name': 'Api - User', + 'verbose_name_plural': 'Api - Users', + }, + ), + migrations.AlterField( + model_name='author', + name='author_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='ishtar_common.AuthorType', verbose_name='Author type'), + ), + migrations.AlterField( + model_name='document', + name='data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='document', + name='history_m2m', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='document', + name='language', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Language', verbose_name='Language'), + ), + migrations.AlterField( + model_name='document', + name='publisher', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='publish', to='ishtar_common.Organization', verbose_name='Publisher'), + ), + migrations.AlterField( + model_name='document', + name='source', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='ishtar_common.Document', verbose_name='Source'), + ), + migrations.AlterField( + model_name='historicalorganization', + name='data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='historicalorganization', + name='history_m2m', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='historicalperson', + name='data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='historicalperson', + name='history_m2m', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='default_language', + field=models.ForeignKey(blank=True, help_text='If set, by default the selected language will be set for localized documents.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Language', verbose_name='Default language for documentation'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='display_srs', + field=models.ForeignKey(blank=True, help_text='Spatial Reference System used for display when no SRS is defined', null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.SpatialReferenceSystem', verbose_name='Spatial Reference System for display'), + ), + migrations.AlterField( + model_name='itemkey', + name='group', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.TargetKeyGroup'), + ), + migrations.AlterField( + model_name='itemkey', + name='importer', + field=models.ForeignKey(blank=True, help_text='Specific key to an import', null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Import'), + ), + migrations.AlterField( + model_name='itemkey', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.IshtarUser'), + ), + migrations.AlterField( + model_name='organization', + name='data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='organization', + name='history_m2m', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='organization', + name='organization_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='ishtar_common.OrganizationType', verbose_name='Type'), + ), + migrations.AlterField( + model_name='organization', + name='precise_town', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Town', verbose_name='Town (precise)'), + ), + migrations.AlterField( + model_name='person', + name='data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='person', + name='history_m2m', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='person', + name='precise_town', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Town', verbose_name='Town (precise)'), + ), + migrations.AlterField( + model_name='statscache', + name='values', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='targetkey', + name='associated_group', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.TargetKeyGroup'), + ), + migrations.AlterField( + model_name='targetkey', + name='associated_import', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Import'), + ), + migrations.AlterField( + model_name='targetkey', + name='associated_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.IshtarUser'), + ), + migrations.AlterField( + model_name='userprofile', + name='profile_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='ishtar_common.ProfileType', verbose_name='Profile type'), + ), + migrations.CreateModel( + name='ApiSearchModel', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('limit_query', models.TextField(blank=True, help_text='Search query add to each request', null=True, verbose_name='Limit query')), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.ApiUser')), + ], + options={ + 'verbose_name': 'Api - Search model', + 'verbose_name_plural': 'Api - Search models', + }, + ), + ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 6783a89b5..59248fa43 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -113,6 +113,11 @@ from ishtar_common.models_imports import ( TargetKeyGroup, ValueFormater, ) +from ishtar_common.models_rest import ( + ApiUser, + ApiSearchModel +) + from ishtar_common.utils import ( get_cache, create_slug, diff --git a/ishtar_common/models_rest.py b/ishtar_common/models_rest.py new file mode 100644 index 000000000..7d321ca92 --- /dev/null +++ b/ishtar_common/models_rest.py @@ -0,0 +1,32 @@ +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType +from django.contrib.gis.db import models + +from ishtar_common.utils import ugettext_lazy as _ + + +class ApiUser(models.Model): + user_ptr = models.OneToOneField( + User, primary_key=True, related_name="apiuser", on_delete=models.CASCADE + ) + ip = models.GenericIPAddressField(verbose_name=_("IP")) + + class Meta: + verbose_name = _("Api - User") + verbose_name_plural = _("Api - Users") + + def __str__(self): + return self.user_ptr.username + + +class ApiSearchModel(models.Model): + user = models.ForeignKey(ApiUser, on_delete=models.CASCADE) + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) + limit_query = models.TextField( + verbose_name=_("Limit query"), blank=True, null=True, + help_text=_("Search query add to each request") + ) + + class Meta: + verbose_name = _("Api - Search model") + verbose_name_plural = _("Api - Search models") diff --git a/ishtar_common/rest.py b/ishtar_common/rest.py new file mode 100644 index 000000000..9354a943d --- /dev/null +++ b/ishtar_common/rest.py @@ -0,0 +1,31 @@ +from rest_framework import authentication, permissions +from rest_framework.response import Response +from rest_framework.views import APIView + +from ishtar_common.models import ApiSearchModel + + +class IpModelPermission(permissions.BasePermission): + def has_permission(self, request, view): + if not request.user or not getattr(request.user, "apiuser", None): + return False + ip_addr = request.META['REMOTE_ADDR'] + q = ApiSearchModel.objects.filter( + user=request.user.apiuser, + user__ip=ip_addr, + content_type__app_label=view.model._meta.app_label, + content_type__model=view.model._meta.model_name) + return bool(q.count()) + + +class SearchAPIView(APIView): + model = None + authentication_classes = (authentication.TokenAuthentication,) + permission_classes = (permissions.IsAuthenticated, IpModelPermission) + + def __init__(self, **kwargs): + assert self.model is not None + super(SearchAPIView, self).__init__(**kwargs) + + def get(self, request, format=None): + return Response({}) |