Skip to content

Commit

Permalink
waffle get_addon code for gravyvalet
Browse files Browse the repository at this point in the history
  • Loading branch information
John Tordoff committed May 13, 2024
1 parent cf4ab0d commit d194c91
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 1 deletion.
34 changes: 34 additions & 0 deletions addons/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,37 @@ def format_last_known_metadata(auth, node, file, error_type):
]
return ''.join(parts)
return msg


class GravyValetAddonAppConfig:
class MockNodeSetting:
def __init__(self, resource, request, legacy_config):
...

class MockUserSetting:
def __init__(self, resource, request, legacy_config):
...

def __init__(self, gravyvalet_data, resource, auth):
self.gravyvalet_data = gravyvalet_data

# TODO: Names in GV must be exact matches?
self.legacy_config = settings.ADDONS_AVAILABLE_DICT[self.gravyvalet_data['data']['attributes']['name']]
self.resource = resource
self.auth = auth
self.FOLDER_SELECTED = self.legacy_config.FOLDER_SELECTED
self.NODE_AUTHORIZED = self.legacy_config.NODE_DEAUTHORIZED
self.NODE_DEAUTHORIZED = self.legacy_config.NODE_DEAUTHORIZED
self.actions = self.legacy_config.actions

@property
def node_settings(self):
return self.MockNodeSetting(self.resource, self.auth, self.legacy_config)

@property
def user_settings(self):
return self.MockUserSetting(self.resource, self.auth, self.legacy_config)

@property
def configured(self):
return self.legacy_config.configured
154 changes: 154 additions & 0 deletions api_tests/providers/test_files_with_gv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import pytest

from osf import features
from api.base.settings.defaults import API_BASE
from api_tests import utils as api_utils
from osf_tests.factories import (
AuthUserFactory,
ProjectFactory,
)
from waffle.testutils import override_flag
from django.shortcuts import reverse


@pytest.mark.django_db
class TestWaffleFilesProviderView:

@pytest.fixture(autouse=True)
def override_flag(self):
with override_flag(features.ENABLE_GV, active=True):
yield

@pytest.fixture()
def user(self):
return AuthUserFactory()

@pytest.fixture()
def provider_gv_id(self):
return 1337

@pytest.fixture()
def node(self, user):
return ProjectFactory(
creator=user,
comment_level='public'
)

@pytest.fixture()
def file(self, user, node):
return api_utils.create_test_file(
node,
user,
create_guid=False
)

@pytest.fixture()
def addon_files_url(self, node, provider_gv_id):
return reverse(
'nodes:node-storage-provider-detail',
kwargs={
'version': 'v2',
'node_id': node._id,
'provider': provider_gv_id
}
)

def test_must_have_auth(self, app, addon_files_url):
res = app.get(
addon_files_url,
expect_errors=True
)
assert res.status_code == 401

def test_must_be_contributor(self, app, addon_files_url):
res = app.get(
addon_files_url,
auth=AuthUserFactory().auth,
expect_errors=True
)
assert res.status_code == 403

def test_get_file_provider(self, app, user, addon_files_url, file, provider_gv_id):
res = app.get(
addon_files_url,
auth=user.auth
)

assert res.status_code == 200
attributes = res.json['data']['attributes']
assert attributes['provider'] == str(provider_gv_id)
assert attributes['name'] == str(provider_gv_id)
assert res.json['data']['id'] == f'{file.target._id}:{str(provider_gv_id)}'


@pytest.mark.django_db
class TestWaffleFilesView:

@pytest.fixture(autouse=True)
def override_flag(self):
with override_flag(features.ENABLE_GV, active=True):
yield

@pytest.fixture()
def user(self):
return AuthUserFactory()

@pytest.fixture()
def provider_gv_id(self):
return 1

@pytest.fixture()
def node(self, user):
return ProjectFactory(
creator=user,
comment_level='public'
)

@pytest.fixture()
def file(self, user, node):
return api_utils.create_test_file(
node,
user,
create_guid=False
)

@pytest.fixture()
def file_url(self, node, provider_gv_id):
return reverse(
'nodes:node-files',
kwargs={
'version': 'v2',
'node_id': node._id,
'provider': str(provider_gv_id) + '/',
'path': 'test_path/'
}
)

def test_must_have_auth(self, app, file_url):
res = app.get(
file_url,
expect_errors=True
)
assert res.status_code == 401

def test_must_be_contributor(self, app, file_url):
res = app.get(
file_url,
auth=AuthUserFactory().auth,
expect_errors=True
)
assert res.status_code == 403

def test_get_file_provider(self, app, user, file_url, file, provider_gv_id):
res = app.get(
file_url,
auth=user.auth
)

assert res.status_code == 200
attributes = res.json['data']['attributes']
assert attributes['provider'] == str(provider_gv_id)
assert attributes['name'] == str(provider_gv_id)
assert res.json['data']['id'] == f'{file.target._id}:{str(provider_gv_id)}'


