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

[Fixes #7718] Permissions assignments on Remote Services #7719

Merged
merged 31 commits into from
Jul 6, 2021
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4bea641
[Backport Resolves #7392] Fix upload/replace/append layer
mattiagiupponi Apr 27, 2021
827218c
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi Apr 27, 2021
2b2e4be
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi Apr 29, 2021
b98fead
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi May 3, 2021
adb26d5
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi May 3, 2021
8f940f8
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi May 4, 2021
77e9940
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi May 6, 2021
74aaa0f
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi May 26, 2021
df39387
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi Jun 10, 2021
0274b67
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi Jun 11, 2021
b451071
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi Jun 17, 2021
4217bd5
Merge branch 'GeoNode:3.2.x' into 3.2.x
mattiagiupponi Jun 23, 2021
4c8bf6c
Merge remote-tracking branch 'upstream/3.2.x' into 3.2.x
mattiagiupponi Jun 25, 2021
781477d
[Fixes #7718] Permissions assignments on Remote Services
mattiagiupponi Jun 28, 2021
bfcc61c
[Fixes #7718] Permissions assignments on Remote Services
mattiagiupponi Jun 29, 2021
16916c8
[Fixes #7718] Permissions assignments on Remote Services
mattiagiupponi Jun 30, 2021
91c7cb4
[Fixes #7718] Permissions assignments on Remote Services
mattiagiupponi Jun 30, 2021
7e97096
[Fixes #7718] Pep8 issues fixed
mattiagiupponi Jun 30, 2021
b147dc9
[Fixes #7718] Permissions assignments on Remote Services
mattiagiupponi Jun 30, 2021
d8d8c61
[Fixes #7718] remove unused imports
mattiagiupponi Jun 30, 2021
b34c432
Merge remote-tracking branch 'upstream/3.2.x' into ISSUE_7718
mattiagiupponi Jul 1, 2021
bd35d29
Merge branch '3.2.x' of https://github.com/GeoNode/geonode into ISSUE…
Jul 1, 2021
9ea6ebd
[Fixes #7718] Fix broken migrations
mattiagiupponi Jul 1, 2021
1669d3d
Merge branch 'ISSUE_7718' of github.com:mattiagiupponi/geonode into I…
mattiagiupponi Jul 1, 2021
e3290a6
[CircelCI] Tests fix
Jul 1, 2021
11bdb48
[Fixes #7718] db startup error
mattiagiupponi Jul 2, 2021
c8938a5
Merge branch 'ISSUE_7718' of github.com:mattiagiupponi/geonode into I…
mattiagiupponi Jul 2, 2021
2a64aef
[Fixes #7718] Fix impovements from ISSUE
mattiagiupponi Jul 2, 2021
51aa2de
Update views.py
mattiagiupponi Jul 5, 2021
8462948
Update service_detail.html
mattiagiupponi Jul 5, 2021
3d40b19
[Fixes #7718] Fix count layers on services list, now is based on visi…
mattiagiupponi Jul 6, 2021
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
8 changes: 1 addition & 7 deletions geonode/base/populate_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
from django.contrib.auth.models import Permission, Group
from django.core.serializers import serialize
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.core.files.uploadedfile import SimpleUploadedFile

from geonode import geoserver # noqa
Expand Down Expand Up @@ -156,12 +155,7 @@ def create_models(type=None, integration=False):
map_data, user_data, people_data, layer_data, document_data = create_fixtures()
anonymous_group, created = Group.objects.get_or_create(name='anonymous')
cont_group, created = Group.objects.get_or_create(name='contributors')
ctype = ContentType.objects.get_for_model(cont_group)
perm, created = Permission.objects.get_or_create(
codename='base_addresourcebase',
name='Can add resources',
content_type=ctype
)
perm = Permission.objects.get(codename='add_resourcebase')
cont_group.permissions.add(perm)
logger.debug("[SetUp] Get or create user admin")
u, created = get_user_model().objects.get_or_create(username='admin')
Expand Down
33 changes: 33 additions & 0 deletions geonode/people/migrations/0033_set_contributors_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Assign the contributors group to users according to #7364

from django.contrib.auth.models import Group, Permission
from geonode.base.models import ResourceBase
from django.contrib.contenttypes.models import ContentType
from django.db import migrations
from django.db.migrations.operations import RunPython


def assign_permissions_to_contributors(apps, schema_editor):
contributors = Group.objects.filter(name='contributors')
if contributors.exists():
contr_obj = contributors.first()
perm = Permission.objects.get(codename='add_resourcebase')
contr_obj.permissions.add(perm)
perm_exists = contr_obj.permissions.filter(codename='base_addresourcebase')
if perm_exists.exists():
contr_obj.permissions.remove(perm_exists.first())
contr_obj.save()
perm_to_remove = Permission.objects.filter(codename='base_addresourcebase')
if perm_to_remove.exists():
perm_to_remove.delete()


class Migration(migrations.Migration):

dependencies = [
('people', '0032_set_contributors_group'),
]

operations = [
RunPython(assign_permissions_to_contributors)
]
3 changes: 2 additions & 1 deletion geonode/security/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
ADMIN_PERMISSIONS,
LAYER_ADMIN_PERMISSIONS,
VIEW_PERMISSIONS,
SERVICE_PERMISSIONS
)

from .utils import (
Expand Down Expand Up @@ -432,7 +433,7 @@ def get_user_perms(self, user):

config = Configuration.load()
ctype = ContentType.objects.get_for_model(self)
PERMISSIONS_TO_FETCH = VIEW_PERMISSIONS + ADMIN_PERMISSIONS + LAYER_ADMIN_PERMISSIONS
PERMISSIONS_TO_FETCH = VIEW_PERMISSIONS + ADMIN_PERMISSIONS + LAYER_ADMIN_PERMISSIONS + SERVICE_PERMISSIONS

resource_perms = Permission.objects.filter(
codename__in=PERMISSIONS_TO_FETCH,
Expand Down
7 changes: 6 additions & 1 deletion geonode/security/permissions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Permissions mapping
PERMISSIONS = {
'base_addresourcebase': 'add_resource',
'add_resourcebase': 'add_resource',
}

# The following permissions will be filtered out when READ_ONLY mode is active
Expand All @@ -26,3 +26,8 @@
'change_layer_data',
'change_layer_style'
]

SERVICE_PERMISSIONS = [
"change_resourcebase_metadata",
"add_resourcebase_from_service"
]
15 changes: 10 additions & 5 deletions geonode/security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ def get_users_with_perms(obj):
"""
Override of the Guardian get_users_with_perms
"""
from .permissions import (VIEW_PERMISSIONS, ADMIN_PERMISSIONS, LAYER_ADMIN_PERMISSIONS)
from .permissions import (VIEW_PERMISSIONS, ADMIN_PERMISSIONS, LAYER_ADMIN_PERMISSIONS, SERVICE_PERMISSIONS)
ctype = ContentType.objects.get_for_model(obj)
permissions = {}
PERMISSIONS_TO_FETCH = VIEW_PERMISSIONS + ADMIN_PERMISSIONS + LAYER_ADMIN_PERMISSIONS
PERMISSIONS_TO_FETCH = VIEW_PERMISSIONS + ADMIN_PERMISSIONS + LAYER_ADMIN_PERMISSIONS + SERVICE_PERMISSIONS

for perm in Permission.objects.filter(codename__in=PERMISSIONS_TO_FETCH, content_type_id=ctype.id):
permissions[perm.id] = perm.codename
Expand Down Expand Up @@ -562,8 +562,6 @@ def sync_geofence_with_guardian(layer, perms, user=None, group=None, group_perms
_group, _user, _disable_cache, users_geolimits, groups_geolimits, anonymous_geolimits = get_user_geolimits(layer, user, group, gf_services)

if _disable_cache:
filters = None
formats = None
# Re-order dictionary
# - if geo-limits have been defined for this user/group, the "*" rule must be the first one
gf_services_limits_first = {"*": gf_services.pop('*')}
Expand Down Expand Up @@ -659,7 +657,7 @@ def _get_gf_services(layer, perms):

def set_owner_permissions(resource, members=None):
"""assign all admin permissions to the owner"""
from .permissions import (VIEW_PERMISSIONS, ADMIN_PERMISSIONS, LAYER_ADMIN_PERMISSIONS)
from .permissions import (VIEW_PERMISSIONS, ADMIN_PERMISSIONS, LAYER_ADMIN_PERMISSIONS, SERVICE_PERMISSIONS)
if resource.polymorphic_ctype:
# Owner & Manager Admin Perms
admin_perms = VIEW_PERMISSIONS + ADMIN_PERMISSIONS
Expand All @@ -680,6 +678,13 @@ def set_owner_permissions(resource, members=None):
for user in members:
assign_perm(perm, user, resource.layer)

if resource.polymorphic_ctype.name == 'service':
for perm in SERVICE_PERMISSIONS:
assign_perm(perm, resource.owner, resource.service)
if members:
for user in members:
assign_perm(perm, user, resource.service)


def remove_object_permissions(instance):
"""Remove object permissions on given resource.
Expand Down
17 changes: 17 additions & 0 deletions geonode/services/migrations/0044_auto_20210628_0955.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.2.20 on 2021-06-28 09:55

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('services', '0043_auto_20210519_1308'),
]

operations = [
migrations.AlterModelOptions(
name='service',
options={'permissions': (('add_resourcebase_from_service', 'Can add resources to Service'),)},
),
]
17 changes: 17 additions & 0 deletions geonode/services/migrations/0045_auto_20210629_1355.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.2.20 on 2021-06-29 13:55

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('services', '0044_auto_20210628_0955'),
]

operations = [
migrations.AlterModelOptions(
name='service',
options={'permissions': (('add_resourcebase_from_service', 'Can add resources to Service'), ('change_resourcebase_metadata', 'Can change resources metadata'))},
),
]
8 changes: 8 additions & 0 deletions geonode/services/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ def probe_service(self):
except Exception:
return 404

class Meta:
# custom permissions,
# change and delete are standard in django-guardian
permissions = (
('add_resourcebase_from_service', 'Can add resources to Service'),
('change_resourcebase_metadata', 'Can change resources metadata'),
)


class ServiceProfileRole(models.Model):

Expand Down
16 changes: 8 additions & 8 deletions geonode/services/templates/services/service_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,22 @@ <h3>{% trans "Service Resources" %} <span class="badge">{{ total_resources }}</s
{% endblock %}
{% block sidebar %}


{% get_obj_perms request.user for service as "resource_perms" %}

{% comment %}{% if "change_service" in resource_perms or "remove_service" in resource_perms or "change_service_permissions" in resource_perms %}{% endcomment %}
{% if "add_resourcebase_from_service" in resource_perms or "change_resourcebase_metadata" in resource_perms or "change_service_permissions" in resource_perms %}
<ul class="list-group">
<li class="list-group-item"><h3>{% trans "Manage" %}</h3></li>

{% comment %}{% if "change_service" in resource_perms %}{% endcomment %}
{% if "change_resourcebase_metadata" in resource_perms %}
<li class="list-group-item"><a class="btn btn-default btn-md btn-block" href="{% url "edit_service" service.id %}">{% trans "Edit Service Metadata" %}</a></li>
{% endif %}
{% if "add_resourcebase_from_service" in resource_perms %}
<li class="list-group-item"><a id="harvestResources" class="btn btn-default btn-md btn-block" href="{% url "harvest_resources" service.id %}">{% trans "Import Service Resources" %}</a></li>
{% comment %}{% endif %}{% endcomment %}
{% comment %}{% if "remove_service" or "delete_service" in resource_perms %}{% endcomment %}
{% endif %}
{% if "remove_service" in permissions_list or "delete_service" in permissions_list or 'delete_resourcebase' in permissions_list %}
<li class="list-group-item"><a class="btn btn-default btn-md btn-block" href="{% url "remove_service" service.id %}">{% trans "Remove Service" %}</a></li>
{% comment %}{% endif %}{% endcomment %}
{% endif %}
</ul>
{% comment %}{% endif %}{% endcomment %}
{% endif %}
{% endblock %}
{% block extra_script %}
{{ block.super }}
Expand Down
2 changes: 1 addition & 1 deletion geonode/services/templates/services/service_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

{% block body_outer %}
<div class="page-header">
{% if user.is_authenticated and not READ_ONLY_MODE %}
{% if user.is_authenticated and not READ_ONLY_MODE and can_add_resources %}
<a href="{% url "register_service" %}" class="btn btn-primary pull-right">{% trans "Add Remote Service" %}</a>
{% endif %}
<h2>{% trans "Remote Services" %}</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ <h3>{% trans "Import resources" %}
<button id="btnClearFilter" type="button" class="btn btn-default">{% trans "Clear Filter" %}</button>
<a class="btn btn-default"
href="{% url "service_detail" service.id %}">{% trans "Back to service details" %}</a>
{% if "add_resourcebase_from_service" in resource_perms or 'add_resourcebase_from_service' in permissions_list %}
<input type="submit" class="btn btn-primary" value="{% trans "Import Resources" %}"/>
{% endif %}
</div>
</div>
</form>
Expand Down
27 changes: 27 additions & 0 deletions geonode/services/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#
#########################################################################
import logging
from geonode.services.enumerations import WMS, INDEXED
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test import Client
from selenium import webdriver
Expand Down Expand Up @@ -882,3 +883,29 @@ def test_harvest_resources(self):
self.selenium.find_element_by_id('btn-id-filter').click()
# self.selenium.find_element_by_id('option_atlantis:tiger_roads_tiger_roads').click()
# self.selenium.find_element_by_tag_name('form').submit()


class TestServiceViews(GeoNodeBaseTestSupport):
def setUp(self):
self.user = 'admin'
self.passwd = 'admin'
self.admin = get_user_model().objects.get(username='admin')
self.sut, _ = Service.objects.get_or_create(
type=WMS,
name='Bogus',
title='Pocus',
owner=self.admin,
method=INDEXED,
metadata_only=True,
base_url='http://bogus.pocus.com/ows')
self.sut.clear_dirty_state()

def test_user_admin_can_access_to_page(self):
self.client.login(username='admin', password='admin')
response = self.client.get(reverse('services'))
self.assertEqual(response.status_code, 200)

def test_invalid_user_cannot_access_to_page(self):
self.client.login(username='bobby', password='bobby')
response = self.client.get(reverse('services'))
self.assertEqual(response.status_code, 302)
Loading