Merge pull request #1065 from alexhermida/feature/not_found_in_forbidden

Feature/not found in forbidden
remotes/origin/release/3.1.1
Alejandro 2018-02-12 15:46:16 +01:00 committed by GitHub
commit 648fb12d39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 22 deletions

View File

@ -32,6 +32,30 @@ from taiga.base.utils.db import to_tsquery
logger = logging.getLogger(__name__)
def get_filter_expression_can_view_projects(user, project_id=None):
# Filter by user permissions
if user.is_authenticated() and user.is_superuser:
return Q()
elif user.is_authenticated():
# authenticated user & project member
membership_model = apps.get_model("projects", "Membership")
memberships_qs = membership_model.objects.filter(user=user)
if project_id:
memberships_qs = memberships_qs.filter(project_id=project_id)
memberships_qs = memberships_qs.filter(
Q(role__permissions__contains=['view_project']) |
Q(is_admin=True))
projects_list = [membership.project_id for membership in
memberships_qs]
return (Q(id__in=projects_list) |
Q(public_permissions__contains=["view_project"]))
else:
# external users / anonymous
return Q(anon_permissions__contains=["view_project"])
#####################################################################
# Base and Mixins
#####################################################################

View File

@ -136,10 +136,25 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
return qs
def retrieve(self, request, *args, **kwargs):
qs = self.get_queryset()
if self.action == "by_slug":
self.lookup_field = "slug"
# If we retrieve the project by slug we want to filter by user the
# permissions and return 404 in case the user don't have access
flt = filters.get_filter_expression_can_view_projects(
self.request.user)
return super().retrieve(request, *args, **kwargs)
qs = qs.filter(flt)
self.object = get_object_or_404(qs, **kwargs)
self.check_permissions(request, 'retrieve', self.object)
if self.object is None:
raise Http404
serializer = self.get_serializer(self.object)
return response.Ok(serializer.data)
def get_serializer_class(self):
if self.action == "list":

View File

@ -23,6 +23,7 @@ from django.utils.translation import ugettext as _
from taiga.base import exceptions as exc
from taiga.base.filters import FilterBackend
from taiga.base.filters import get_filter_expression_can_view_projects
from taiga.base.utils.db import to_tsquery
logger = logging.getLogger(__name__)
@ -63,28 +64,11 @@ class CanViewProjectObjFilterBackend(FilterBackend):
))
raise exc.BadRequest(_("'project' must be an integer value."))
qs = queryset
filter_expression = get_filter_expression_can_view_projects(
request.user,
project_id)
# Filter by user permissions
if request.user.is_authenticated() and request.user.is_superuser:
# superuser
qs = qs
elif request.user.is_authenticated():
# authenticated user & project member
membership_model = apps.get_model("projects", "Membership")
memberships_qs = membership_model.objects.filter(user=request.user)
if project_id:
memberships_qs = memberships_qs.filter(project_id=project_id)
memberships_qs = memberships_qs.filter(Q(role__permissions__contains=['view_project']) |
Q(is_admin=True))
projects_list = [membership.project_id for membership in memberships_qs]
qs = qs.filter((Q(id__in=projects_list) |
Q(public_permissions__contains=["view_project"])))
else:
# external users / anonymous
qs = qs.filter(anon_permissions__contains=["view_project"])
qs = queryset.filter(filter_expression)
return super().filter_queryset(request, qs, view)

View File

@ -72,6 +72,21 @@ def test_get_project_by_slug(client):
assert response.status_code == 404
def test_get_private_project_by_slug(client):
project = f.create_project(is_private=True)
f.MembershipFactory(user=project.owner, project=project, is_admin=True)
url = reverse("projects-by-slug")
response = client.json.get(url, {"slug": project.slug})
assert response.status_code == 404
client.login(project.owner)
response = client.json.get(url, {"slug": project.slug})
assert response.status_code == 200
def test_create_project(client):
user = f.create_user()
url = reverse("projects-list")