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

APIv3 endpoint: allow to modify a Project once it's imported #5952

Merged
merged 12 commits into from
Oct 8, 2019

Conversation

humitos
Copy link
Member

@humitos humitos commented Jul 17, 2019

  • allow users to modify existing projects using the API
  • only allow to change fields that are not possible to change via the YAML
  • users should only be able to change projects where they are maintainers

@humitos humitos added Status: blocked Issue is blocked on another issue PR: work in progress Pull request is not ready for full review labels Jul 17, 2019
We are nesting all the endpoints inside `/projects/`. When hitting,
`/project/<slug>` this endpoint does not have any "parent project", so
we need to get the "project_slug" from the view kwargs instead of from
the URL.
Do not allow any other action that's not list, retrieve or
superproject when the detail=True (accessing an object directly)

`/subprojects/` and `/translations/` are considered `list` actions
with detail=True views.
@humitos humitos removed PR: work in progress Pull request is not ready for full review Status: blocked Issue is blocked on another issue labels Sep 10, 2019
@humitos humitos requested a review from a team September 10, 2019 16:50
@humitos
Copy link
Member Author

humitos commented Sep 10, 2019

This PR should be ready to review and all the permissions should be fixed and working as we need.

Copy link
Member

@ericholscher ericholscher left a comment

Choose a reason for hiding this comment

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

This seems like a good change, but I don't fully understand it -- where is the logic that actually makes it so that PATCH works now? Is it the overridden update method? Is it the change to the serializer?

docs/api/v3.rst Outdated Show resolved Hide resolved
"default_version": "v0.27.0"
}

:statuscode 204: Updated successfully
Copy link
Member

Choose a reason for hiding this comment

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

I assume it will also raise an error in some cases?

Copy link
Member Author

@humitos humitos Oct 1, 2019

Choose a reason for hiding this comment

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

On the "Ship APIv3" PR I was thinking to remove all the redundant docs or un-useful list of fields: avoid things like slug: the slug of the Project and just document that ones that are useful.

I applied the same concept for status codes, mentioning only the important ones (based on David's comment as well: #4863 (comment))

I did a commit for this in that PR: f7e168f

What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Seems reasonable 👍

@@ -92,3 +100,20 @@ def get_queryset(self):

# List view are only allowed if user is owner of parent project
return self.listing_objects(queryset, self.request.user)


class UpdatePartialUpdateMixin:
Copy link
Member

Choose a reason for hiding this comment

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

This is a super confusing name. Why does it have Update in the name twice?

Copy link
Member Author

Choose a reason for hiding this comment

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

I should probably rename this to UpdateMixin only. This class makes PUT to return 204 on success as PATCH.

if view.detail:
# detail view is only allowed on list/retrieve actions (not
# ``update`` or ``partial_update``)
if view.detail and view.action in ('list', 'retrieve', 'superproject'):
Copy link
Member

Choose a reason for hiding this comment

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

These feel like they should be constants? What is a superproject? It still feels weird that it is a method name to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

superproject is an action name, defined by the class method under ProjectViewSet. We should apply the same permissions restrictions than for a detail action (since it only returns one superproject if exists).

list and retrieve are DRF standard action names (same as update or partial_update).

We already talked about this at #5857 (comment)

(I'm adding this comment as a code comment)


"""Serializer used to modify a Project once imported."""

repository = RepositorySerializer(source='*')
Copy link
Member

Choose a reason for hiding this comment

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

What is source='*'? It should likely have a comment.

Copy link
Member Author

Choose a reason for hiding this comment

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

* it's standard for DRF but has a special meaning. It means that the whole object will be passed to the RepositorySerializer, not just a specific field of it.

(see docs https://www.django-rest-framework.org/api-guide/fields/#source)

@@ -271,7 +276,8 @@ class TranslationRelationshipViewSet(APIv3Settings, NestedViewSetMixin,
# of ``ProjectQuerySetMixin`` to make calling ``super().get_queryset()`` work
# properly and filter nested dependencies
class VersionsViewSet(APIv3Settings, NestedViewSetMixin, ProjectQuerySetMixin,
FlexFieldsMixin, UpdateModelMixin, ReadOnlyModelViewSet):
FlexFieldsMixin, UpdatePartialUpdateMixin,
UpdateModelMixin, ReadOnlyModelViewSet):
Copy link
Member

Choose a reason for hiding this comment

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

Does this also allow us to PATCH to Versions?

Copy link
Member Author

@humitos humitos Oct 1, 2019

Choose a reason for hiding this comment

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

Yes. It makes the PUT and PATCH to behave in the same way (because of UpdatePartialUpdateMixin: returns 204 on both verbs).

Copy link
Member Author

Choose a reason for hiding this comment

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

It was already working like that, but I moved the update method to a Mixin since it's shared with another class now.

@humitos
Copy link
Member Author

humitos commented Oct 1, 2019

where is the logic that actually makes it so that PATCH works now?Is it the overridden update method?

Yes.

Basically, this is the line that allows the PATCH/PUT: https://github.com/readthedocs/readthedocs.org/pull/5952/files#diff-e7d0914abe4a0641d49078f90f75e695R77

UpdateModelMixin defines the update method (PUT) and partial_update (PATCH) and makes DRF to "listen" to these verbs as well. The rest of the PR are permission handling, refactor, tests and docs.

…adthedocs/readthedocs.org into humitos/apiv3/project-update-endpoint
Copy link
Member

@ericholscher ericholscher left a comment

Choose a reason for hiding this comment

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

Seems good to me 👍

@humitos humitos merged commit 7fcdf5c into master Oct 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants