Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Second DRS Fix #297

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0f83a11
selective access types and defaulting
willronchetti Aug 25, 2023
a7bcaae
small changes, take schema filename
willronchetti Aug 28, 2023
54eb15a
continue drs
willronchetti Jun 6, 2024
67f883c
add fix for drs json renderer
willronchetti Jun 6, 2024
0d2f3ce
add back cl
willronchetti Jun 6, 2024
81824b5
add test
willronchetti Jun 7, 2024
2d128d1
fix static checks
willronchetti Jun 7, 2024
54253c9
Merge branch 'master' into drs
willronchetti Jun 7, 2024
0ce2041
remove auth check on route
willronchetti Jun 7, 2024
feb13fe
remove unused import
willronchetti Jun 7, 2024
1738c10
Merge branch 'master' into drs
willronchetti Jun 26, 2024
dc0a67a
remove drs_id validation
willronchetti Jun 26, 2024
a406fc9
Merge branch 'master' into drs
willronchetti Jun 26, 2024
1b0e6d5
refactor unique key usage for base compatibility with drs
willronchetti Jun 27, 2024
bd53c1c
Merge branch 'drs' of https://github.com/4dn-dcic/snovault into drs
willronchetti Jun 27, 2024
d190218
push beta
willronchetti Jun 27, 2024
8ecbe8e
merge master
willronchetti Aug 14, 2024
b3dbb8d
repair drs for 1.3
willronchetti Aug 16, 2024
814e2e0
version
willronchetti Aug 16, 2024
b83041f
always reference drs id (accession) in uri
willronchetti Aug 27, 2024
79f0606
allow object_id for options
willronchetti Aug 28, 2024
d8036a6
fix options path
willronchetti Aug 28, 2024
03092f1
do not check content type for options since unused
willronchetti Aug 29, 2024
d4c8d96
merged in master
dmichaels-harvard Oct 10, 2024
4420556
lint fix
dmichaels-harvard Oct 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ snovault
Change Log
----------


11.22.0
=======

* Update ``drs`` validation to remove drs_uri


11.22.0
=======

* 2024-09-03/dmichaels
- Fix in snovault/tests/elasticsearch_fixture.py (use only for local/dev deploy) for
strange (new as of 2024-09-02) behavior where it was hanging on startup during
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dcicsnovault"
version = "11.22.0"
version = "11.22.0.1b1" # TODO: To become 11.23.0
description = "Storage support for 4DN Data Portals."
authors = ["4DN-DCIC Team <[email protected]>"]
license = "MIT"
Expand Down
9 changes: 6 additions & 3 deletions snovault/drs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pyramid.view import view_config
from pyramid.exceptions import HTTPNotFound
from pyramid.response import Response
from .util import debug_log


Expand All @@ -12,7 +13,6 @@
REQUIRED_FIELDS = [
'id',
'created_time',
'drs_id',
'self_uri',
'size',
'checksums'
Expand Down Expand Up @@ -54,7 +54,8 @@ def get_and_format_drs_object(request, object_uri):
except Exception:
raise HTTPNotFound('You accessed a DRS object_uri that either does not exist'
' or you do not have access to it.')
drs_object['self_uri'] = f'drs://{request.host}{request.path}'
uri = drs_object['id']
drs_object['self_uri'] = f'drs://{request.host}/{uri}'
return drs_object


Expand Down Expand Up @@ -83,13 +84,15 @@ def get_drs_url(request, object_uri):


@view_config(
route_name='drs_objects', request_method='GET'
route_name='drs_objects', request_method=['GET', 'OPTIONS']
)
@debug_log
def drs_objects(context, request):
""" Implements DRS GET as specified by the API description
https://ga4gh.github.io/data-repository-service-schemas/preview/release/drs-1.0.0/docs/#_getobject
"""
if request.method == 'OPTIONS':
return Response(status_code=204)
drs_object_uri = '/' + request.matchdict['object_id']
formatted_drs_object = get_and_format_drs_object(request, drs_object_uri)
try:
Expand Down
2 changes: 1 addition & 1 deletion snovault/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def validate_request_tween(request):
if 'X_REQUEST_METHOD' in environ:
environ['REQUEST_METHOD'] = environ['X_REQUEST_METHOD']

if request.method in ('GET', 'HEAD'):
if request.method in ('GET', 'HEAD', 'OPTIONS'):
# If GET request, don't need to check `request.content_type`
# Includes page text/html requests.
return handler(request)
Expand Down
11 changes: 10 additions & 1 deletion snovault/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,10 +528,19 @@ def rev_link_atids(self, request, rev_name):
self.get_filtered_rev_links(request, rev_name)]

