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

Hide location action buttons unless user has permission to do the action #1268

Merged
merged 7 commits into from
Apr 3, 2017

Conversation

laura-barluzzi
Copy link
Contributor

Proposed changes in this pull request

Fix bug #1233: only show the location action buttons to users who have permission to do the action.

Screenshot of location view for user without edit/delete permission:
user

Screenshot of location view for user with edit/delete permission:
admin

When should this PR be merged

No dependencies.

Risks

None.

Follow up actions

None.

Checklist (for reviewing)

General

  • Is this PR explained thoroughly? All code changes must be accounted for in the PR description.
  • Is the PR labeled correctly? It should have the migration label if a new migration is added.
  • Is the risk level assessment sufficient? The risks section should contain all risks that might be introduced with the PR and which actions we need to take to mitigate these risks. Possible risks are database migrations, new libraries that need to be installed or changes to deployment scripts.

Functionality

  • Are all requirements met? Compare implemented functionality with the requirements specification.
  • Does the UI work as expected? There should be no Javascript errors in the console; all resources should load. There should be no unexpected errors. Deliberately try to break the feature to find out if there are corner cases that are not handled.

Code

  • Do you fully understand the introduced changes to the code? If not ask for clarification, it might uncover ways to solve a problem in a more elegant and efficient way.
  • Does the PR introduce any inefficient database requests? Use the debug server to check for duplicate requests.
  • Are all necessary strings marked for translation? All strings that are exposed to users via the UI must be marked for translation.

Tests

  • Are there sufficient test cases? Ensure that all components are tested individually; models, forms, and serializers should be tested in isolation even if a test for a view covers these components.
  • If this is a bug fix, are tests for the issue in place There must be a test case for the bug to ensure the issue won’t regress. Make sure that the tests break without the new code to fix the issue.
  • If this is a new feature or a significant change to an existing feature has the manual testing spreadsheet been updated with instructions for manual testing?

Documentation

  • Are changes to the UI documented in the platform docs? If this PR introduces new platform site functionality or changes existing ones, the changes must be documented in the Cadasta Platform Documentation.
  • Are changes to the API documented in the API docs? If this PR introduces new API functionality or changes existing ones, the changes must be documented in the API docs.
  • Are reusable components documented? If this PR introduces components that are relevant to other developers (for instance a mixin for a view or a generic form) they should be documented in the Wiki.

Copy link
Member

@oliverroick oliverroick left a comment

Choose a reason for hiding this comment

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

Hi @laura-barluzzi, some the tests are failing. Please make sure all tests pass before we can proceed with the review.

@laura-barluzzi
Copy link
Contributor Author

Hi @oliverroick, I made some changes and now all the tests run on my machine.

Copy link
Contributor

@clash99 clash99 left a comment

Choose a reason for hiding this comment

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

Hi @laura-barluzzi - thanks for your work on this! It looks good from a ui perspective! Can you just update your branch to be current with the latest master branch?

@laura-barluzzi
Copy link
Contributor Author

Hi @clash99, I've updated it. Let me know if there's something else to do.

Copy link
Member

@oliverroick oliverroick left a comment

Choose a reason for hiding this comment

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

Hi @laura-barluzzi, thank you for your contribution. It looks almost ok, there are two things I would like to ask you to change:

  1. Check the permissions against the correct object (see my comment in the code).
  2. You have only added tests for users who have all permissions. Could you also add tests that render the view with users who don't have permissions and thus should not see the buttons?

Thanks!

@@ -186,6 +186,10 @@ def get_context_data(self, *args, **kwargs):
project = self.get_project()
context['is_allowed_add_location'] = user.has_perm('spatial.create',
project)
context['is_allowed_update_location'] = user.has_perm('spatial.update',
project)
Copy link
Member

Choose a reason for hiding this comment

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

Your checkin the permission against the wrong object here. For spatial.create project is fine, because the user wants to create a spatial unit for the project. For spatial.update and spatial.delete, you need to use the spatial unit instance from the view; the permission needs to be checked against itself and not its project.

@laura-barluzzi
Copy link
Contributor Author

