Skip to content

Commit

Permalink
Merge branch 'qgis:master' into fix-icons-in-style-list
Browse files Browse the repository at this point in the history
  • Loading branch information
Xpirix authored Feb 1, 2024
2 parents 204d523 + a062b30 commit 3b5b7af
Show file tree
Hide file tree
Showing 39 changed files with 1,380 additions and 54 deletions.
2 changes: 2 additions & 0 deletions REQUIREMENTS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ django-bootstrap-pagination==1.7.1
django-sortable-listview==0.43
django-user-map
djangorestframework==3.12.2
pyjwt==1.7.1
djangorestframework-simplejwt==4.4
django-rest-auth==0.9.5
drf-yasg
django-matomo==0.1.6
3 changes: 3 additions & 0 deletions dockerize/docker/REQUIREMENTS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ requests==2.23.0
markdown==3.2.1

djangorestframework==3.11.2
pyjwt==1.7.1
djangorestframework-simplejwt==4.4

sorl-thumbnail-serializer-field==0.2.1
django-rest-auth==0.9.5
drf-yasg==1.17.1
Expand Down
6 changes: 3 additions & 3 deletions qgis-app/base/views/processing_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
View,
)
from django.views.generic.base import ContextMixin
from django.utils.encoding import escape_uri_path

GROUP_NAME = "Style Managers"

Expand Down Expand Up @@ -484,9 +485,8 @@ def get(self, request, *args, **kwargs):
response = HttpResponse(
zipfile.getvalue(), content_type="application/x-zip-compressed"
)
response["Content-Disposition"] = "attachment; filename=%s.zip" % (
slugify(object.name, allow_unicode=True)
)
zip_name = slugify(object.name, allow_unicode=True)
response["Content-Disposition"] = f"attachment; filename*=utf-8''{escape_uri_path(zip_name)}.zip"
return response


Expand Down
6 changes: 3 additions & 3 deletions qgis-app/fixtures/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"last_login": "2010-11-24 07:56:12",
"groups": [],
"user_permissions": [],
"password": "sha1$d6c11$4f3f04e104dc8bbe7950234f0cd8406a65df0bdf",
"password": "pbkdf2_sha256$150000$foQAQGi54z25$AQelhq+oBE3TOBJRT9F9UsEP5K1PSWQnQeozkmyc3fs=",
"email": "",
"date_joined": "2010-11-24 07:56:12"
}
Expand All @@ -30,7 +30,7 @@
"last_login": "2010-11-25 07:35:07",
"groups": [],
"user_permissions": [],
"password": "sha1$9ba9f$6088ef8abc2243a55e777e937159c8f2fd4920bb",
"password": "pbkdf2_sha256$150000$BBba4NloaWZO$XN4lzpxcvFSrLl1QqiwQz/0ZLiEH/JTgEJE/uRRXWto=",
"email": "admin@admin.it",
"date_joined": "2009-10-06 18:04:20"
}
Expand All @@ -48,7 +48,7 @@
"last_login": "2010-11-25 07:35:20",
"groups": [],
"user_permissions": [],
"password": "sha1$cb97a$221727796b3f551e342dca9d00112f072e399182",
"password": "pbkdf2_sha256$150000$GJga5YEinaWz$zJAjCXccvWHNPGmoZEjvBNgm1DGkjZGA3BmTVaNAxP4=",
"email": "",
"date_joined": "2010-11-25 07:35:20"
}
Expand Down
39 changes: 39 additions & 0 deletions qgis-app/plugins/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from functools import wraps
from django.http import HttpResponseForbidden
from rest_framework_simplejwt.authentication import JWTAuthentication
from plugins.models import Plugin, PluginOutstandingToken
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken, OutstandingToken
import datetime

def has_valid_token(function):
@wraps(function)
def wrap(request, *args, **kwargs):
auth_token = request.META.get("HTTP_AUTHORIZATION")
package_name = kwargs.get('package_name')
if not str(auth_token).startswith('Bearer'):
raise InvalidToken("Invalid token")

