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

Make APIv3 permission classes modular #5858

Closed
wants to merge 12 commits into from

Conversation

humitos
Copy link
Member

@humitos humitos commented Jun 27, 2019

This PR just split our own permission class that handles all the cases into tree where each of them are in charge of an specific thing:

  • IsAuthenticated (from DRF): checks that the user is authenticated
  • PublicDetailPrivateListing: do not grant permissions if the user doing a listing over an object he doesn't is part of
  • ListCreateProject: allow listing at /api/v3/projects/ to list user's projects and also to create a project at the same endpoint by POST

Depends on #5857

@humitos humitos requested a review from a team June 27, 2019 12:06
@humitos humitos changed the base branch from master to humitos/apiv3-import-project June 27, 2019 12:06
@humitos humitos force-pushed the humitos/apiv3-import-project branch from d9f08a9 to 6302256 Compare June 27, 2019 12:07
@humitos humitos changed the base branch from humitos/apiv3-import-project to master June 27, 2019 12:08
@humitos humitos changed the base branch from master to humitos/apiv3-import-project June 27, 2019 12:08
@humitos humitos force-pushed the humitos/apiv3-modular-permissions branch from ed42f57 to 064889a Compare June 27, 2019 12:09
return True

project = view._get_parent_project()
if view.has_admin_permission(request.user, project):
Copy link
Contributor

Choose a reason for hiding this comment

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

has_admin_permission seems poorly named to me. It isn't immediately clear what it means. I realize it means that the user is a maintainer on the project but maybe it should be more explicit. How about is_project_maintainer or something like that. It does seem to mirror the method name on the ProjectQuerySet but it is much more clear what that method does in context (Project.objects.for_admin_user is fairly clear although could be better while view.has_admin_permission is not).

Copy link
Member Author

Choose a reason for hiding this comment

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

is_project_maintainer is a good name, but I'm not sure it does fit with corporate (or under an organizational structure) --where only read access is granted.

Even if it doesn't fit 100%, it's still a better name 😄

@@ -126,6 +130,20 @@ class ProjectsViewSet(APIv3Settings, NestedViewSetMixin, ProjectQuerySetMixin,
'active_versions.last_build.config',
]

def get_serializer_class(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

I see what you're doing here, but stylistically, I think it would be better to get rid of this method and make create() explicitly use a different serializer on incoming POST data.

In all cases, you want the JSON output to use ProjectSerializer. However, when there's user input like a user creating a project they aren't going to send every last field as some of them are automatic or have reasonable defaults so a different serializer may make sense. Since you're already overriding the output serializer in create(), I'd rather you just instead overrode the input serializer and used the default output serializer.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, it looks like this is necessary due to how CreateModelMixin works.

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 changed this. Although, since this PR is based on the "Import Project" one, some things changed there and I will re-check this once that one gets merged.

@@ -50,7 +55,7 @@ class APIv3Settings:
# Using only ``TokenAuthentication`` for now, so we can give access to
# specific carefully selected users only
authentication_classes = (TokenAuthentication,)
permission_classes = (PublicDetailPrivateListing,)
permission_classes = (IsAuthenticated & (ListCreateProject | PublicDetailPrivateListing),)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is starting to make me nervous and I don't really understand how ListCreateProject is that different from PublicDetailPrivateListing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ouch! I thought that splitting these permissions in different classes would be easier to understand them.

Before this PR, everything was under a black box called PublicDetailPrivateListing. I decided to split it because it did more than what it name says.

My idea is:

  • IsAuthenticated is the first required condition,

then, the user has access to

  • ListCreateProject: list OR create at the /projects/ endpoint (which is kind special)

NOTE: ListCreateProject may be moved to ProjectsViewSet since it's the only place where it's needed

OR

  • PublicDetailPrivateListing: detail on any object or list of "private" (personal) objects.

Let me know if this helps to clarify or if you have another idea how to make it better.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think overall, I'd feel a lot better if these special cases were not on the base class that every API endpoint extends from. The project endpoint is special (although with all the extra complexity, I'm starting to doubt that it should be) and these changes should be localized to there!

@humitos humitos force-pushed the humitos/apiv3-import-project branch from c44f039 to b29b3b5 Compare July 9, 2019 08:51
@humitos humitos requested a review from davidfischer July 9, 2019 08:56
@humitos humitos requested a review from a team July 16, 2019 09:50
@stsewd
Copy link
Member

stsewd commented Jul 16, 2019

@humitos there are merge conflicts to be resolved before review

@humitos humitos changed the base branch from humitos/apiv3-import-project to master July 23, 2019 11:28
@humitos
Copy link
Member Author

humitos commented Jul 23, 2019

@stsewd I fixed the conflicts and change the base to be master. Let me know!

@humitos
Copy link
Member Author

humitos commented Jul 30, 2019

@davidfischer I'd appreciate another round of review here.

@@ -153,11 +153,6 @@ def test_import_project(self):
response_json['created'] = '2019-04-29T10:00:00Z'
response_json['modified'] = '2019-04-29T12:00:00Z'

self.assertDictEqual(
Copy link
Contributor

Choose a reason for hiding this comment

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

I we remove this, the previous couple lines don't do anything, right?

@@ -50,7 +55,7 @@ class APIv3Settings:
# Using only ``TokenAuthentication`` for now, so we can give access to
# specific carefully selected users only
authentication_classes = (TokenAuthentication,)
permission_classes = (PublicDetailPrivateListing,)
permission_classes = (IsAuthenticated & (ListCreateProject | PublicDetailPrivateListing),)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think overall, I'd feel a lot better if these special cases were not on the base class that every API endpoint extends from. The project endpoint is special (although with all the extra complexity, I'm starting to doubt that it should be) and these changes should be localized to there!

@stale
Copy link

stale bot commented Sep 13, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: stale Issue will be considered inactive soon label Sep 13, 2019
@stale stale bot closed this Sep 20, 2019
@dojutsu-user
Copy link
Member

I believe this is still valid.

@dojutsu-user dojutsu-user reopened this Sep 20, 2019
@stale stale bot removed the Status: stale Issue will be considered inactive soon label Sep 20, 2019
@agjohnson agjohnson added the Accepted Accepted issue on our roadmap label Sep 25, 2019
@humitos
Copy link
Member Author

humitos commented Jul 22, 2020

I will need to re-visit this PR after #6489 got merged.

@humitos humitos closed this Jan 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Accepted issue on our roadmap
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants