Skip to content

Commit

Permalink
[Fixes #5779] Data edition permissions set in GeoNode for a layer are…
Browse files Browse the repository at this point in the history
… not applied on the WFS
  • Loading branch information
afabiani committed Nov 14, 2020
1 parent da1603f commit 9e4e839
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
13 changes: 7 additions & 6 deletions geonode/proxy/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,13 @@ def proxy(request, url=None, response_callback=None,
'%s%s' % (settings.SITEURL, 'geoserver'),
ogc_server_settings.LOCATION.rstrip('/'))

response, content = http_client.request(_url,
method=request.method,
data=_data,
headers=headers,
timeout=timeout,
user=request.user)
response, content = http_client.request(
_url,
method=request.method,
data=_data,
headers=headers,
timeout=timeout,
user=request.user)
content = response.content or response.reason
status = response.status_code
content_type = response.headers.get('Content-Type')
Expand Down
5 changes: 4 additions & 1 deletion geonode/security/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ def set_permissions(self, perm_spec, created=False):
# Set the GeoFence Rules
if settings.OGC_SERVER['default'].get("GEOFENCE_SECURITY_ENABLED", False):
if self.polymorphic_ctype.name == 'layer':
sync_geofence_with_guardian(self.layer, perms, user=user)
group_perms = None
if 'groups' in perm_spec and len(perm_spec['groups']) > 0:
group_perms = perm_spec['groups']
sync_geofence_with_guardian(self.layer, perms, user=_user, group_perms=group_perms)

# All the other groups
if 'groups' in perm_spec and len(perm_spec['groups']) > 0:
Expand Down
48 changes: 42 additions & 6 deletions geonode/security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,24 +532,41 @@ def set_geofence_all(instance):


@on_ogc_backend(geoserver.BACKEND_PACKAGE)
def sync_geofence_with_guardian(layer, perms, user=None, group=None):
def sync_geofence_with_guardian(layer, perms, user=None, group=None, group_perms=None):
"""
Sync Guardian permissions to GeoFence.
"""
_layer_name = layer.name if layer and hasattr(layer, 'name') else layer.alternate.split(":")[0]
_layer_workspace = get_layer_workspace(layer)
# Create new rule-set
gf_services = {}
gf_services["*"] = 'download_resourcebase' in perms and \
('view_resourcebase' in perms or 'change_layer_style' in perms)
gf_services["WMS"] = 'view_resourcebase' in perms or 'change_layer_style' in perms
gf_services["GWC"] = 'view_resourcebase' in perms or 'change_layer_style' in perms
gf_services["WFS"] = ('download_resourcebase' in perms or 'change_layer_data' in perms) \
and layer.is_vector()
gf_services["WCS"] = ('download_resourcebase' in perms or 'change_layer_data' in perms) \
and not layer.is_vector()
gf_services["WPS"] = 'download_resourcebase' in perms or 'change_layer_data' in perms
gf_services["*"] = 'download_resourcebase' in perms and \
('view_resourcebase' in perms or 'change_layer_style' in perms)

gf_requests = {}
if 'change_layer_data' not in perms:
_skip_perm = False
if user and group_perms:
if isinstance(user, string_types):
user = get_user_model().objects.get(username=user)
user_groups = list(user.groups.all().values_list('name', flat=True))
for _group, _perm in group_perms.items():
if 'change_layer_data' in _perm and _group in user_groups:
_skip_perm = True
break
if not _skip_perm:
gf_requests["WFS"] = {
"TRANSACTION": False,
"LOCKFEATURE": False,
"GETFEATUREWITHLOCK": False
}
_user = None
_group = None
_disable_layer_cache = False
Expand Down Expand Up @@ -602,19 +619,31 @@ def sync_geofence_with_guardian(layer, perms, user=None, group=None):
_wkt = None
if users_geolimits and users_geolimits.count():
_wkt = users_geolimits.last().wkt
if service in gf_requests:
for request, enabled in gf_requests[service].items():
_update_geofence_rule(layer, _layer_name, _layer_workspace,
service, request=request, user=_user, allow=enabled)
_update_geofence_rule(layer, _layer_name, _layer_workspace, service, user=_user, geo_limit=_wkt)
elif not _group:
logger.debug("Adding to geofence the rule: %s %s *" % (layer, service))
_wkt = None
if anonymous_geolimits and anonymous_geolimits.count():
_wkt = anonymous_geolimits.last().wkt
_update_geofence_rule(layer, _layer_name, _layer_workspace, service, geo_limit=_wkt)
if service in gf_requests:
for request, enabled in gf_requests[service].items():
_update_geofence_rule(layer, _layer_name, _layer_workspace,
service, request=request, user=_user, allow=enabled)
if _group:
logger.debug("Adding 'group' to geofence the rule: %s %s %s" % (layer, service, _group))
_wkt = None
if groups_geolimits and groups_geolimits.count():
_wkt = groups_geolimits.last().wkt
_update_geofence_rule(layer, _layer_name, _layer_workspace, service, group=_group, geo_limit=_wkt)
if service in gf_requests:
for request, enabled in gf_requests[service].items():
_update_geofence_rule(layer, _layer_name, _layer_workspace,
service, request=request, group=_group, allow=enabled)
if not getattr(settings, 'DELAYED_SECURITY_SIGNALS', False):
set_geofence_invalidate_cache()
else:
Expand Down Expand Up @@ -682,7 +711,7 @@ def remove_object_permissions(instance):


def _get_geofence_payload(layer, layer_name, workspace, access, user=None, group=None,
service=None, geo_limit=None):
service=None, request=None, geo_limit=None):
highest_priority = get_highest_priority()
root_el = etree.Element("Rule")
username_el = etree.SubElement(root_el, "userName")
Expand All @@ -702,6 +731,9 @@ def _get_geofence_payload(layer, layer_name, workspace, access, user=None, group
if service is not None and service != "*":
service_el = etree.SubElement(root_el, "service")
service_el.text = service
if request is not None and request != "*":
service_el = etree.SubElement(root_el, "request")
service_el.text = request
if service and service == "*" and geo_limit is not None and geo_limit != "":
access_el = etree.SubElement(root_el, "access")
access_el.text = "LIMIT"
Expand All @@ -716,15 +748,19 @@ def _get_geofence_payload(layer, layer_name, workspace, access, user=None, group
return etree.tostring(root_el)


def _update_geofence_rule(layer, layer_name, workspace, service, user=None, group=None, geo_limit=None):
def _update_geofence_rule(layer, layer_name, workspace,
service, request=None,
user=None, group=None,
geo_limit=None, allow=True):
payload = _get_geofence_payload(
layer=layer,
layer_name=layer_name,
workspace=workspace,
access="ALLOW",
access="ALLOW" if allow else "DENY",
user=user,
group=group,
service=service,
request=request,
geo_limit=geo_limit
)
logger.debug("request data: {}".format(payload))
Expand Down

0 comments on commit 9e4e839

Please sign in to comment.