# Validate JWT token
authentication = JWTAuthentication()
try:
validated_token = authentication.get_validated_token(auth_token[7:])
plugin_id = validated_token.payload.get('plugin_id')
jti = validated_token.payload.get('refresh_jti')
token_id = OutstandingToken.objects.get(jti=jti).pk
is_blacklisted = BlacklistedToken.objects.filter(token_id=token_id).exists()
if not plugin_id or is_blacklisted:
raise InvalidToken("Invalid token")

plugin = Plugin.objects.get(pk=plugin_id)
if not plugin or plugin.package_name != package_name:
raise InvalidToken("Invalid token")
plugin_token = PluginOutstandingToken.objects.get(token__pk=token_id, plugin=plugin)
plugin_token.last_used_on = datetime.datetime.now()
plugin_token.save()
request.plugin_token = plugin_token
return function(request, *args, **kwargs)
except (InvalidToken, TokenError) as e:
return HttpResponseForbidden(str(e))

return wrap
13 changes: 12 additions & 1 deletion qgis-app/plugins/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.forms import CharField, ModelForm, ValidationError
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from plugins.models import Plugin, PluginVersion, PluginVersionFeedback
from plugins.models import Plugin, PluginOutstandingToken, PluginVersion, PluginVersionFeedback
from plugins.validator import validator
from taggit.forms import *

Expand Down Expand Up @@ -259,3 +259,14 @@ def clean(self):
self.cleaned_data['tasks'] = tasks

return self.cleaned_data

class PluginTokenForm(ModelForm):
"""
Form for token description editing
"""

class Meta:
model = PluginOutstandingToken
fields = (
"description",
)
40 changes: 40 additions & 0 deletions qgis-app/plugins/management/commands/organize_old_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# myapp/management/commands/organize_packages.py
import os
import shutil
from django.core.management.base import BaseCommand
from django.conf import settings
from plugins.models import PluginVersion

PLUGINS_STORAGE_PATH = getattr(settings, "PLUGINS_STORAGE_PATH", "packages")
class Command(BaseCommand):
help = 'Organize packages created before 2014 into folders by year'

def handle(self, *args, **options):
packages_dir = os.path.join(settings.MEDIA_ROOT, PLUGINS_STORAGE_PATH)

# Some of the packages created on 2014 also need to be organized
versions = PluginVersion.objects.filter(created_on__lt='2014-12-31').exclude(package__icontains='2014/')
self.stdout.write(self.style.NOTICE(f'{versions.count()} packages will be organized.'))

for version in versions:
year_folder = os.path.join(packages_dir, str(version.created_on.year))

# Create the year folder if it doesn't exist
os.makedirs(year_folder, exist_ok=True)

# Copy the package file to the year folder
old_path = version.package.path
if os.path.exists(old_path):
new_path = os.path.join(year_folder, os.path.basename(old_path))
if not os.path.exists(new_path):
shutil.copy(old_path, year_folder)

# Update the model with the new package path
version.package.name = os.path.relpath(new_path, settings.MEDIA_ROOT)
version.save()
else:
self.stdout.write(self.style.WARNING(f'Plugin version id {version.pk} ignored: {new_path} already exists.'))
else:
self.stdout.write(self.style.WARNING(f'Plugin version id {version.pk} ignored: {old_path} is not found.'))

self.stdout.write(self.style.SUCCESS('Packages organized successfully'))
6 changes: 2 additions & 4 deletions qgis-app/plugins/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
# Author: A. Pasotti

from django.contrib import auth
from django.contrib.auth.models import User

from rest_framework_simplejwt.authentication import JWTAuthentication

