Skip to content

Commit

Permalink
Advanced Workflow: Make sure the APIs counters are coherent with the …
Browse files Browse the repository at this point in the history
…visible resources
  • Loading branch information
afabiani committed Oct 23, 2020
1 parent 5591b92 commit 1855d74
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 32 deletions.
14 changes: 7 additions & 7 deletions geonode/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,8 @@ def dehydrate_member_count(self, bundle):
def dehydrate(self, bundle):
"""Provide additional resource counts"""
request = bundle.request
_user = request.user
counts = _get_resource_counts(
_user,
request,
resourcebase_filter_kwargs={
'group__groupprofile__categories': bundle.obj
}
Expand Down Expand Up @@ -428,9 +427,8 @@ class Meta:
def dehydrate(self, bundle):
"""Provide additional resource counts"""
request = bundle.request
_user = request.user
counts = _get_resource_counts(
_user,
request,
resourcebase_filter_kwargs={'group': bundle.obj}
)

Expand Down Expand Up @@ -856,15 +854,15 @@ class StyleResource(GeoserverStyleResource):
pass


def _get_resource_counts(user, resourcebase_filter_kwargs):
def _get_resource_counts(request, resourcebase_filter_kwargs):
"""Return a dict with counts of resources of various types
The ``resourcebase_filter_kwargs`` argument should be a dict with a suitable
queryset filter that can be applied to select only the relevant
``ResourceBase`` objects to use when retrieving counts. For example::
_get_resource_counts(
user,
request,
{
'group__slug': 'my-group',
}
Expand All @@ -876,10 +874,12 @@ def _get_resource_counts(user, resourcebase_filter_kwargs):
"""
resources = get_visible_resources(
ResourceBase.objects.filter(**resourcebase_filter_kwargs),
user,
request.user,
request=request,
admin_approval_required=settings.ADMIN_MODERATE_UPLOADS,
unpublished_not_visible=settings.RESOURCE_PUBLISHING,
private_groups_not_visibile=settings.GROUP_PRIVATE_RESOURCES)

values = resources.values(
'polymorphic_ctype__model',
'is_approved',
Expand Down
25 changes: 21 additions & 4 deletions geonode/security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,23 @@
from django.conf import settings
from django.db.models import Q
from django.contrib.auth import get_user_model
# from django.contrib.gis.geos import GEOSGeometry
from django.core.exceptions import PermissionDenied
from django.contrib.contenttypes.models import ContentType
# from django.contrib.auth import login
from django.contrib.auth.models import Group, Permission
from django.core.exceptions import ObjectDoesNotExist
from guardian.utils import get_user_obj_perms_model
from guardian.shortcuts import assign_perm, get_anonymous_user
from geonode.groups.models import GroupProfile

from geonode.utils import resolve_object
from geonode.utils import get_layer_workspace
from geonode.groups.models import GroupProfile

logger = logging.getLogger("geonode.security.utils")


def get_visible_resources(queryset,
user,
request=None,
admin_approval_required=False,
unpublished_not_visible=False,
private_groups_not_visibile=False):
Expand Down Expand Up @@ -106,7 +108,22 @@ def get_visible_resources(queryset,
elif not user or user.is_anonymous:
filter_set = filter_set.exclude(Q(dirty_state=True))

return filter_set
_allowed_resources = []
for _resource in filter_set.all():
try:
resolve_object(
request,
_resource.__class__,
{
'id': _resource.id
},
'base.view_resourcebase',
user=user)
_allowed_resources.append(_resource.id)
except (PermissionDenied, Exception) as e:
logger.debug(e)

return filter_set.filter(id__in=_allowed_resources)


def get_users_with_perms(obj):
Expand Down
2 changes: 1 addition & 1 deletion geonode/social/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _filter_actions(action, request):
except ResourceBase.DoesNotExist:
_filtered_actions.append(_action.id)
except (PermissionDenied, Exception) as e:
logging.debug(e)
logger.debug(e)
return _filtered_actions

context['action_list'] = Action.objects.filter(
Expand Down
41 changes: 21 additions & 20 deletions geonode/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ def _get_viewer_projection_info(srid):


def resolve_object(request, model, query, permission='base.view_resourcebase',
permission_required=True, permission_msg=None):
user=None, permission_required=True, permission_msg=None):
"""Resolve an object using the provided query and check the optional
permission. Model views should wrap this function as a shortcut.
Expand All @@ -886,6 +886,7 @@ def resolve_object(request, model, query, permission='base.view_resourcebase',
permission_required - if False, allow get methods to proceed
permission_msg - optional message to use in 403
"""
user = request.user if request and request.user else user
obj = get_object_or_404(model, **query)
obj_to_check = obj.get_self_resource()

Expand All @@ -910,52 +911,52 @@ def resolve_object(request, model, query, permission='base.view_resourcebase',
if manager not in obj_group_managers and not manager.is_superuser:
obj_group_managers.append(manager)
if group_profile.user_is_member(
request.user) and request.user not in obj_group_members:
obj_group_members.append(request.user)
user) and user not in obj_group_members:
obj_group_members.append(user)
except GroupProfile.DoesNotExist:
pass

if settings.RESOURCE_PUBLISHING or settings.ADMIN_MODERATE_UPLOADS:
is_admin = False
is_manager = False
is_owner = True if request.user == obj_to_check.owner else False
if request.user and request.user.is_authenticated:
is_admin = request.user.is_superuser if request.user else False
is_owner = True if user == obj_to_check.owner else False
if user and user.is_authenticated:
is_admin = user.is_superuser if user else False
try:
is_manager = request.user.groupmember_set.all().filter(role='manager').exists()
is_manager = user.groupmember_set.all().filter(role='manager').exists()
except Exception:
is_manager = False
if (not obj_to_check.is_approved):
if not request.user or request.user.is_anonymous:
if not user or user.is_anonymous:
raise Http404
elif not is_admin:
if is_manager and request.user in obj_group_managers:
if (not request.user.has_perm('publish_resourcebase', obj_to_check)) and (
not request.user.has_perm('view_resourcebase', obj_to_check)) and (
not request.user.has_perm('change_resourcebase_metadata', obj_to_check)) and (
if is_manager and user in obj_group_managers:
if (not user.has_perm('publish_resourcebase', obj_to_check)) and (
not user.has_perm('view_resourcebase', obj_to_check)) and (
not user.has_perm('change_resourcebase_metadata', obj_to_check)) and (
not is_owner and not settings.ADMIN_MODERATE_UPLOADS):
pass
else:
assign_perm(
'view_resourcebase', request.user, obj_to_check)
'view_resourcebase', user, obj_to_check)
assign_perm(
'publish_resourcebase',
request.user,
user,
obj_to_check)
assign_perm(
'change_resourcebase_metadata',
request.user,
user,
obj_to_check)
assign_perm(
'download_resourcebase',
request.user,
user,
obj_to_check)

if is_owner:
assign_perm(
'change_resourcebase', request.user, obj_to_check)
'change_resourcebase', user, obj_to_check)
assign_perm(
'delete_resourcebase', request.user, obj_to_check)
'delete_resourcebase', user, obj_to_check)

allowed = True
if permission.split('.')[-1] in ['change_layer_data',
Expand All @@ -964,10 +965,10 @@ def resolve_object(request, model, query, permission='base.view_resourcebase',
obj_to_check = obj
if permission:
if permission_required or request.method != 'GET':
if request.user in obj_group_managers:
if user in obj_group_managers:
allowed = True
else:
allowed = request.user.has_perm(
allowed = user.has_perm(
permission,
obj_to_check)
if not allowed:
Expand Down

0 comments on commit 1855d74

Please sign in to comment.