Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
47 changes: 41 additions & 6 deletions api/preprints/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ class PreprintSerializer(TaxonomizableSerializerMixin, MetricsSerializerMixin, J
related_view='preprints:preprint-versions',
related_view_kwargs={'preprint_id': '<_id>'},
read_only=True,
help_text=(
'Relationship to all versions of this preprint. '
'Related URL: /v2/preprints/{preprint_id}/versions/ (GET to list, POST to create a new version).'
),
)

citation = NoneIfWithdrawal(
Expand Down Expand Up @@ -190,6 +194,7 @@ class PreprintSerializer(TaxonomizableSerializerMixin, MetricsSerializerMixin, J
related_view='providers:preprint-providers:preprint-provider-detail',
related_view_kwargs={'provider_id': '<provider._id>'},
read_only=False,
help_text='Relationship to the preprint provider. Required on creation.',
)

files = NoneIfWithdrawal(
Expand Down Expand Up @@ -500,11 +505,30 @@ class Meta:


class PreprintCreateSerializer(PreprintSerializer):
"""Serializer for creating a new preprint.

Notes
- Overrides `PreprintSerializer` to allow nullable `id` and implements `create`.
- Requires `provider` and `title`.
- Optional `description`.
- Optional privileged fields: `manual_guid`, `manual_doi` (gated by MANUAL_DOI_AND_GUID flag).
"""
# Overrides PreprintSerializer to make id nullable, adds `create`
# TODO: add better Docstrings
id = IDField(source='_id', required=False, allow_null=True)
manual_guid = ser.CharField(write_only=True, required=False, allow_null=True, allow_blank=True)
manual_doi = ser.CharField(write_only=True, required=False, allow_null=True, allow_blank=True)
manual_guid = ser.CharField(
write_only=True,
required=False,
allow_null=True,
allow_blank=True,
help_text='Privileged: manually assign a GUID on creation (feature-flag gated).',
)
manual_doi = ser.CharField(
write_only=True,
required=False,
allow_null=True,
allow_blank=True,
help_text='Privileged: manually assign an article DOI on creation (feature-flag gated).',
)

def create(self, validated_data):

Expand All @@ -527,11 +551,22 @@ def create(self, validated_data):


class PreprintCreateVersionSerializer(PreprintSerializer):
# Overrides PreprintSerializer to make title nullable and customize version creation
# TODO: add better Docstrings
"""Serializer for creating a new version of an existing preprint.

Notes
- Overrides `PreprintSerializer` to make `title` optional during version creation.
- Requires `create_from_guid` referencing the source preprint GUID (base or versioned).
- Only users with ADMIN on the source preprint may create a new version.
"""
id = IDField(source='_id', required=False, allow_null=True)
title = ser.CharField(required=False)
create_from_guid = ser.CharField(required=True, write_only=True)
create_from_guid = ser.CharField(
required=True,
write_only=True,
help_text=(
'GUID of the source preprint to version (accepts base GUID or versioned GUID, e.g., abc12 or abc12_v3).'
),
)

def create(self, validated_data):
create_from_guid = validated_data.pop('create_from_guid', None)
Expand Down
10 changes: 10 additions & 0 deletions api/preprints/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,13 @@ def get_annotated_queryset_with_metrics(self, queryset, metric_class, metric_nam


class PreprintVersionsList(PreprintMetricsViewMixin, JSONAPIBaseView, generics.ListCreateAPIView, PreprintFilterMixin):
"""List existing versions of a preprint or create a new version.

GET: Returns a collection of preprint resources representing all versions of the given preprint.
POST: Creates a new version from the current preprint. Requires ADMIN on the source preprint.

Related to the `versions` relationship on the Preprint resource.
"""
# These permissions are not checked for the list of preprints, permissions handled by the query
permission_classes = (
drf_permissions.IsAuthenticatedOrReadOnly,
Expand Down Expand Up @@ -282,6 +289,9 @@ def create(self, request, *args, **kwargs):

class PreprintDetail(PreprintOldVersionsImmutableMixin, PreprintMetricsViewMixin, JSONAPIBaseView, generics.RetrieveUpdateDestroyAPIView, PreprintMixin, WaterButlerMixin):
"""The documentation for this endpoint can be found [here](https://developer.osf.io/#operation/preprints_read).

Note: The resource now exposes a `versions` relationship pointing to
`/v2/preprints/{preprint_id}/versions/` for listing or creating versions.
"""
permission_classes = (
drf_permissions.IsAuthenticatedOrReadOnly,
Expand Down
Loading