From a61cf6ce597e9bd605783e5dbeba5f506a1329fc Mon Sep 17 00:00:00 2001 From: Mikko Nieminen Date: Mon, 9 Dec 2024 12:35:38 +0100 Subject: [PATCH] fix and refactor syncremote command (#1517, #1518) --- CHANGELOG.rst | 2 + docs/source/major_changes.rst | 1 + .../management/commands/syncremote.py | 51 ++++--------------- 3 files changed, 14 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fb3da42b..f1f066e9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,6 +29,7 @@ Changed - **Projectroles** - Update default OIDC login button template (#1503) - Update ownership transfer timeline event data (#1514) + - Refactor ``syncremote`` management command (#1518) Fixed ----- @@ -38,6 +39,7 @@ Fixed - Add workaround to ``ProjectInviteCreateView`` returning 404 with category and query string (#1510) - Broken tour help attachments in ``ProjectRoleView`` (#1512) - ``RoleAssignmentCreateView`` crash as delegate with promoting and delegate limit reached (#1515) + - ``syncremote`` command crash from legacy API media type and version (#1517) v1.0.2 (2024-09-09) diff --git a/docs/source/major_changes.rst b/docs/source/major_changes.rst index bda57c32..0435b921 100644 --- a/docs/source/major_changes.rst +++ b/docs/source/major_changes.rst @@ -23,6 +23,7 @@ Release Highlights - Fix invite create view redirect failing in categories - Fix role promoting crash as delegate with delegate limit reached - Fix requiring deprecated SODAR API settings in tests +- Fix syncremote management command crash - General bug fixes and minor updates Breaking Changes diff --git a/projectroles/management/commands/syncremote.py b/projectroles/management/commands/syncremote.py index a051acf6..b9c58f77 100644 --- a/projectroles/management/commands/syncremote.py +++ b/projectroles/management/commands/syncremote.py @@ -1,18 +1,13 @@ """Syncremote management command for synchronizing remote projects""" -import json -import ssl import sys -import urllib.request from django.conf import settings from django.core.management.base import BaseCommand -from django.urls import reverse from projectroles.management.logging import ManagementCommandLogger from projectroles.models import RemoteSite, SODAR_CONSTANTS from projectroles.remote_projects import RemoteProjectAPI -from projectroles.views_api import CORE_API_MEDIA_TYPE, CORE_API_DEFAULT_VERSION logger = ManagementCommandLogger(__name__) @@ -24,12 +19,13 @@ class Command(BaseCommand): - help = 'Synchronizes user and project data from a remote site' + help = 'Synchronizes user and project data from the source site' def add_arguments(self, parser): pass def handle(self, *args, **options): + remote_api = RemoteProjectAPI() if getattr(settings, 'PROJECTROLES_DISABLE_CATEGORIES', False): logger.info( 'Project categories and nesting disabled, ' @@ -39,11 +35,10 @@ def handle(self, *args, **options): if settings.PROJECTROLES_SITE_MODE != SITE_MODE_TARGET: logger.error('Site not in TARGET mode, unable to sync') sys.exit(1) - try: - site = RemoteSite.objects.get(mode=SITE_MODE_SOURCE) + source_site = RemoteSite.objects.get(mode=SITE_MODE_SOURCE) except RemoteSite.DoesNotExist: - logger.error('No source site defined, unable to sync') + logger.error('No source site set, unable to sync') sys.exit(1) if getattr(settings, 'PROJECTROLES_ALLOW_LOCAL_USERS', False): @@ -52,46 +47,22 @@ def handle(self, *args, **options): 'roles for existing local users' ) logger.info( - 'Retrieving data from remote site "{}" ({})..'.format( - site.name, site.get_url() + 'Retrieving data from source site "{}" ({})..'.format( + source_site.name, source_site.get_url() ) ) - api_url = site.get_url() + reverse( - 'projectroles:api_remote_get', kwargs={'secret': site.secret} - ) - try: - api_req = urllib.request.Request(api_url) - api_req.add_header( - 'accept', - '{}; version={}'.format( - CORE_API_MEDIA_TYPE, CORE_API_DEFAULT_VERSION - ), - ) - response = urllib.request.urlopen(api_req) - remote_data = json.loads(response.read()) - + remote_data = remote_api.get_remote_data(source_site) except Exception as ex: - helper_text = '' - if ( - isinstance(ex, urllib.error.URLError) - and isinstance(ex.reason, ssl.SSLError) - and ex.reason.reason == 'WRONG_VERSION_NUMBER' - ): - helper_text = ( - ' (most likely the server cannot handle HTTPS requests)' - ) logger.error( - 'Unable to retrieve data from remote site: {}{}'.format( - ex, helper_text - ) + 'Failed to retrieve data from source site: {}'.format(ex) ) sys.exit(1) - remote_api = RemoteProjectAPI() + logger.info('Synchronizing remote data from source site..') try: - remote_api.sync_remote_data(site, remote_data) + remote_api.sync_remote_data(source_site, remote_data) except Exception as ex: - logger.error('Remote sync cancelled with exception: {}'.format(ex)) + logger.error('Remote sync failed with exception: {}'.format(ex)) sys.exit(1) logger.info('Syncremote command OK')