Skip to content

Commit

Permalink
move tighter permissions behind a feature flag
Browse files Browse the repository at this point in the history
  • Loading branch information
aaxelb committed Oct 30, 2024
1 parent ed13c34 commit 9ac4cc9
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 24 deletions.
1 change: 1 addition & 0 deletions share/models/feature_flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class FeatureFlag(models.Model):
ELASTIC_EIGHT_DEFAULT = 'elastic_eight_default'
IGNORE_SHAREV2_INGEST = 'ignore_sharev2_ingest'
SUGGEST_CREATOR_FACET = 'suggest_creator_facet'
FORBID_UNTRUSTED_FEED = 'forbid_untrusted_feed'

# name _should_ be one of the constants above, but that is not enforced by `choices`
name = models.TextField(unique=True)
Expand Down
48 changes: 26 additions & 22 deletions tests/trove/views/test_ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

from django.test import TestCase

from share.models.feature_flag import FeatureFlag
from tests import factories
from tests._testutil import patch_feature_flag


class TestIngest(TestCase):
Expand Down Expand Up @@ -136,20 +138,21 @@ def test_anonymous_post(self):
self.assertFalse(_mock_tract.swallow.called)

def test_nontrusted_post(self):
_nontrusted_user = factories.ShareUserFactory()
with mock.patch('trove.views.ingest.digestive_tract') as _mock_tract:
_resp = self.client.post(
'/trove/ingest?' + urlencode({
'focus_iri': 'https://foo.example/blarg',
'record_identifier': 'blarg',
'is_supplementary': '',
}),
content_type='text/turtle',
data='turtleturtleturtle',
HTTP_AUTHORIZATION=_nontrusted_user.authorization(),
)
self.assertEqual(_resp.status_code, HTTPStatus.FORBIDDEN)
self.assertFalse(_mock_tract.swallow.called)
with patch_feature_flag(FeatureFlag.FORBID_UNTRUSTED_FEED):
_nontrusted_user = factories.ShareUserFactory()
with mock.patch('trove.views.ingest.digestive_tract') as _mock_tract:
_resp = self.client.post(
'/trove/ingest?' + urlencode({
'focus_iri': 'https://foo.example/blarg',
'record_identifier': 'blarg',
'is_supplementary': '',
}),
content_type='text/turtle',
data='turtleturtleturtle',
HTTP_AUTHORIZATION=_nontrusted_user.authorization(),
)
self.assertEqual(_resp.status_code, HTTPStatus.FORBIDDEN)
self.assertFalse(_mock_tract.swallow.called)

def test_anonymous_delete(self):
with mock.patch('trove.views.ingest.digestive_tract') as _mock_tract:
Expand All @@ -158,14 +161,15 @@ def test_anonymous_delete(self):
self.assertFalse(_mock_tract.expel.called)

def test_nontrusted_delete(self):
_nontrusted_user = factories.ShareUserFactory()
with mock.patch('trove.views.ingest.digestive_tract') as _mock_tract:
_resp = self.client.delete(
'/trove/ingest?record_identifier=blarg',
HTTP_AUTHORIZATION=_nontrusted_user.authorization(),
)
self.assertEqual(_resp.status_code, HTTPStatus.FORBIDDEN)
self.assertFalse(_mock_tract.expel.called)
with patch_feature_flag(FeatureFlag.FORBID_UNTRUSTED_FEED):
_nontrusted_user = factories.ShareUserFactory()
with mock.patch('trove.views.ingest.digestive_tract') as _mock_tract:
_resp = self.client.delete(
'/trove/ingest?record_identifier=blarg',
HTTP_AUTHORIZATION=_nontrusted_user.authorization(),
)
self.assertEqual(_resp.status_code, HTTPStatus.FORBIDDEN)
self.assertFalse(_mock_tract.expel.called)

def test_invalid_expiration_date(self):
with mock.patch('trove.views.ingest.digestive_tract') as _mock_tract:
Expand Down
5 changes: 3 additions & 2 deletions trove/views/ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.views import View

from share import exceptions
from share.models.feature_flag import FeatureFlag
from trove import digestive_tract


Expand All @@ -22,7 +23,7 @@ def post(self, request):
# TODO: permissions by focus_iri domain (compare with user's Source)?
if not request.user.is_authenticated:
return http.HttpResponse(status=HTTPStatus.UNAUTHORIZED)
if not request.user.is_trusted:
if FeatureFlag.objects.flag_is_up(FeatureFlag.FORBID_UNTRUSTED_FEED) and not request.user.is_trusted:
return http.HttpResponse(status=HTTPStatus.FORBIDDEN)
# TODO: declare/validate params with dataclass
_focus_iri = request.GET.get('focus_iri')
Expand Down Expand Up @@ -61,7 +62,7 @@ def delete(self, request):
# TODO: cleaner permissions
if not request.user.is_authenticated:
return http.HttpResponse(status=HTTPStatus.UNAUTHORIZED)
if not request.user.is_trusted:
if FeatureFlag.objects.flag_is_up(FeatureFlag.FORBID_UNTRUSTED_FEED) and not request.user.is_trusted:
return http.HttpResponse(status=HTTPStatus.FORBIDDEN)
# TODO: declare/validate params with dataclass
_record_identifier = request.GET.get('record_identifier')
Expand Down

0 comments on commit 9ac4cc9

Please sign in to comment.