Skip to content

Commit

Permalink
serializer: add external_pids if visible
Browse files Browse the repository at this point in the history
* ADD permission checking when an individual record
  or deposit is retrieved to add the external_pids field.

Signed-off-by: Dinos Kousidis <[email protected]>
  • Loading branch information
Dinos Kousidis committed Feb 2, 2018
1 parent cebb8c8 commit ea41b50
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 11 deletions.
12 changes: 12 additions & 0 deletions b2share/modules/deposit/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,18 @@ def copy_data_from_previous(previous_record):
return copied_data


def generate_external_pids(record):
"""Generate the list of external files of a record sorted by key."""
external_pids = []
current_file_keys = [f for f in record.files if
f.obj.file.storage_class == 'B']
current_file_keys.sort(key=lambda f: f.obj.key)
for f in current_file_keys:
external_pids.append({'key': f.obj.key,
'ePIC_PID': f.obj.file.uri})
return external_pids


copy_data_from_previous.extra_removed_fields = [
'publication_state', 'publication_date', '$schema'
]
5 changes: 4 additions & 1 deletion b2share/modules/deposit/fetchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
from .providers import DepositUUIDProvider


FetchedPID = namedtuple('FetchedPID', ['provider', 'pid_type', 'pid_value'])
FetchedPID = namedtuple('FetchedPID', ['provider', 'object_uuid',
'pid_type', 'pid_value'])


def b2share_deposit_uuid_fetcher(record_uuid, data):
"""Fetch a deposit's identifiers."""
return FetchedPID(
provider=DepositUUIDProvider,
object_uuid=record_uuid,
pid_type=DepositUUIDProvider.pid_type,
pid_value=str(data['_deposit']['id']),
)
12 changes: 8 additions & 4 deletions b2share/modules/records/fetchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,29 @@

from .providers import RecordUUIDProvider

FetchedPID = namedtuple('FetchedPID', ['provider', 'pid_type', 'pid_value'])

from invenio_records_rest.views import Blueprint
FetchedPID = namedtuple('FetchedPID', ['provider', 'object_uuid',
'pid_type', 'pid_value'])


def b2share_record_uuid_fetcher(record_uuid, data):
"""Fetch a record's identifiers."""
return FetchedPID(
provider=RecordUUIDProvider,
object_uuid=record_uuid,
pid_type=RecordUUIDProvider.pid_type,
pid_value=str(next(pid['value'] for pid in data['_pid']
if pid['type'] == RecordUUIDProvider.pid_type)),
)


def b2share_parent_pid_fetcher(record_uuid, data):
"""Fetch record's parent version persistent identifier."""
return FetchedPID(
provider=RecordUUIDProvider,
# The record_uuid is not relevant for the parent pids
# but it is added in the signature for consistency.
object_uuid=None,
pid_type=RecordUUIDProvider.pid_type,
pid_value=next(pid['value'] for pid in data['_pid']
if pid['type'] == RecordUUIDProvider.parent_pid_type)
if pid['type'] == RecordUUIDProvider.parent_pid_type)
)
2 changes: 1 addition & 1 deletion b2share/modules/records/indexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def indexer_receiver(sender, json=None, record=None, index=None,
if 'external_pids' in json['_deposit']:
# Keep the 'external_pids' if the record is a draft (deposit) or
# if the files are public.
if (is_deposit(record.model) or allow_public_file_metadata(json)):
if (not is_deposit(record.model) and allow_public_file_metadata(json)):
json['external_pids'] = json['_deposit']['external_pids']
del json['_deposit']['external_pids']
if not index.startswith('records'):
Expand Down
37 changes: 32 additions & 5 deletions b2share/modules/records/serializers/schemas/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@

"""B2Share Records JSON schemas used for serialization."""

from flask import g
from marshmallow import Schema, fields, pre_dump
from b2share.modules.access.policies import allow_public_file_metadata
from b2share.modules.deposit.api import generate_external_pids
from b2share.modules.files.permissions import files_permission_factory
from b2share.modules.records.utils import is_deposit
from invenio_records_files.models import Bucket


DOI_URL_PREFIX = 'http://doi.org/'
Expand All @@ -43,19 +48,41 @@ class DraftSchemaJSONV1(Schema):
@pre_dump
def filter_internal(self, data):
"""Remove internal fields from the record metadata."""
external_pids = []
bucket = None
record = None
if hasattr(g, 'record'):
record = g.record
if record.files:
bucket = Bucket.query.filter_by(
id=str(record.files.bucket)).first()
if is_deposit(record.model):
external_pids = generate_external_pids(record)
# if it is a published record don't generate external pids
# as they are immutable and stored in _deposit
else:
external_pids = record.model.json[
'_deposit'].get('external_pids')

if '_deposit' in data['metadata']:
if 'external_pids' in data['metadata']['_deposit']:
data['metadata']['external_pids'] = \
data['metadata']['_deposit']['external_pids']
data['metadata']['owners'] = data['metadata']['_deposit']['owners']
# Add the external_pids only if the
# user is allowed to read the bucket
if external_pids and record and bucket:
if (files_permission_factory(bucket, 'bucket-read').can() or
allow_public_file_metadata(record)):
data['metadata']['external_pids'] = external_pids
del data['metadata']['_deposit']
if '_files' in data['metadata']:
if allow_public_file_metadata(data['metadata']):
# Also add the files field only if the user is allowed
if (bucket and files_permission_factory(
bucket, 'bucket-read').can()) or \
allow_public_file_metadata(data['metadata']):
data['files'] = data['metadata']['_files']
for _file in data['files']:
if 'external_pids' in data['metadata'] and \
any(d['key'] == _file['key']
for d in data['metadata']['external_pids']):
for d in external_pids):
_file['b2safe'] = True
del data['metadata']['_files']
if '_pid' in data['metadata']:
Expand Down

0 comments on commit ea41b50

Please sign in to comment.