def unique_keys(self, properties):
return {
""" This function used to only resolve keys from schema, it has been
updated to handle both accession and alternate_accession
"""
keys = {
name: [v for prop in props for v in ensurelist(properties.get(prop, ()))]
for name, props in self.type_info.schema_keys.items()
}
if 'accession' not in self.schema['properties']:
return keys
keys.setdefault('accession', []).extend(properties.get('alternate_accessions', []))
if properties.get('status') != 'replaced' and 'accession' in properties:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the and 'accession' in properties clause needed - if you get here won't it definitely be there even if only an empty list from the line above?

And will this not be problematic for 'replaced' files as now this file that has the old accession as an alternative_accession will have a unique key conflict with the replaced file which is still accessible and in the db?

keys['accession'].append(properties['accession'])
return keys

def add_accession_to_title(self, title):
if self.properties.get('accession') is not None:
Expand Down
6 changes: 5 additions & 1 deletion snovault/test_schemas/TestingDownload.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"mixinProperties": [
{ "$ref": "mixins.json#/status" },
{ "$ref": "mixins.json#/submitted" }
{ "$ref": "mixins.json#/submitted" },
{ "$ref": "mixins.json#/accession" }
],
"properties": {
"attachment": {
Expand All @@ -25,6 +26,9 @@
"enum": ["image/png"]
}
}
},
"accession": {
"accessionType": "TD"
}
}
}
30 changes: 29 additions & 1 deletion snovault/test_schemas/mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,33 @@
"pattern": "^[a-zA-Z0-9_\\-][a-zA-Z0-9_\\-\\s]+[a-zA-Z0-9_\\-]$"
}
}
}
},
"accession": {
"accession": {
"title": "Accession",
"description": "A unique identifier to be used to reference the object.",
"internal_comment": "Only admins are allowed to set or update this value.",
"exclude_from": [
"FFedit-create"
],
"type": "string",
"format": "accession",
"permission": "restricted_fields",
"serverDefault": "accession"
},
"alternate_accessions": {
"title": "Alternate Accessions",
"description": "Accessions previously assigned to objects that have been merged with this object.",
"type": "array",
"lookup": 1000,
"internal_comment": "Only admins are allowed to set or update this value.",
"items": {
"title": "Alternate Accession",
"description": "An accession previously assigned to an object that has been merged with this object.",
"type": "string",
"permission": "restricted_fields",
"format": "accession"
}
}
}
}
10 changes: 7 additions & 3 deletions snovault/tests/test_drs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ class TestDRSAPI:
def test_drs_get_object(self, testapp, testing_download): # noQA fixture
""" Tests basic structure about a drs object """
res = testapp.get(testing_download)
drs_object_uri = res.json['uuid']
drs_object_uri = res.json['accession']
drs_object_uuid = res.json['uuid']
testapp.options(f'/ga4gh/drs/v1/objects/{drs_object_uri}',
headers={'Content-Type': 'application/json'}, status=204)
drs_object_1 = testapp.get(f'/ga4gh/drs/v1/objects/{drs_object_uri}').json
for key in REQUIRED_FIELDS:
assert key in drs_object_1
assert drs_object_1['self_uri'] == f'drs://localhost:80/ga4gh/drs/v1/objects/{drs_object_uri}'
assert drs_object_1['self_uri'] == f'drs://localhost:80/{drs_object_uri}'
assert (drs_object_1['access_methods'][0]['access_url']['url']
== f'{self.BASE_URL}{drs_object_uri}/@@download')
== f'{self.BASE_URL}{drs_object_uuid}/@@download')
assert (drs_object_1['access_methods'][0]['access_id'] == 'http')

# failure cases
testapp.get(f'/ga4gh/drs/v1/objects/not_a_uri', status=404)
Expand Down
19 changes: 6 additions & 13 deletions snovault/tests/testing_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,6 @@ def __ac_local_roles__(self):
# roles[viewing_group_members] = 'role.viewing_group_member'
return roles

def unique_keys(self, properties):
keys = super(Item, self).unique_keys(properties)
if 'accession' not in self.schema['properties']:
return keys
keys.setdefault('accession', []).extend(properties.get('alternate_accessions', []))
if properties.get('status') != 'replaced' and 'accession' in properties:
keys['accession'].append(properties['accession'])
return keys

@calculated_property(schema={
"title": "Display Title",
"description": "A calculated title for every object in 4DN",
Expand Down Expand Up @@ -418,6 +409,7 @@ class NestedObjectLinkTarget(Item):

@collection(
'testing-downloads',
unique_key='accession',
properties={
'title': 'Test download collection',
'description': 'Testing. Testing. 1, 2, 3.',
Expand All @@ -436,11 +428,11 @@ def drs(context, request):
downstream API (see drs.py).
"""
rendered_object = request.embed(str(context.uuid), '@@object', as_user=True)
accession = rendered_object['accession']
drs_object = {
'id': rendered_object['@id'],
'id': accession,
'created_time': rendered_object['date_created'],
'drs_id': rendered_object['uuid'],
'self_uri': f'drs://{request.host}{request.path}',
'self_uri': f'drs://{request.host}/{accession}',
'size': 0,
'checksums': [
{
Expand All @@ -453,7 +445,8 @@ def drs(context, request):
'access_url': {
'url': f'http://{request.host}/{context.uuid}/@@download'
},
'type': 'http'
'type': 'http',
'access_id': 'http'
},
]
}
Expand Down
Loading