From a90e5001864d5c9b18a4aeb834510ffbb939d690 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 8 Jul 2021 12:32:53 +0200 Subject: [PATCH 01/14] Bump Django version to 2.2.24 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ae2fa60f..585eae34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==2.1 +Django==2.2.24 django-fluent-dashboard==1.0.1 django-admin-tools==0.9.1 django-extensions==2.1.1 From c21a52a756a5719d8063833a13eb70722009d083 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 8 Jul 2021 12:46:17 +0200 Subject: [PATCH 02/14] Bump django-rest-framework version to 3.12.2 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 585eae34..40f2080b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ celery==3.1.23 kombu==3.0.35 billiard==3.3.0.23 Markdown==3.3.4 -djangorestframework==3.10.3 +djangorestframework==3.12.2 ecdsa==0.11 Pygments==1.6 django-filter==2.2.0 From 50f916fa4dc45996a0c2e35394436ee1c45ca509 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 8 Jul 2021 12:46:55 +0200 Subject: [PATCH 03/14] Replace `base_name` => `basename` for consisntency's sake Changed on DRF 3.12.x and related to PR https://github.com/encode/django-rest-framework/pull/5990 --- orchestra/api/helpers.py | 10 +++++----- orchestra/api/options.py | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/orchestra/api/helpers.py b/orchestra/api/helpers.py index 67594455..53803d9a 100644 --- a/orchestra/api/helpers.py +++ b/orchestra/api/helpers.py @@ -23,16 +23,16 @@ def link_wrap(view, view_names): return wrapper -def insert_links(viewset, base_name): - collection_links = ['api-root', '%s-list' % base_name] - object_links = ['api-root', '%s-list' % base_name, '%s-detail' % base_name] +def insert_links(viewset, basename): + collection_links = ['api-root', '%s-list' % basename] + object_links = ['api-root', '%s-list' % basename, '%s-detail' % basename] exception_links = ['api-root'] list_links = ['api-root'] - retrieve_links = ['api-root', '%s-list' % base_name] + retrieve_links = ['api-root', '%s-list' % basename] # Determine any `@action` or `@link` decorated methods on the viewset for methodname in dir(viewset): method = getattr(viewset, methodname) - view_name = '%s-%s' % (base_name, methodname.replace('_', '-')) + view_name = '%s-%s' % (basename, methodname.replace('_', '-')) if hasattr(method, 'collection_bind_to_methods'): list_links.append(view_name) retrieve_links.append(view_name) diff --git a/orchestra/api/options.py b/orchestra/api/options.py index 8b377564..4d429a03 100644 --- a/orchestra/api/options.py +++ b/orchestra/api/options.py @@ -18,33 +18,33 @@ class LogApiMixin(object): message = _('Added.') self.log(request, message, ADDITION, instance=self.serializer.instance) return response - + def perform_create(self, serializer): """ stores serializer for accessing instance on create() """ super(LogApiMixin, self).perform_create(serializer) self.serializer = serializer - + def update(self, request, *args, **kwargs): from django.contrib.admin.models import CHANGE response = super(LogApiMixin, self).update(request, *args, **kwargs) message = _('Changed data') self.log(request, message, CHANGE) return response - + def partial_update(self, request, *args, **kwargs): from django.contrib.admin.models import CHANGE response = super(LogApiMixin, self).partial_update(request, *args, **kwargs) message = _('Changed %s') % response.data self.log(request, message, CHANGE) return response - + def destroy(self, request, *args, **kwargs): from django.contrib.admin.models import DELETION message = _('Deleted') self.log(request, message, DELETION) response = super(LogApiMixin, self).destroy(request, *args, **kwargs) return response - + def log(self, request, message, action, instance=None): from django.contrib.admin.models import LogEntry instance = instance or self.get_object() @@ -64,21 +64,21 @@ class LinkHeaderRouter(DefaultRouter): APIRoot = import_class(settings.ORCHESTRA_API_ROOT_VIEW) APIRoot.router = self return APIRoot.as_view() - - def register(self, prefix, viewset, base_name=None): + + def register(self, prefix, viewset, basename=None): """ inserts link headers on every viewset """ - if base_name is None: - base_name = self.get_default_base_name(viewset) - insert_links(viewset, base_name) - self.registry.append((prefix, viewset, base_name)) - + if basename is None: + basename = self.get_default_basename(viewset) + insert_links(viewset, basename) + self.registry.append((prefix, viewset, basename)) + def get_viewset(self, prefix_or_model): for _prefix, viewset, __ in self.registry: if _prefix == prefix_or_model or viewset.queryset.model == prefix_or_model: return viewset msg = "%s does not have a regiestered viewset" % prefix_or_model raise KeyError(msg) - + def insert(self, prefix_or_model, name, field, **kwargs): """ Dynamically add new fields to an existing serializer """ viewset = self.get_viewset(prefix_or_model) From de26baf75ac1c4dbe8067849307936d998f2a6a9 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 8 Jul 2021 13:49:24 +0200 Subject: [PATCH 04/14] Refactor TransactionProcessAdmin.delete_selected override Override `delete_queryset` instead of overriding `delete_selected` action. Fixes admin.E130 error. Related ticket https://github.com/django/django/pull/10603 --- orchestra/contrib/payments/actions.py | 10 ---------- orchestra/contrib/payments/admin.py | 9 ++++++++- orchestra/contrib/payments/helpers.py | 1 - 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/orchestra/contrib/payments/actions.py b/orchestra/contrib/payments/actions.py index e6b4b348..d2f5a433 100644 --- a/orchestra/contrib/payments/actions.py +++ b/orchestra/contrib/payments/actions.py @@ -175,16 +175,6 @@ commit.url_name = 'commit' commit.short_description = _("Commit") -def delete_selected(modeladmin, request, queryset): - """ Has to have same name as admin.actions.delete_selected """ - related_transactions = helpers.pre_delete_processes(modeladmin, request, queryset) - response = actions.delete_selected(modeladmin, request, queryset) - if response is None: - helpers.post_delete_processes(modeladmin, request, related_transactions) - return response -delete_selected.short_description = actions.delete_selected.short_description - - def report(modeladmin, request, queryset): if queryset.model == Transaction: transactions = queryset diff --git a/orchestra/contrib/payments/admin.py b/orchestra/contrib/payments/admin.py index 45b67a48..016543ac 100644 --- a/orchestra/contrib/payments/admin.py +++ b/orchestra/contrib/payments/admin.py @@ -179,7 +179,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin): change_view_actions = ( actions.mark_process_as_executed, actions.abort, actions.commit, actions.report ) - actions = change_view_actions + (actions.delete_selected,) + actions = change_view_actions display_state = admin_colored('state', colors=PROCESS_STATE_COLORS) display_created_at = admin_date('created_at', short_description=_("Created")) @@ -233,6 +233,13 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin): helpers.post_delete_processes(self, request, related_transactions) return response + def delete_queryset(self, request, queryset): + # override default admin action delete behaviour + related_transactions = helpers.pre_delete_processes(self, request, queryset) + super().delete_queryset(self, request, queryset) + helpers.post_delete_processes(self, request, related_transactions) + + admin.site.register(PaymentSource, PaymentSourceAdmin) admin.site.register(Transaction, TransactionAdmin) admin.site.register(TransactionProcess, TransactionProcessAdmin) diff --git a/orchestra/contrib/payments/helpers.py b/orchestra/contrib/payments/helpers.py index 9fde2489..b6645d53 100644 --- a/orchestra/contrib/payments/helpers.py +++ b/orchestra/contrib/payments/helpers.py @@ -5,7 +5,6 @@ from .models import Transaction def pre_delete_processes(modeladmin, request, queryset): - """ Has to have same name as admin.actions.delete_selected """ if not queryset: messages.warning(request, _("No transaction process selected.")) From 1faab905d65c968764f2f00b5b90156a48848ae8 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 8 Jul 2021 13:58:37 +0200 Subject: [PATCH 05/14] Remove duplicated 'delete_selected' action of TicketAdmin Fixes admin.E130 error --- orchestra/contrib/issues/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orchestra/contrib/issues/admin.py b/orchestra/contrib/issues/admin.py index 66881ddd..7b607fe9 100644 --- a/orchestra/contrib/issues/admin.py +++ b/orchestra/contrib/issues/admin.py @@ -138,7 +138,7 @@ class TicketAdmin(ExtendedModelAdmin): 'owner__username' ) actions = ( - mark_as_unread, mark_as_read, 'delete_selected', reject_tickets, + mark_as_unread, mark_as_read, reject_tickets, resolve_tickets, close_tickets, take_tickets ) sudo_actions = ('delete_selected',) From b37d9cc51548d1e8e6d8b8e6e65d961b13e2015f Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 8 Jul 2021 14:48:51 +0200 Subject: [PATCH 06/14] Remove unneeded custom 'delete_selected' `has_delete_permission` already avoids deleting main system users --- orchestra/contrib/systemusers/actions.py | 26 ------------------------ orchestra/contrib/systemusers/admin.py | 20 +++++++++++------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/orchestra/contrib/systemusers/actions.py b/orchestra/contrib/systemusers/actions.py index f2e53ec5..80743ea4 100644 --- a/orchestra/contrib/systemusers/actions.py +++ b/orchestra/contrib/systemusers/actions.py @@ -128,29 +128,3 @@ def create_link(modeladmin, request, queryset): return TemplateResponse(request, 'admin/systemusers/systemuser/create_link.html', context) create_link.url_name = 'create-link' create_link.tool_description = _("Create link") - - -def delete_selected(modeladmin, request, queryset): - """ wrapper arround admin.actions.delete_selected to prevent main system users deletion """ - opts = modeladmin.model._meta - app_label = opts.app_label - # Check that the user has delete permission for the actual model - if not modeladmin.has_delete_permission(request): - raise PermissionDenied - else: - accounts = [] - for user in queryset: - if user.is_main: - accounts.append(user.username) - if accounts: - n = len(accounts) - messages.error(request, ungettext( - "You have selected one main system user (%(accounts)s), which can not be deleted.", - "You have selected some main system users which can not be deleted (%(accounts)s).", - n) % { - 'accounts': ', '.join(accounts[:10]+['...'] if n > 10 else accounts) - } - ) - return - return admin.actions.delete_selected(modeladmin, request, queryset) -delete_selected.short_description = _("Delete selected %(verbose_name_plural)s") diff --git a/orchestra/contrib/systemusers/admin.py b/orchestra/contrib/systemusers/admin.py index fed11679..59b4c271 100644 --- a/orchestra/contrib/systemusers/admin.py +++ b/orchestra/contrib/systemusers/admin.py @@ -1,4 +1,4 @@ -from django.contrib import admin +from django.contrib import admin, messages from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin @@ -7,7 +7,7 @@ from orchestra.contrib.accounts.actions import list_accounts from orchestra.contrib.accounts.admin import SelectAccountAdminMixin from orchestra.contrib.accounts.filters import IsActiveListFilter -from .actions import set_permission, create_link, delete_selected +from .actions import set_permission, create_link from .filters import IsMainListFilter from .forms import SystemUserCreationForm, SystemUserChangeForm from .models import SystemUser @@ -43,18 +43,18 @@ class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, Extende form = SystemUserChangeForm ordering = ('-id',) change_view_actions = (set_permission, create_link) - actions = (disable, enable, delete_selected, list_accounts) + change_view_actions - + actions = (disable, enable, list_accounts) + change_view_actions + def display_main(self, user): return user.is_main display_main.short_description = _("Main") display_main.boolean = True - + def display_home(self, user): return user.get_home() display_home.short_description = _("Home") display_home.admin_order_field = 'home' - + def get_form(self, request, obj=None, **kwargs): form = super(SystemUserAdmin, self).get_form(request, obj, **kwargs) form.account = self.account @@ -65,9 +65,15 @@ class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, Extende formfield = form.base_fields['groups'] formfield.queryset = formfield.queryset.exclude(id=obj.id) return form - + def has_delete_permission(self, request, obj=None): if obj and obj.is_main: + self.message_user(request, _( + "You have selected one main system user (%(account)s), which can not be deleted.", + ) % {'account': obj}, + messages.ERROR, + ) + return False return super(SystemUserAdmin, self).has_delete_permission(request, obj) From d3e5ea59a9fde5575028861f29b2fa6df04dc566 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Fri, 9 Jul 2021 12:34:43 +0200 Subject: [PATCH 07/14] Bump passlib version to 1.7.4 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 40f2080b..b0b26a72 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ Pygments==1.6 django-filter==2.2.0 jsonfield==0.9.22 python-dateutil>=2.7.0 -https://github.com/glic3rinu/passlib/archive/master.zip +passlib==1.7.4 django-iban==0.3.0 requests phonenumbers From cda47e2fb6846ec9833bb9161684fd2b7cd1c298 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Fri, 9 Jul 2021 13:03:53 +0200 Subject: [PATCH 08/14] Remove deprecated passlib setting __vary_rounds Deprecated since version 1.7 and will be removed in 2.0 The (very minimal) security benefit it provides was judged to not be worth code complexity it requires. --- orchestra/conf/project_template/project_name/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/orchestra/conf/project_template/project_name/settings.py b/orchestra/conf/project_template/project_name/settings.py index 576dd0b8..c59610d7 100644 --- a/orchestra/conf/project_template/project_name/settings.py +++ b/orchestra/conf/project_template/project_name/settings.py @@ -260,7 +260,6 @@ PASSLIB_CONFIG = ( "default = sha512_crypt\n" "deprecated = django_pbkdf2_sha1, django_salted_sha1, django_salted_md5, " " django_des_crypt, des_crypt, hex_md5\n" - "all__vary_rounds = 0.05\n" "django_pbkdf2_sha256__min_rounds = 10000\n" "sha512_crypt__min_rounds = 80000\n" "staff__django_pbkdf2_sha256__default_rounds = 12500\n" From e3ec82a182eb8ec82d6804dc6e0bb2b2b327c54a Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Tue, 13 Jul 2021 11:24:07 +0200 Subject: [PATCH 09/14] Bump django-rest-framework version to 3.12.4 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b0b26a72..6a896f11 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ celery==3.1.23 kombu==3.0.35 billiard==3.3.0.23 Markdown==3.3.4 -djangorestframework==3.12.2 +djangorestframework==3.12.4 ecdsa==0.11 Pygments==1.6 django-filter==2.2.0 From a400c25de9e56fa21831306fe355235e5cce6755 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Tue, 13 Jul 2021 11:48:41 +0200 Subject: [PATCH 10/14] Upgrade django-filter & django-extensions --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6a896f11..72955a68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ Django==2.2.24 django-fluent-dashboard==1.0.1 django-admin-tools==0.9.1 -django-extensions==2.1.1 +django-extensions==3.1.3 django-celery==3.2.1 celery==3.1.23 kombu==3.0.35 @@ -10,7 +10,7 @@ Markdown==3.3.4 djangorestframework==3.12.4 ecdsa==0.11 Pygments==1.6 -django-filter==2.2.0 +django-filter==2.4.0 jsonfield==0.9.22 python-dateutil>=2.7.0 passlib==1.7.4 From 1258a2768839bedecb89a9fb95be3600f217136a Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Tue, 13 Jul 2021 12:01:27 +0200 Subject: [PATCH 11/14] Bump django-localflavor version to 3.1 See related issue #10 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 72955a68..91ad2625 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ django-iban==0.3.0 requests phonenumbers django-countries -django-localflavor +django-localflavor==3.1 amqp anyjson pytz From 9f80c75da75c322f049a33bcb3856a5a5b2b778d Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Tue, 13 Jul 2021 12:09:29 +0200 Subject: [PATCH 12/14] Drop unused python-ecdsa dependency --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 91ad2625..53252fd3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,6 @@ kombu==3.0.35 billiard==3.3.0.23 Markdown==3.3.4 djangorestframework==3.12.4 -ecdsa==0.11 Pygments==1.6 django-filter==2.4.0 jsonfield==0.9.22 From 6720df314b3ef29449472ae13def052318200577 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Tue, 13 Jul 2021 12:46:20 +0200 Subject: [PATCH 13/14] Bump jsonfield version to 3.1.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 53252fd3..94b0f73b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ Markdown==3.3.4 djangorestframework==3.12.4 Pygments==1.6 django-filter==2.4.0 -jsonfield==0.9.22 +jsonfield==3.1.0 python-dateutil>=2.7.0 passlib==1.7.4 django-iban==0.3.0 From 361b4b41a8191ee9171d4f910feeb7da6ef3da27 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Tue, 13 Jul 2021 12:55:35 +0200 Subject: [PATCH 14/14] Upgrade Pygments and phonenumbers libraries --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 94b0f73b..14d5ce5e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,14 +8,14 @@ kombu==3.0.35 billiard==3.3.0.23 Markdown==3.3.4 djangorestframework==3.12.4 -Pygments==1.6 +Pygments==2.9.0 django-filter==2.4.0 jsonfield==3.1.0 python-dateutil>=2.7.0 passlib==1.7.4 django-iban==0.3.0 requests -phonenumbers +phonenumbers==8.12.27 django-countries django-localflavor==3.1 amqp