Skip to content

Save customized search if user has member level permissions #4947

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

Merged
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
10 changes: 10 additions & 0 deletions src/sentry/api/bases/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ class ProjectSettingPermission(ProjectPermission):
}


class RelaxedSearchPermission(ProjectPermission):
scope_map = {
'GET': ['project:read', 'project:write', 'project:admin'],
# members can do writes
'POST': ['project:write', 'project:admin', 'project:read'],
'PUT': ['project:write', 'project:admin', 'project:read'],
'DELETE': ['project:admin'],
}


class ProjectEndpoint(Endpoint):
permission_classes = (ProjectPermission,)

Expand Down
12 changes: 1 addition & 11 deletions src/sentry/api/endpoints/project_search_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rest_framework import serializers
from rest_framework.response import Response

from sentry.api.bases.project import ProjectEndpoint, ProjectPermission
from sentry.api.bases.project import ProjectEndpoint, RelaxedSearchPermission
from sentry.api.exceptions import ResourceDoesNotExist
from sentry.api.serializers import serialize
from sentry.models import SavedSearch, SavedSearchUserDefault
Expand All @@ -20,16 +20,6 @@ class SavedSearchSerializer(serializers.Serializer):
isUserDefault = serializers.BooleanField(required=False)


class RelaxedSearchPermission(ProjectPermission):
scope_map = {
'GET': ['project:read', 'project:write', 'project:admin'],
'POST': ['project:write', 'project:admin'],
# members can do partial writes
'PUT': ['project:write', 'project:admin', 'project:read'],
'DELETE': ['project:admin'],
}


class ProjectSearchDetailsEndpoint(ProjectEndpoint):
permission_classes = (RelaxedSearchPermission,)

Expand Down
38 changes: 27 additions & 11 deletions src/sentry/api/endpoints/project_searches.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from django.db import IntegrityError, transaction
from rest_framework import serializers
from rest_framework.response import Response
from django.db.models import Q

from sentry.api.bases.project import ProjectEndpoint
from sentry.api.bases.project import ProjectEndpoint, RelaxedSearchPermission
from sentry.api.serializers import serialize
from sentry.models import SavedSearch, SavedSearchUserDefault

Expand All @@ -17,6 +18,8 @@ class SavedSearchSerializer(serializers.Serializer):


class ProjectSearchesEndpoint(ProjectEndpoint):
permission_classes = (RelaxedSearchPermission,)

def get(self, request, project):
"""
List a project's saved searches
Expand All @@ -26,9 +29,16 @@ def get(self, request, project):
{method} {path}

"""
results = list(SavedSearch.objects.filter(
project=project,
).order_by('name'))
if request.access.has_scope('project:write'):
results = list(SavedSearch.objects.filter(
project=project,
owner__isnull=True
).order_by('name'))
else:
results = list(SavedSearch.objects.filter(
Q(owner=request.user) | Q(owner__isnull=True),
project=project
).order_by('name'))

return Response(serialize(results, request.user))

Expand Down Expand Up @@ -57,20 +67,26 @@ def post(self, request, project):
name=result['name'],
query=result['query'],
is_default=result.get('isDefault', False),
owner=(None if request.access.has_scope('project:write') else request.user)
)
except IntegrityError:
return Response({
'detail': 'Search with same name already exists.'
}, status=400)

if search.is_default:
SavedSearch.objects.filter(
project=project,
).exclude(
id=search.id,
).update(
is_default=False,
)
if request.access.has_scope('project:write'):
SavedSearch.objects.filter(
project=project,
).exclude(
id=search.id,
).update(
is_default=False,
)
else:
return Response({
'detail': 'User doesn\'t have permission to set default view'
}, status=400)

if result.get('isUserDefault'):
SavedSearchUserDefault.objects.create_or_update(
Expand Down
1 change: 1 addition & 0 deletions src/sentry/api/serializers/models/savedsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ def serialize(self, obj, attrs, user):
'isDefault': obj.is_default,
'isUserDefault': attrs['isUserDefault'],
'dateCreated': obj.date_added,
'isPrivate': bool(obj.owner),
}
1 change: 1 addition & 0 deletions src/sentry/models/savedsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class SavedSearch(Model):
query = models.TextField()
date_added = models.DateTimeField(default=timezone.now)
is_default = models.BooleanField(default=False)
owner = FlexibleForeignKey('sentry.User', null=True)

class Meta:
app_label = 'sentry'
Expand Down
Loading