Hi @oliverroick, I changed the logic so that the permission is checked against the location object instead of the project, but I struggle to figure out how to update the tests. Can you please guide me on this? Cheers

@oliverroick
Copy link
Member

Hey @laura-barluzzi,

If you look at this part; this is where permissions are assigned to a user. In a default test the user has these permissions, so the buttons are shown.

You now need to add a test for the case when the buttons are not shown. In that test, you need to:

  1. Create policies that explicitly deny permission to edit and delete the location.
  2. Assign the policies to a users.
  3. Get a rendered response using that user.
  4. And evaluate if the site was rendereded correctly.

You can create policies that deny permissions by copying the clauses that I linked above and add another clause that looks like this:

{
    'effect': 'deny',
    'object': ['spatial/*/*/*'],
    'action': ['spatial.update', 'spatial.delete']
},

Combined with the other policies the user will be able to view all locations but not edit or delete any of them.

If you look at this test case, you'll see an example how to use a specific user with a request (for step 3) and how you can overwrite specific items in the template context for the rendered expected response to make sure the buttons are not rendered (for step 4).

Note: We're using django-skivvy to setup test cases for views. Each test class defines a standard template context for expected response for all the tests (see here for reference). And you can overwrite selected items using render_content.

@laura-barluzzi
Copy link
Contributor Author

Hi @oliverroick, thank you for telling me how to add a new test. Before adding the new tests, I'd like to address something I'm confused about and I was hoping you could help me figure this out.

Currently some of the existing tests fail, e.g. https://travis-ci.org/Cadasta/cadasta-platform/jobs/212860743#L955-L975

Currently all the exiting test template contexts render the edit/delete location buttons e.g. https://github.com/Cadasta/cadasta-platform/pull/1268/files#diff-d2f99481b1c4d834b7e971c17527a28cR590

And by default, the user has all permissions on the spatial object: https://github.com/laura-barluzzi/cadasta-platform/blob/bugfix/%231233/cadasta/spatial/tests/test_views_default.py#L42-L44

So doesn't that mean that the buttons should get rendered and the tests should pass? I'm confused what's going on here. Why the tests are not passing?

@oliverroick
Copy link
Member

@laura-barluzzi

You have only added the permissions check to LocationDetail but not to any of the other views. If you look at the tests that are failing you'll see which of the views you need to change.

It would be a good idea to move the functionality to work out the permissions into a mixin and apply that to all the views that require it. Otherwise you'd be replicating a lot of code.

Good job on writing the tests so thoroughly!

@laura-barluzzi
Copy link
Contributor Author

Hi @oliverroick, I figured out how to make all the tests pass and I pushed this commit. Next I'll add the test for cases without buttons.

@laura-barluzzi
Copy link
Contributor Author

Hi @oliverroick I added the test with the denied edit/delete permission. Let me know what you think and if there's something else to do before merging.

Copy link
Member

@oliverroick oliverroick left a comment

Choose a reason for hiding this comment

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

Hi @laura-barluzzi, you're almost there. There's a small bug in the template that you still need to fix. See the comment in the code

@@ -12,8 +12,12 @@
<h2 class="short"><span>{% trans "Location" %} </span>{{ location.name }}</h2>
<div class="top-btn pull-right">
<!-- Action buttons -->
<a class="btn btn-default btn-action btn-sm" href="{% url 'locations:edit' object.organization.slug object.slug location.id %}" title="{% trans 'Edit location' %}" aria-label="{% trans 'Edit location' %}"><span class="glyphicon glyphicon-pencil"></span></a>
<a class="btn btn-default btn-action btn-sm" href="{% url 'locations:delete' object.organization.slug object.slug location.id %}" title="{% trans 'Delete location' %}" aria-label="{% trans 'Delete location' %}"><span class="glyphicon glyphicon-trash"></span></a>
{% if is_allowed_update_location %}
Copy link
Member

Choose a reason for hiding this comment

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

The edit button is never shown because you're using the wrong template context name here.

Copy link
Member

@oliverroick oliverroick left a comment

Choose a reason for hiding this comment

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

Good to go from my end. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants