Skip to content
This repository has been archived by the owner on Sep 16, 2022. It is now read-only.

Commit

Permalink
Cscfairmeta 642 draft field validation (#638)
Browse files Browse the repository at this point in the history
* CSCFAIRMETA-642: [FIX] bug allowed new version from draft dataset
* CSCFAIRMETA-642: [FIX] bug allowed user metadata adds via normal update
- V2 api should only allow adding files and user metadata of those files
   via separate rpc api and not by updating the dataset with PUT or
   PATCH
* CSCFAIRMETA-642: [FIX] crash when creating dataset without catalog
* CSCFAIRMETA-642: [FIX] bug where v2 fields were visible in v1 model
* CSCFAIRMETA-642: [ADD] more permissive validation for drafts
- New JSON schema for draft datasets which requires only title in
  research_dataset in addition to metadata_provider_org and
  metadata_provider_user.
- New draft data catalog that can be used only for draft datasets.
  This can be used in case where the file origin is not yet determined.
* CSCFAIRMETA-642: [ADD] v2 api for datacatalogs
- V2 datacatalogs allow different schemas for v1 and v2 apis.
  No need to save the schema in both v1/schemas for datacatalogs
  and v2 for datasets.
* CSCFAIRMETA-642: [ADD] documentation of the new data catalog
* CSCFAIRMETA-642: [ADD] catalog permissions to initialdata

Co-authored-by: Katri Tegel <[email protected]>
Co-authored-by: Evgenia Lyjina <[email protected]>
Co-authored-by: genie9 <[email protected]>
  • Loading branch information
4 people authored Nov 5, 2020
1 parent 3d3bc2d commit 13a4a77
Show file tree
Hide file tree
Showing 23 changed files with 1,991 additions and 43 deletions.
13 changes: 7 additions & 6 deletions docs/v2/source/datasets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ The official Fairdata data catalogs with end user write access are:
Other data catalogs where End Users can directly store dataset metadata:


+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+
| Catalog | Purpose | Identifier |
+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+
| Legacy | Store legacy datasets that are published elsewhere. Published datasets may not have all of the required metadata to qualify as Fairdata-dataset. Identifiers are not generated by Metax: User has to provide any identifiers. | urn:nbn:fi:att:data-catalog-legacy |
+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+

+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+
| Catalog | Purpose | Identifier |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+
| Legacy | Store legacy datasets that are published elsewhere. Published datasets may not have all of the required metadata to qualify as Fairdata-dataset. Identifiers are not generated by Metax: User has to provide any identifiers. | urn:nbn:fi:att:data-catalog-legacy |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+
| Draft | Store datasets which are in draft state and data catalog is not yet decided. This catalog is used as a default catalog when creating datasets. Note you must change catalog to one from above before file addition or publication. | urn:nbn:fi:att:data-catalog-dft |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------+



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from django.conf import settings as django_settings
from rest_framework.serializers import ValidationError

from metax_api.exceptions import Http403
from metax_api.exceptions import Http400, Http403
from metax_api.models import CatalogRecord, DataCatalog, Directory, Contract, Common, File
from metax_api.services import (
CatalogRecordService as CRS,
Expand Down Expand Up @@ -51,7 +51,7 @@

END_USER_ALLOWED_DATA_CATALOGS = django_settings.END_USER_ALLOWED_DATA_CATALOGS
LEGACY_CATALOGS = django_settings.LEGACY_CATALOGS

DFT_CATALOG = django_settings.DFT_DATA_CATALOG_IDENTIFIER

class CatalogRecordSerializer(CommonSerializer):

Expand Down Expand Up @@ -145,6 +145,9 @@ def is_valid(self, raise_exception=False):
# in the database, and what the data catalog is being changed to.
self._validate_research_dataset_uniqueness(self.instance.research_dataset)

# updating data catalog of published dataset to draft data catalog is restricted
self._validate_draft_data_catalog()

# executes other validation related code, such as validate_research_dataset()
super(CatalogRecordSerializer, self).is_valid(raise_exception=raise_exception)

Expand All @@ -164,6 +167,10 @@ def update(self, instance, validated_data):
return super(CatalogRecordSerializer, self).update(instance, validated_data)

def create(self, validated_data):
if 'V2' not in self.__class__.__name__ and \
validated_data['data_catalog'].catalog_json['identifier'] == DFT_CATALOG:
raise Http400({ 'detail': [ 'Draft catalog cannot be used in V1 API' ]})

if self._migration_override_requested():

# any custom stuff before create that might be necessary for migration purposes
Expand Down Expand Up @@ -390,8 +397,14 @@ def _populate_file_titles(self, ds):
files_from_db.pop(i)
break

def validate_research_dataset(self, value):
def _validate_draft_data_catalog(self):
# catalog object is not yet included to initial_data so have to fetch it
dc_pid = DataCatalog.objects.get(pk=self.initial_data['data_catalog']).catalog_json['identifier']

if dc_pid == DFT_CATALOG and (self.instance.is_published() or self.instance.draft_of):
raise ValidationError({ 'detail': ['Catalog cannot be changed back to draft'] })

def validate_research_dataset(self, value):
self._populate_file_and_dir_titles(value)

self.validate_json_schema(value)
Expand Down Expand Up @@ -422,7 +435,7 @@ def validate_json_schema(self, value):

if self._operation_is_create:
if not value.get('preferred_identifier', None):
if DataCatalogService.is_harvested(self.initial_data['data_catalog']):
if DataCatalogService.is_harvested(self.initial_data.get('data_catalog')):
raise ValidationError({ 'preferred_identifier':
['harvested catalog record must have preferred identifier']})

Expand Down
4 changes: 2 additions & 2 deletions src/metax_api/api/rest/v2/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
from metax_api.api.rest.base.views import (
ApiErrorViewSet,
ContractViewSet,
DataCatalogViewSet,
DirectoryViewSet,
FileStorageViewSet,
FileViewSet,
SchemaViewSet
)
from .views import (
DataCatalogViewSet,
DatasetViewSet,
)

Expand Down Expand Up @@ -92,7 +92,6 @@ def __init__(self, *args, **kwargs):
router_v1 = CustomRouter(trailing_slash=False)
router_v1.register(r'apierrors/?', ApiErrorViewSet)
router_v1.register(r'contracts/?', ContractViewSet)
router_v1.register(r'datacatalogs/?', DataCatalogViewSet)
router_v1.register(r'directories/?', DirectoryViewSet)
router_v1.register(r'files/?', FileViewSet)
router_v1.register(r'filestorages/?', FileStorageViewSet)
Expand All @@ -102,6 +101,7 @@ def __init__(self, *args, **kwargs):

router_v2 = CustomRouterV2(trailing_slash=False)
router_v2.register(r'datasets/?', DatasetViewSet)
router_v2.register(r'datacatalogs/?', DataCatalogViewSet)
router_v2.register(
r'datasets/(?P<identifier>.+)/metadata_versions/(?P<metadata_version_identifier>.+)/?',
DatasetViewSet
Expand Down
Loading

0 comments on commit 13a4a77

Please sign in to comment.