27 changes: 26 additions & 1 deletion osf/models/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import itertools
import logging
import re
import waffle
import requests
from future.moves.urllib.parse import urljoin
import warnings
from rest_framework import status as http_status
Expand Down Expand Up @@ -54,6 +56,7 @@
from .user import OSFUser
from .validators import validate_title, validate_doi
from framework.auth.core import Auth
from osf import features
from osf.utils.datetime_aware_jsonfield import DateTimeAwareJSONField
from osf.utils.fields import NonNaiveDateTimeField, ensure_str
from osf.utils.requests import get_request_and_user_id, string_type_request_headers
Expand Down Expand Up @@ -83,7 +86,7 @@
from api.caching import settings as cache_settings
from api.caching.utils import storage_usage_cache
from api.share.utils import update_share

from addons.base.utils import GravyValetAddonAppConfig

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -2430,6 +2433,28 @@ def _remove_from_associated_collections(self, auth=None, force=False):
force=True
)

def get_addon(self, name, is_deleted=False):
request, user_id = get_request_and_user_id()

default_addons = ['wiki']
for addon in settings.ADDONS_AVAILABLE:
if 'node' in addon.added_default:
default_addons.append(addon.short_name)

if waffle.flag_is_active(request, features.ENABLE_GV) and name not in ['osfstorage', 'wiki']:
resp = requests.get(
settings.GV_EXTERNAL_STORAGE_ENDPOINT.format(service_id=name),
auth=(request.user.username, request.user.password)
)
data = resp.json()
return GravyValetAddonAppConfig(
data,
self,
auth=(request.user.username, request.user.password)
)
else:
return super().get_addon(name, is_deleted)


class NodeUserObjectPermission(UserObjectPermissionBase):
"""
Expand Down
24 changes: 24 additions & 0 deletions osf/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re
from future.moves.urllib.parse import urljoin, urlencode
import uuid
import waffle
from copy import deepcopy

from flask import Request as FlaskRequest
Expand Down Expand Up @@ -59,6 +60,10 @@
from website.util.metrics import OsfSourceTags
from importlib import import_module
from osf.utils.requests import get_headers_from_request
import requests
from osf.utils.requests import get_request_and_user_id
from osf import features
from addons.base.utils import GravyValetAddonAppConfig

SessionStore = import_module(settings.SESSION_ENGINE).SessionStore

Expand Down Expand Up @@ -1220,6 +1225,25 @@ def create_unregistered(cls, fullname, email=None):

return user

def get_addon(self, name, is_deleted=False, auth=None):
request, user_id = get_request_and_user_id()

default_addons = ['wiki']
for addon in website_settings.ADDONS_AVAILABLE:
if 'user' in addon.added_default:
default_addons.append(addon.short_name)

if waffle.flag_is_active(request, features.ENABLE_GV) and name not in ['osfstorage', 'wiki']:
resp = requests.get(
website_settings.GV_USER_ADDON_ENDPOINT.format(account_id=name),
auth=auth
)
resp.raise_for_status()
data = resp.json()['data']
return GravyValetAddonAppConfig(data, self, auth)
else:
return super().get_addon(name, is_deleted)

def update_guessed_names(self):
"""Updates the CSL name fields inferred from the the full name.
"""
Expand Down
9 changes: 9 additions & 0 deletions website/settings/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -2142,3 +2142,12 @@ def from_node_usage(cls, usage_bytes, private_limit=None, public_limit=None):

WAFFLE_VALUES_YAML = 'osf/features.yaml'
DEFAULT_DRAFT_NODE_TITLE = 'Untitled'
GV_RESOURCE_DOMAIN = 'http://192.168.168.167:8004/v1/resource-references/?filter[resource_uri]={owner_uri}'
GV_USER_DOMAIN = 'http://192.168.168.167:8004/v1/user-references/?filter[user_uri]={owner_uri}'
GV_API_ROOT = 'http://192.168.168.167:8004/v1'
GV_RESOURCE_ENDPOINT = GV_API_ROOT + 'resource-references/?filter[resource_uri]={resource_uri}'
GV_USER_ENDPOINT = GV_API_ROOT + 'user-references/?filter[user_uri]={owner_uri}'
# These two are for `get_addon` vs `get_addons`
GV_USER_ADDON_ENDPOINT = 'http://192.168.168.167:8004/v1/authorized-storage-accounts/{account_id}'
GV_NODE_ADDON_ENDPOINT = 'http://192.168.168.167:8004/v1/configured-storage-addons/{addon_id}'
GV_EXTERNAL_STORAGE_ENDPOINT = 'http://192.168.168.167:8004/v1/external-storage-services/{service_id}'

0 comments on commit d194c91

Please sign in to comment.