def HttpAuthMiddleware(get_response):
"""
Expand All @@ -12,7 +11,7 @@ def HttpAuthMiddleware(get_response):

def middleware(request):
auth_basic = request.META.get("HTTP_AUTHORIZATION")
if auth_basic:
if auth_basic and not str(auth_basic).startswith('Bearer'):
import base64

username, dummy, password = base64.decodestring(
Expand All @@ -27,7 +26,6 @@ def middleware(request):
# by logging the user in.
request.user = user
auth.login(request, user)

response = get_response(request)

# Code to be executed for each request/response after
Expand Down
24 changes: 24 additions & 0 deletions qgis-app/plugins/migrations/0005_pluginoutstandingtoken.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 2.2.25 on 2023-12-11 23:36

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('token_blacklist', '0007_auto_20171017_2214'),
('plugins', '0004_merge_20231122_0223'),
]

operations = [
migrations.CreateModel(
name='PluginOutstandingToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_blacklisted', models.BooleanField(default=False)),
('plugin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='plugins.Plugin')),
('token', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='token_blacklist.OutstandingToken')),
],
),
]
28 changes: 28 additions & 0 deletions qgis-app/plugins/migrations/0006_auto_20231218_0225.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 2.2.25 on 2023-12-18 02:25

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('plugins', '0005_pluginoutstandingtoken'),
]

operations = [
migrations.AddField(
model_name='pluginoutstandingtoken',
name='description',
field=models.CharField(blank=True, help_text="Describe this token so that it's easier to remember where you're using it.", max_length=512, null=True, verbose_name='Description'),
),
migrations.AddField(
model_name='pluginoutstandingtoken',
name='is_newly_created',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='pluginoutstandingtoken',
name='last_used_on',
field=models.DateTimeField(blank=True, null=True, verbose_name='Last used on'),
),
]
30 changes: 30 additions & 0 deletions qgis-app/plugins/migrations/0007_auto_20240109_0428.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 2.2.25 on 2024-01-09 04:28

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('plugins', '0006_auto_20231218_0225'),
]

operations = [
migrations.AddField(
model_name='pluginversion',
name='is_from_token',
field=models.BooleanField(default=False, verbose_name='Is uploaded using token'),
),
migrations.AddField(
model_name='pluginversion',
name='token',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='plugins.PluginOutstandingToken', verbose_name='Token used'),
),
migrations.AlterField(
model_name='pluginversion',
name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Created by'),
),
]
38 changes: 37 additions & 1 deletion qgis-app/plugins/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from django.utils import timezone
from djangoratings.fields import AnonymousRatingField
from taggit_autosuggest.managers import TaggableManager
from rest_framework_simplejwt.token_blacklist.models import OutstandingToken

PLUGINS_STORAGE_PATH = getattr(settings, "PLUGINS_STORAGE_PATH", "packages/%Y")
PLUGINS_FRESH_DAYS = getattr(settings, "PLUGINS_FRESH_DAYS", 30)
Expand Down Expand Up @@ -671,6 +672,33 @@ def from_db_value(self, value, expression, connection):
return self.to_python(value)


class PluginOutstandingToken(models.Model):
"""
Plugin outstanding token
"""
plugin = models.ForeignKey(
Plugin,
on_delete=models.CASCADE
)
token = models.ForeignKey(
OutstandingToken,
on_delete=models.CASCADE
)
is_blacklisted = models.BooleanField(default=False)
is_newly_created = models.BooleanField(default=False)
description = models.CharField(
verbose_name=_("Description"),
help_text=_("Describe this token so that it's easier to remember where you're using it."),
max_length=512,
blank=True,
null=True,
)
last_used_on = models.DateTimeField(
verbose_name=_("Last used on"),
blank=True,
null=True
)

class PluginVersion(models.Model):
"""
Plugin versions
Expand All @@ -686,7 +714,7 @@ class PluginVersion(models.Model):
downloads = models.IntegerField(_("Downloads"), default=0, editable=False)
# owners
created_by = models.ForeignKey(
User, verbose_name=_("Created by"), on_delete=models.CASCADE
User, verbose_name=_("Created by"), on_delete=models.CASCADE, null=True, blank=True
)
# version info, the first should be read from plugin
min_qg_version = QGVersionZeroForcedField(
Expand Down Expand Up @@ -722,6 +750,14 @@ class PluginVersion(models.Model):
blank=False,
null=True,
)
is_from_token = models.BooleanField(
_("Is uploaded using token"),
default=False
)
# Link to the token if upload is using token
token = models.ForeignKey(
PluginOutstandingToken, verbose_name=_("Token used"), on_delete=models.CASCADE, null=True, blank=True
)

# Managers, used in xml output
objects = models.Manager()
Expand Down
Loading

0 comments on commit 3b5b7af

Please sign in to comment.