From 7290523d956856b96436473e4af587ca7e2ac300 Mon Sep 17 00:00:00 2001 From: abram axel booth Date: Fri, 12 Jul 2024 10:45:56 -0400 Subject: [PATCH 1/2] fix: waffle flags in flask context (use `api.waffle.utils.flag_is_active`, not `waffle.flag_is_active`) --- addons/base/views.py | 5 +++-- api/institutions/authentication.py | 4 ++-- osf/external/messages/celery_publishers.py | 5 +++-- osf/models/metaschema.py | 4 ++-- osf/models/mixins.py | 7 +++---- website/ember_osf_web/decorators.py | 4 ++-- website/oauth/views.py | 4 ++-- website/project/views/file.py | 6 +++--- website/views.py | 15 +++++++-------- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/addons/base/views.py b/addons/base/views.py index ecc17b77844..2e061f4f665 100644 --- a/addons/base/views.py +++ b/addons/base/views.py @@ -24,6 +24,7 @@ from addons.osfstorage.models import OsfStorageFileNode from addons.osfstorage.utils import enqueue_update_analytics +from api.waffle.utils import flag_is_active from framework import sentry from framework.auth import Auth from framework.auth import cas @@ -869,10 +870,10 @@ def addon_view_or_download_file(auth, path, provider, **kwargs): # There's no download action redirect to the Ember front-end file view and create guid. if action != 'download': - if isinstance(target, Node) and waffle.flag_is_active(request, features.EMBER_FILE_PROJECT_DETAIL): + if isinstance(target, Node) and flag_is_active(request, features.EMBER_FILE_PROJECT_DETAIL): guid = file_node.get_guid(create=True) return redirect(f'{settings.DOMAIN}{guid._id}/') - if isinstance(target, Registration) and waffle.flag_is_active(request, features.EMBER_FILE_REGISTRATION_DETAIL): + if isinstance(target, Registration) and flag_is_active(request, features.EMBER_FILE_REGISTRATION_DETAIL): guid = file_node.get_guid(create=True) return redirect(f'{settings.DOMAIN}{guid._id}/') diff --git a/api/institutions/authentication.py b/api/institutions/authentication.py index 45d969f169a..a6402bfffec 100644 --- a/api/institutions/authentication.py +++ b/api/institutions/authentication.py @@ -4,7 +4,6 @@ import jwe import jwt -import waffle from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed, PermissionDenied @@ -14,6 +13,7 @@ from api.base.authentication import drf from api.base import exceptions, settings +from api.waffle.utils import flag_is_active from framework import sentry from framework.auth import get_or_create_institutional_user @@ -339,7 +339,7 @@ def authenticate(self, request): user=user, domain=DOMAIN, osf_support_email=OSF_SUPPORT_EMAIL, - storage_flag_is_active=waffle.flag_is_active(request, features.STORAGE_I18N), + storage_flag_is_active=flag_is_active(request, features.STORAGE_I18N), ) # Add the email to the user's account if it is identified by the eppn diff --git a/osf/external/messages/celery_publishers.py b/osf/external/messages/celery_publishers.py index 3c3c90f9d37..7ac04cd48bd 100644 --- a/osf/external/messages/celery_publishers.py +++ b/osf/external/messages/celery_publishers.py @@ -1,5 +1,6 @@ -import waffle from kombu import Exchange + +from api.waffle.utils import flag_is_active from framework.celery_tasks import app as celery_app from website import settings from osf import features @@ -36,7 +37,7 @@ def publish_merged_user(user): def _publish_user_status_change(body: dict): - if settings.USE_CELERY and waffle.flag_is_active(get_current_request(), features.ENABLE_GV): + if settings.USE_CELERY and flag_is_active(get_current_request(), features.ENABLE_GV): with celery_app.producer_pool.acquire() as producer: producer.publish( body=body, diff --git a/osf/models/metaschema.py b/osf/models/metaschema.py index f3a3e22ecc3..b4b94df05b3 100644 --- a/osf/models/metaschema.py +++ b/osf/models/metaschema.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- from django.db import models -import waffle import jsonschema from website.util import api_v2_url from .base import BaseModel, ObjectIDMixin from .validators import RegistrationResponsesValidator +from api.waffle.utils import flag_is_active from osf.utils.datetime_aware_jsonfield import DateTimeAwareJSONField from osf.exceptions import ValidationValueError, ValidationError @@ -36,7 +36,7 @@ def allow_egap_admins(queryset, request): Allows egap admins to see EGAP registrations as visible, should be deleted when when the EGAP registry goes live. """ - if hasattr(request, 'user') and not waffle.flag_is_active(request, EGAP_ADMINS): + if hasattr(request, 'user') and not flag_is_active(request, EGAP_ADMINS): return queryset.exclude(name='EGAP Registration') return queryset diff --git a/osf/models/mixins.py b/osf/models/mixins.py index e22acb24857..fe8642f2a99 100644 --- a/osf/models/mixins.py +++ b/osf/models/mixins.py @@ -3,8 +3,6 @@ import markupsafe import logging -import waffle - from django.apps import apps from django.contrib.auth.models import Group, AnonymousUser from django.core.exceptions import ObjectDoesNotExist, ValidationError @@ -14,6 +12,7 @@ from guardian.shortcuts import assign_perm, get_perms, remove_perm, get_group_perms from api.providers.workflows import Workflows, PUBLIC_STATES +from api.waffle.utils import flag_is_active from framework import status from framework.auth import Auth from framework.auth.core import get_user @@ -491,7 +490,7 @@ def addons(self): def get_addons(self): request, user_id = get_request_and_user_id() - if waffle.flag_is_active(request, features.ENABLE_GV): + if flag_is_active(request, features.ENABLE_GV): osf_addons = filter( lambda x: x is not None, (self.get_addon(addon) for addon in self.OSF_HOSTED_ADDONS) @@ -528,7 +527,7 @@ def get_addon(self, name, is_deleted=False): # Avoid test-breakages by avoiding early access to the request context if name not in self.OSF_HOSTED_ADDONS: request, user_id = get_request_and_user_id() - if waffle.flag_is_active(request, features.ENABLE_GV): + if flag_is_active(request, features.ENABLE_GV): return self._get_addon_from_gv(gv_pk=name, requesting_user_id=user_id) try: diff --git a/website/ember_osf_web/decorators.py b/website/ember_osf_web/decorators.py index 43780f7e4c4..978445f2bf3 100644 --- a/website/ember_osf_web/decorators.py +++ b/website/ember_osf_web/decorators.py @@ -1,8 +1,8 @@ -import waffle import functools from flask import request +from api.waffle.utils import flag_is_active from website.ember_osf_web.views import use_ember_app @@ -14,7 +14,7 @@ def ember_flag_is_active(flag_name): def decorator(func): @functools.wraps(func) def wrapped(*args, **kwargs): - if waffle.flag_is_active(request, flag_name): + if flag_is_active(request, flag_name): return use_ember_app() else: return func(*args, **kwargs) diff --git a/website/oauth/views.py b/website/oauth/views.py index 3367047e99f..26199868d28 100644 --- a/website/oauth/views.py +++ b/website/oauth/views.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from rest_framework import status as http_status -import waffle import requests from urllib.parse import ( urlencode, @@ -11,6 +10,7 @@ from flask import redirect, request +from api.waffle.utils import flag_is_active from framework.auth.decorators import must_be_logged_in from framework.exceptions import HTTPError from osf.models import ExternalAccount @@ -50,7 +50,7 @@ def oauth_connect(service_name, auth): @must_be_logged_in def oauth_callback(service_name, auth): - if waffle.flag_is_active(request, features.ENABLE_GV): + if flag_is_active(request, features.ENABLE_GV): _forward_to_addon_service() return {} diff --git a/website/project/views/file.py b/website/project/views/file.py index 9459b78bf67..56da1718765 100644 --- a/website/project/views/file.py +++ b/website/project/views/file.py @@ -1,12 +1,12 @@ """ Files views. """ -import waffle from flask import request from osf import features from osf.models import Node, Registration +from api.waffle.utils import flag_is_active from website.util import rubeus from website.project.decorators import must_be_contributor_or_public, must_not_be_retracted_registration from website.project.views.node import _view_project @@ -19,10 +19,10 @@ def collect_file_trees(auth, node, **kwargs): """Collect file trees for all add-ons implementing HGrid views, then format data as appropriate. """ - if isinstance(node, Node) and waffle.flag_is_active(request, features.EMBER_PROJECT_FILES): + if isinstance(node, Node) and flag_is_active(request, features.EMBER_PROJECT_FILES): return use_ember_app() - if isinstance(node, Registration) and waffle.flag_is_active(request, features.EMBER_REGISTRATION_FILES): + if isinstance(node, Registration) and flag_is_active(request, features.EMBER_REGISTRATION_FILES): return use_ember_app() serialized = _view_project(node, auth, primary=True) diff --git a/website/views.py b/website/views.py index adee1d27887..9de84299652 100644 --- a/website/views.py +++ b/website/views.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals import furl -import waffle import itertools from rest_framework import status as http_status import logging @@ -35,7 +34,7 @@ from osf.utils import permissions from osf.metadata.tools import pls_gather_metadata_file -from api.waffle.utils import storage_i18n_flag_active +from api.waffle.utils import storage_i18n_flag_active, flag_is_active logger = logging.getLogger(__name__) preprints_dir = os.path.abspath(os.path.join(os.getcwd(), EXTERNAL_EMBER_APPS['preprints']['path'])) @@ -336,25 +335,25 @@ def resolve_guid(guid, suffix=None): return stream_emberapp(EXTERNAL_EMBER_APPS['preprints']['server'], preprints_dir) return use_ember_app() - elif isinstance(resource, Registration) and (clean_suffix in ('', 'comments', 'links', 'components', 'resources',)) and waffle.flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): + elif isinstance(resource, Registration) and (clean_suffix in ('', 'comments', 'links', 'components', 'resources',)) and flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): return use_ember_app() - elif isinstance(resource, Registration) and clean_suffix and clean_suffix.startswith('metadata') and waffle.flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): + elif isinstance(resource, Registration) and clean_suffix and clean_suffix.startswith('metadata') and flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): return use_ember_app() - elif isinstance(resource, Registration) and (clean_suffix in ('files', 'files/osfstorage')) and waffle.flag_is_active(request, features.EMBER_REGISTRATION_FILES): + elif isinstance(resource, Registration) and (clean_suffix in ('files', 'files/osfstorage')) and flag_is_active(request, features.EMBER_REGISTRATION_FILES): return use_ember_app() - elif isinstance(resource, Node) and clean_suffix and any(path.startswith(clean_suffix) for path in addon_paths) and waffle.flag_is_active(request, features.EMBER_PROJECT_FILES): + elif isinstance(resource, Node) and clean_suffix and any(path.startswith(clean_suffix) for path in addon_paths) and flag_is_active(request, features.EMBER_PROJECT_FILES): return use_ember_app() elif isinstance(resource, Node) and clean_suffix and clean_suffix.startswith('metadata'): return use_ember_app() elif isinstance(resource, BaseFileNode) and resource.is_file and not isinstance(resource.target, Preprint): - if isinstance(resource.target, Registration) and waffle.flag_is_active(request, features.EMBER_FILE_REGISTRATION_DETAIL): + if isinstance(resource.target, Registration) and flag_is_active(request, features.EMBER_FILE_REGISTRATION_DETAIL): return use_ember_app() - if isinstance(resource.target, Node) and waffle.flag_is_active(request, features.EMBER_FILE_PROJECT_DETAIL): + if isinstance(resource.target, Node) and flag_is_active(request, features.EMBER_FILE_PROJECT_DETAIL): return use_ember_app() # Redirect to legacy endpoint for Nodes, Wikis etc. From bb54ae04dccaa970f606e7d35bbdab968166d4c1 Mon Sep 17 00:00:00 2001 From: abram axel booth Date: Fri, 12 Jul 2024 11:21:33 -0400 Subject: [PATCH 2/2] fix: do flask stuff only when flask --- api/waffle/utils.py | 19 +++++++++++-------- tests/test_ember_osf_web.py | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/api/waffle/utils.py b/api/waffle/utils.py index 9b6236e9a2e..573afe93be5 100644 --- a/api/waffle/utils.py +++ b/api/waffle/utils.py @@ -2,7 +2,7 @@ from framework.auth.core import _get_current_user from osf import features -from flask import request +import flask class MockUser(object): @@ -13,18 +13,21 @@ def flag_is_active(request, flag_name): """ This function changes the typical flask request object so it can be used by django-waffle. Other modifications for django-waffle can be found in the __call__ method of OsfWebRenderer. - :param flask request object: - :return flask request object: + + :param request (flask or django): + :param flag name (string): + :return bool: """ - # Waffle does not enjoy NoneTypes as user values. - request.user = _get_current_user() or MockUser() - request.COOKIES = getattr(request, 'cookies', None) + if isinstance(request, flask.Request): + # Waffle does not enjoy NoneTypes as user values. + request.user = _get_current_user() or MockUser() + request.COOKIES = getattr(request, 'cookies', None) return waffle.flag_is_active(request, flag_name) def storage_i18n_flag_active(): - return flag_is_active(request, features.STORAGE_I18N) + return flag_is_active(flask.request, features.STORAGE_I18N) def storage_usage_flag_active(): - return flag_is_active(request, features.STORAGE_USAGE) + return flag_is_active(flask.request, features.STORAGE_USAGE) diff --git a/tests/test_ember_osf_web.py b/tests/test_ember_osf_web.py index 6a3f074968b..14cd1c50fdb 100644 --- a/tests/test_ember_osf_web.py +++ b/tests/test_ember_osf_web.py @@ -32,7 +32,7 @@ def test_dont_use_ember_app(self, mock_use_ember_app): assert not mock_use_ember_app.called @mock.patch('api.waffle.utils._get_current_user') - @mock.patch('website.ember_osf_web.decorators.waffle.flag_is_active') + @mock.patch('website.ember_osf_web.decorators.flag_is_active') @mock.patch('website.ember_osf_web.decorators.use_ember_app') def test_ember_flag_is_active_authenticated_user(self, mock_use_ember_app, mock_flag_is_active, mock__get_current_user): # mock over external module 'waflle.flag_is_active` not ours @@ -46,7 +46,7 @@ def test_ember_flag_is_active_authenticated_user(self, mock_use_ember_app, mock_ mock_use_ember_app.assert_called_with() @mock.patch('api.waffle.utils._get_current_user', return_value=None) - @mock.patch('website.ember_osf_web.decorators.waffle.flag_is_active') + @mock.patch('website.ember_osf_web.decorators.flag_is_active') @mock.patch('website.ember_osf_web.decorators.use_ember_app') def test_ember_flag_is_active_unauthenticated_user(self, mock_use_ember_app, mock_flag_is_active, mock__get_current_user): # mock over external module 'waflle.flag_is_active` not ours