def user_can(self, user, permission): """ Checks if a has a given permission to the resource """ # To avoid circular import from geonode.base.models import Configuration config = Configuration.load() # Check read-only status if given permission is for edit, change or publish perm_prefixes = ['change', 'delete', 'publish'] if any(prefix in permission for prefix in perm_prefixes): if config.read_only: return False resource = self.get_self_resource() user_perms = self.get_user_perms(user).union( resource.get_user_perms(user)) is_admin = user.is_superuser is_staff = user.is_staff is_owner = user == self.owner try: is_manager = user.groupmember_set.all().filter( role='manager').exists() except Exception: is_manager = False has_access = is_admin or is_staff or is_owner or is_manager or user.has_perm( permission, obj=self) if permission in user_perms or has_access: return True return False
def setUp(self): super().setUp() self.user = '******' self.passwd = 'admin' create_dataset_data() self.config = Configuration.load() self.OGC_DEFAULT_SETTINGS = { 'default': { 'BACKEND': 'geonode.geoserver', 'LOCATION': 'http://localhost:8080/geoserver/', 'USER': '******', 'PASSWORD': '******', 'MAPFISH_PRINT_ENABLED': True, 'PRINT_NG_ENABLED': True, 'GEONODE_SECURITY_ENABLED': True, 'GEOFENCE_SECURITY_ENABLED': True, 'WMST_ENABLED': False, 'BACKEND_WRITE_ENABLED': True, 'WPS_ENABLED': False, 'DATASTORE': '', } } self.UPLOADER_DEFAULT_SETTINGS = { 'BACKEND': 'geonode.importer', 'OPTIONS': { 'TIME_ENABLED': False, 'MOSAIC_ENABLED': False}} self.DATABASE_DEFAULT_SETTINGS = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'development.db'}}
def get_base_right_topbar_menu(context): user = context.get('request').user about = { "label": "About", "type": "dropdown", "items": [{ "type": "link", "href": "/people/", "label": "People" }, { "type": "link", "href": "/groups/", "label": "Groups" }] } if user.is_authenticated and not Configuration.load().read_only: about['items'].extend([{ "type": "divider" }, { "type": "link", "href": "/invitations/geonode-send-invite/", "label": "Invite users" }, { "type": "link", "href": "/admin/people/profile/add/", "label": "Add user" } if user.is_superuser else None, { "type": "link", "href": "/groups/create/", "label": "Create group" }]) return [about]
def get_user_perms(self, user): """ Returns a list of permissions a user has on a given resource. """ # To avoid circular import from geonode.base.models import Configuration config = Configuration.load() ctype = ContentType.objects.get_for_model(self) PERMISSIONS_TO_FETCH = VIEW_PERMISSIONS + DOWNLOAD_PERMISSIONS + ADMIN_PERMISSIONS + SERVICE_PERMISSIONS # include explicit permissions appliable to "subtype == 'vector'" if self.subtype == 'vector': PERMISSIONS_TO_FETCH += DATASET_ADMIN_PERMISSIONS elif self.subtype == 'raster': PERMISSIONS_TO_FETCH += DATASET_EDIT_STYLE_PERMISSIONS resource_perms = Permission.objects.filter( codename__in=PERMISSIONS_TO_FETCH, content_type_id=ctype.id).values_list('codename', flat=True) # Don't filter for admin users if not user.is_superuser: user_model = get_user_obj_perms_model(self) user_resource_perms = user_model.objects.filter( object_pk=self.pk, content_type_id=ctype.id, user__username=str(user), permission__codename__in=resource_perms) # get user's implicit perms for anyone flag implicit_perms = get_perms(user, self) # filter out implicit permissions unappliable to "subtype != 'vector'" if self.subtype == 'raster': implicit_perms = list( set(implicit_perms) - set(DATASET_EDIT_DATA_PERMISSIONS)) elif self.subtype != 'vector': implicit_perms = list( set(implicit_perms) - set(DATASET_ADMIN_PERMISSIONS)) resource_perms = user_resource_perms.union( user_model.objects.filter( permission__codename__in=implicit_perms)).values_list( 'permission__codename', flat=True) # filter out permissions for edit, change or publish if readonly mode is active perm_prefixes = ['change', 'delete', 'publish'] if config.read_only: clauses = (Q(codename__contains=prefix) for prefix in perm_prefixes) query = reduce(operator.or_, clauses) if user.is_superuser: resource_perms = resource_perms.exclude(query) else: perm_objects = Permission.objects.filter( codename__in=resource_perms) resource_perms = perm_objects.exclude(query).values_list( 'codename', flat=True) return resource_perms
def test_maintenance_true(self): web_client = Client() # set read-only flag config = Configuration.load() config.read_only = False config.maintenance = True config.save() # post not whitelisted URL as superuser response = web_client.get('/') self.assertEqual(response.status_code, 503, 'User is allowed to get index page')
def configuration_session_cache(session): CONFIG_CACHE_TIMEOUT_SEC = 60 _config = session.get('config') _now = datetime.utcnow() _dt = isoparse(_config.get('expiration')) if _config else _now if _config is None or _dt < _now: config = Configuration.load() _dt = _now + timedelta(seconds=CONFIG_CACHE_TIMEOUT_SEC) cached_config = {'configuration': {}, 'expiration': _dt.isoformat()} for field_name in ['read_only', 'maintenance']: cached_config['configuration'][field_name] = getattr( config, field_name) session['config'] = cached_config
def handle(self, **options): skip_read_only = options.get('skip_read_only') config = Configuration.load() # activate read only mode and store it's original config value if not skip_read_only: original_read_only_value = config.read_only config.read_only = True config.save() try: self.execute_restore(**options) finally: # restore read only mode's original value if not skip_read_only: config.read_only = original_read_only_value config.save()
def get_user_perms(self, user): """ Returns a list of permissions a user has on a given resource """ # To avoid circular import from geonode.base.models import Configuration config = Configuration.load() ctype = ContentType.objects.get_for_model(self) PERMISSIONS_TO_FETCH = VIEW_PERMISSIONS + ADMIN_PERMISSIONS + LAYER_ADMIN_PERMISSIONS resource_perms = Permission.objects.filter( codename__in=PERMISSIONS_TO_FETCH, content_type_id=ctype.id).values_list('codename', flat=True) # Don't filter for admin users if not (user.is_superuser or user.is_staff): user_model = get_user_obj_perms_model(self) user_resource_perms = user_model.objects.filter( object_pk=self.pk, content_type_id=ctype.id, user__username=str(user), permission__codename__in=resource_perms) # get user's implicit perms for anyone flag implicit_perms = get_perms(user, self) resource_perms = user_resource_perms.union( user_model.objects.filter( permission__codename__in=implicit_perms)).values_list( 'permission__codename', flat=True) # filter out permissions for edit, change or publish if readonly mode is active perm_prefixes = ['change', 'delete', 'publish'] if config.read_only: clauses = (Q(codename__contains=prefix) for prefix in perm_prefixes) query = reduce(operator.or_, clauses) if (user.is_superuser or user.is_staff): resource_perms = resource_perms.exclude(query) else: perm_objects = Permission.objects.filter( codename__in=resource_perms) resource_perms = perm_objects.exclude(query).values_list( 'codename', flat=True) return resource_perms
def perms(self): if self.is_superuser or self.is_staff: # return all permissions for admins perms = PERMISSIONS.values() else: user_groups = self.groups.values_list('name', flat=True) group_perms = Permission.objects.filter( group__name__in=user_groups ).distinct().values_list('codename', flat=True) # return constant names defined by GeoNode perms = [PERMISSIONS[db_perm] for db_perm in group_perms] # check READ_ONLY mode config = Configuration.load() if config.read_only: # exclude permissions affected by readonly perms = [perm for perm in perms if perm not in READ_ONLY_AFFECTED_PERMISSIONS] return perms
def test_read_only_casual_user_privileges(self): web_client = Client() url_name = 'autocomplete_region' # set read-only flag config = Configuration.load() config.read_only = True config.maintenance = False config.save() # get user user, _ = get_user_model().objects.get_or_create(username='******') web_client.force_login(user) # post not whitelisted URL as superuser response = web_client.post(reverse(url_name)) self.assertEqual(response.status_code, 405, 'User is allowed to post to forbidden URL')
def test_read_only_whitelist(self): web_client = Client() # set read-only flag config = Configuration.load() config.read_only = True config.maintenance = False config.save() # post to whitelisted URLs as AnonymousUser for url_name in ReadOnlyMiddleware.WHITELISTED_URL_NAMES: if url_name == 'login': response = web_client.post(reverse('admin:login')) elif url_name == 'logout': response = web_client.post(reverse('admin:logout')) else: response = web_client.post(reverse(url_name)) self.assertNotEqual(response.status_code, 405, 'Whitelisted URL is not available.')
def handle(self, **options): skip_read_only = options.get('skip_read_only') config = Configuration.load() # activate read only mode and store it's original config value if not skip_read_only: original_read_only_value = config.read_only config.read_only = True config.save() try: # execute backup procedure self.execute_backup(**options) except Exception: raise finally: # restore read only mode's original value if not skip_read_only: config.read_only = original_read_only_value config.save()
def test_maintenance_whitelist(self): web_client = Client() # set read-only flag config = Configuration.load() config.read_only = False config.maintenance = True config.save() # post to whitelisted URLs as AnonymousUser for url_name in MaintenanceMiddleware.WHITELISTED_URL_NAMES: if url_name == 'login': response = web_client.get(reverse('admin:login')) elif url_name == 'logout': response = web_client.get(reverse('admin:logout')) elif url_name == 'index': # url needed in the middleware only for admin panel login redirection continue else: response = web_client.get(reverse(url_name)) self.assertNotEqual(response.status_code, 503, 'Whitelisted URL is not available.')
def resource_service_copy(self, request, pk=None): """Instructs the Async dispatcher to execute a 'COPY' operation over a valid 'pk' - PUT input_params: { instance: "<str: ID>" owner: "<str: username = <current_user>>" defaults: dict = {} } - output_params: { output: { uuid: "<str: UUID>" } } - output: { "status": "ready", "execution_id": "<str: execution ID>", "status_url": "http://localhost:8000/api/v2/resource-service/execution-status/<str: execution ID>" } Sample Request: 1. curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'defaults={"title":"pippo"}' http://localhost:8000/api/v2/resources/<id>/copy OUTPUT: { "status":"ready", "execution_id":"08846e84-eae4-11eb-84be-00155d41f2fb", "status_url":"http://localhost:8000/api/v2/resource-service/execution-status/08846e84-eae4-11eb-84be-00155d41f2fb" } 2. curl -v -X GET -u admin:admin http://localhost:8000/api/v2/resource-service/execution-status/08846e84-eae4-11eb-84be-00155d41f2fb OUTPUT: { "user": "******", "status": "finished", "func_name": "update", "created": "2021-07-22T14:42:56.284740Z", "finished": "2021-07-22T14:43:01.813971Z", "last_updated": "2021-07-22T14:42:56.284797Z", "input_params": { "uuid": "ee11541c-eaee-11eb-942c-00155d41f2fb", "defaults": "{\"title\":\"pippo\"}" }, "output_params": { "output": { "uuid": "ee11541c-eaee-11eb-942c-00155d41f2fb" } } } """ config = Configuration.load() resource = self.get_object() if config.read_only or config.maintenance or request.user.is_anonymous or not request.user.is_authenticated or \ resource is None or not request.user.has_perm('view_resourcebase', resource.get_self_resource()): return Response(status=status.HTTP_403_FORBIDDEN) try: request_params = QueryDict(request.body, mutable=True) _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='copy', input_params={ "instance": resource.id, "owner": request_params.get('owner', request.user.username), "defaults": request_params.get('defaults', '{}') }) resouce_service_dispatcher.apply_async((_exec_request.exec_id, )) return Response( { 'status': _exec_request.status, 'execution_id': _exec_request.exec_id, 'status_url': urljoin( settings.SITEURL, reverse('rs-execution-status', kwargs={'execution_id': _exec_request.exec_id })) }, status=status.HTTP_200_OK) except Exception as e: logger.exception(e) return Response(status=status.HTTP_400_BAD_REQUEST, exception=e)
def view(req, step=None): """Main uploader view""" if not auth.get_user(req).is_authenticated: return error_response(req, errors=["Not Authorized"]) config = Configuration.load() if config.read_only or config.maintenance: return error_response(req, errors=["Not Authorized"]) upload_session = None upload_id = req.GET.get('id', None) if step is None: if upload_id: # upload recovery upload_obj = get_object_or_404(Upload, import_id=upload_id, user=req.user) session = upload_obj.get_session if session: return next_step_response(req, session) step = 'save' # delete existing session if upload_id and upload_id in req.session: del req.session[upload_id] req.session.modified = True else: if not upload_id: return render(req, "upload/layer_upload_invalid.html", context={}) upload_obj = get_object_or_404(Upload, import_id=upload_id, user=req.user) session = upload_obj.get_session try: if session: upload_session = session else: upload_session = _get_upload_session(req) except Exception as e: logger.exception(e) try: if req.method == 'GET' and upload_session: # set the current step to match the requested page - this # could happen if the form is ajax w/ progress monitoring as # the advance would have already happened @hacky _completed_step = upload_session.completed_step try: _completed_step = get_previous_step(upload_session, step) upload_session.completed_step = _completed_step except Exception as e: logger.warning(e) return error_response(req, errors=e.args) resp = _steps[step](req, upload_session) resp_js = None try: content = resp.content if isinstance(content, bytes): content = content.decode('UTF-8') resp_js = json.loads(content) except Exception as e: logger.warning(e) # must be put back to update object in session if upload_session: if resp_js and step == 'final': try: delete_session = resp_js.get('status') != 'pending' if delete_session: # we're done with this session, wax it upload_session = None del req.session[upload_id] req.session.modified = True except Exception: pass else: upload_session = _get_upload_session(req) if upload_session: Upload.objects.update_from_session(upload_session) if resp_js: _success = resp_js.get('success', False) _redirect_to = resp_js.get('redirect_to', '') _required_input = resp_js.get('required_input', False) if _success and (_required_input or 'upload/final' in _redirect_to): from geonode.upload.tasks import finalize_incomplete_session_uploads finalize_incomplete_session_uploads.apply_async() return resp except BadStatusLine: logger.exception('bad status line, geoserver down?') return error_response(req, errors=[_geoserver_down_error_msg]) except gsimporter.RequestFailed as e: logger.exception('request failed') errors = e.args # http bad gateway or service unavailable if int(errors[0]) in (502, 503): errors = [_geoserver_down_error_msg] return error_response(req, errors=errors) except gsimporter.BadRequest as e: logger.exception('bad request') return error_response(req, errors=e.args) except Exception as e: return error_response(req, exception=e)
def resource_service_create(self, request, resource_type: str = None): """Instructs the Async dispatcher to execute a 'CREATE' operation **WARNING**: This will create an empty dataset; if you need to upload a resource to GeoNode, consider using the endpoint "ingest" instead - POST input_params: { uuid: "<str: UUID>", defaults: "{\"owner\":\"<str: username>\",<list: str>}", # WARNING: 'owner' is mandatory resource_type: "<enum: ['dataset', 'document', 'map', '<GeoApp: name>']>" } - output_params: { output: <int: number of resources deleted / 0 if none> } - output: { "status": "ready", "execution_id": "<str: execution ID>", "status_url": "http://localhost:8000/api/v2/resource-service/execution-status/<str: execution ID>" } Sample Request: 1. curl -v -X POST -u admin:admin -H "Content-Type: application/json" -d 'defaults={"owner":"admin","title":"pippo"}' http://localhost:8000/api/v2/resources/create/dataset OUTPUT: { "status": "ready", "execution_id": "90ca670d-df60-44b6-b358-d792c6aecc58", "status_url": "http://localhost:8000/api/v2/resource-service/execution-status/90ca670d-df60-44b6-b358-d792c6aecc58" } 2. curl -v -X GET -u admin:admin http://localhost:8000/api/v2/resource-service/execution-status/90ca670d-df60-44b6-b358-d792c6aecc58 OUTPUT: { "user": "******", "status": "finished", "func_name": "create", "created": "2021-07-22T15:32:09.096075Z", "finished": "2021-07-22T15:32:26.936683Z", "last_updated": "2021-07-22T15:32:09.096129Z", "input_params": { "uuid": "fa404f64-eb01-11eb-8f91-00155d41f2fb", "defaults": "{\"owner\":\"admin\",\"title\":\"pippo\"}", "resource_type": "dataset" }, "output_params": { "output": { "uuid": "fa404f64-eb01-11eb-8f91-00155d41f2fb" } } } """ config = Configuration.load() if config.read_only or config.maintenance or request.user.is_anonymous or not request.user.is_authenticated \ or not request.user.has_perm('base.add_resourcebase'): return Response(status=status.HTTP_403_FORBIDDEN) try: request_params = QueryDict(request.body, mutable=True) _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='create', input_params={ "uuid": request_params.get('uuid', str(uuid1())), "resource_type": resource_type, "defaults": request_params.get( 'defaults', f"{{\"owner\":\"{request.user.username}\"}}") }) resouce_service_dispatcher.apply_async((_exec_request.exec_id, )) return Response( { 'status': _exec_request.status, 'execution_id': _exec_request.exec_id, 'status_url': urljoin( settings.SITEURL, reverse('rs-execution-status', kwargs={'execution_id': _exec_request.exec_id })) }, status=status.HTTP_200_OK) except Exception as e: logger.exception(e) return Response(status=status.HTTP_400_BAD_REQUEST, exception=e)
def resource_service_update(self, request, pk=None): """Instructs the Async dispatcher to execute a 'UPDATE' operation over a valid 'uuid' - PUT input_params: { id: "<str: ID>" xml_file: str = None metadata_uploaded: bool = False vals: dict = {} regions: list = [] keywords: list = [] custom: dict = {} notify: bool = True } - output_params: { output: { uuid: "<str: UUID>" } } - output: { "status": "ready", "execution_id": "<str: execution ID>", "status_url": "http://localhost:8000/api/v2/resource-service/execution-status/<str: execution ID>" } Sample Request: 1. curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'vals={"title":"pippo"}' http://localhost:8000/api/v2/resources/<id>/update OUTPUT: { "status":"ready", "execution_id":"08846e84-eae4-11eb-84be-00155d41f2fb", "status_url":"http://localhost:8000/api/v2/resource-service/execution-status/08846e84-eae4-11eb-84be-00155d41f2fb" } 2. curl -v -X GET -u admin:admin http://localhost:8000/api/v2/resource-service/execution-status/08846e84-eae4-11eb-84be-00155d41f2fb OUTPUT: { "user": "******", "status": "finished", "func_name": "update", "created": "2021-07-22T14:42:56.284740Z", "finished": "2021-07-22T14:43:01.813971Z", "last_updated": "2021-07-22T14:42:56.284797Z", "input_params": { "uuid": "ee11541c-eaee-11eb-942c-00155d41f2fb", "vals": "{\"title\":\"pippo\"}", "custom": {}, "notify": true, "regions": [], "keywords": [], "xml_file": null, "metadata_uploaded": false }, "output_params": { "output": { "uuid": "ee11541c-eaee-11eb-942c-00155d41f2fb" } } } Sample Request with more parameters: 1. curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'vals={"title":"pippo"}' -d 'metadata_uploaded=true' -d 'keywords=["k1", "k2", "k3"]' http://localhost:8000/api/v2/resources/<id>/update """ config = Configuration.load() resource = self.get_object() if config.read_only or config.maintenance or request.user.is_anonymous or not request.user.is_authenticated or \ resource is None or not request.user.has_perm('change_resourcebase', resource.get_self_resource()): return Response(status=status.HTTP_403_FORBIDDEN) try: request_params = QueryDict(request.body, mutable=True) _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='update', input_params={ "uuid": request_params.get('uuid', resource.uuid), "xml_file": request_params.get('xml_file', None), "metadata_uploaded": request_params.get('metadata_uploaded', False), "vals": request_params.get('vals', '{}'), "regions": request_params.get('regions', '[]'), "keywords": request_params.get('keywords', '[]'), "custom": request_params.get('custom', '{}'), "notify": request_params.get('notify', True) }) resouce_service_dispatcher.apply_async((_exec_request.exec_id, )) return Response( { 'status': _exec_request.status, 'execution_id': _exec_request.exec_id, 'status_url': urljoin( settings.SITEURL, reverse('rs-execution-status', kwargs={'execution_id': _exec_request.exec_id })) }, status=status.HTTP_200_OK) except Exception as e: logger.exception(e) return Response(status=status.HTTP_400_BAD_REQUEST, exception=e)
def resource_service_delete(self, request, pk=None): """Instructs the Async dispatcher to execute a 'DELETE' operation over a valid 'uuid' - DELETE input_params: { id: "<str: ID>" } - output_params: { output: <int: number of resources deleted / 0 if none> } - output: { "status": "ready", "execution_id": "<str: execution ID>", "status_url": "http://localhost:8000/api/v2/resource-service/execution-status/<str: execution ID>" } Sample request: 1. curl -v -X DELETE -u admin:admin http://localhost:8000/api/v2/resources/<id>/delete OUTPUT: { "status":"ready", "execution_id":"7ed0b141-cf85-434f-bbfb-c02447a5221b", "status_url":"http://localhost:8000/api/v2/resource-service/execution-status/7ed0b141-cf85-434f-bbfb-c02447a5221b" } 2. curl -v -X GET -u admin:admin http://localhost:8000/api/v2/resource-service/execution-status/7ed0b141-cf85-434f-bbfb-c02447a5221b OUTPUT: { "user":"******", "status":"finished", "func_name":"delete", "created":"2021-07-19T14:09:59.930619Z", "finished":"2021-07-19T14:10:00.054915Z", "last_updated":"2021-07-19T14:09:59.930647Z", "input_params":{"uuid":"1234"}, "output_params":{"output":0} } """ config = Configuration.load() resource = self.get_object() if config.read_only or config.maintenance or request.user.is_anonymous or not request.user.is_authenticated or \ resource is None or not request.user.has_perm('delete_resourcebase', resource.get_self_resource()): return Response(status=status.HTTP_403_FORBIDDEN) try: _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='delete', input_params={"uuid": resource.uuid}) resouce_service_dispatcher.apply_async((_exec_request.exec_id, )) return Response( { 'status': _exec_request.status, 'execution_id': _exec_request.exec_id, 'status_url': urljoin( settings.SITEURL, reverse('rs-execution-status', kwargs={'execution_id': _exec_request.exec_id })) }, status=status.HTTP_200_OK) except Exception as e: logger.exception(e) return Response(status=status.HTTP_400_BAD_REQUEST, exception=e)
def setUp(self): super(LayerTests, self).setUp() self.user = '******' self.passwd = 'admin' create_layer_data() self.config = Configuration.load()
def setUp(self): super().setUp() # make sure Configuration exists in the database for Read Only mode tests Configuration.load()
def resource_urls(request): """Global values to pass to templates""" site = Site.objects.get_current() thesaurus = Thesaurus.objects.filter(facet=True).all() if hasattr(settings, 'THESAURUS'): warnings.warn( 'Thesaurus settings is going to be' 'deprecated in the future versions, please move the settings to ' 'the new configuration ', FutureWarning) defaults = dict( STATIC_URL=settings.STATIC_URL, CATALOGUE_BASE_URL=default_catalogue_backend()['URL'], ACCOUNT_OPEN_SIGNUP=settings.ACCOUNT_OPEN_SIGNUP, ACCOUNT_APPROVAL_REQUIRED=settings.ACCOUNT_APPROVAL_REQUIRED, VERSION=get_version(), SITE_NAME=site.name, SITE_DOMAIN=site.domain, SITEURL=settings.SITEURL, INSTALLED_APPS=settings.INSTALLED_APPS, THEME_ACCOUNT_CONTACT_EMAIL=settings.THEME_ACCOUNT_CONTACT_EMAIL, TINYMCE_DEFAULT_CONFIG=settings.TINYMCE_DEFAULT_CONFIG, DEBUG_STATIC=getattr( settings, "DEBUG_STATIC", False), PROXY_URL=getattr( settings, 'PROXY_URL', '/proxy/?url='), DISPLAY_SOCIAL=getattr( settings, 'DISPLAY_SOCIAL', False), DISPLAY_COMMENTS=getattr( settings, 'DISPLAY_COMMENTS', False), DISPLAY_RATINGS=getattr( settings, 'DISPLAY_RATINGS', False), DISPLAY_WMS_LINKS=getattr( settings, 'DISPLAY_WMS_LINKS', True), CREATE_LAYER=getattr( settings, 'CREATE_LAYER', True), TWITTER_CARD=getattr( settings, 'TWITTER_CARD', False), TWITTER_SITE=getattr( settings, 'TWITTER_SITE', '@GeoNode'), TWITTER_HASHTAGS=getattr( settings, 'TWITTER_HASHTAGS', []), OPENGRAPH_ENABLED=getattr( settings, 'OPENGRAPH_ENABLED', False), ADMIN_MODERATE_UPLOADS=getattr( settings, 'ADMIN_MODERATE_UPLOADS', False), TOPICCATEGORY_MANDATORY=getattr( settings, 'TOPICCATEGORY_MANDATORY', False), GROUP_MANDATORY_RESOURCES=getattr( settings, 'GROUP_MANDATORY_RESOURCES', False), GROUP_PRIVATE_RESOURCES=getattr( settings, 'GROUP_PRIVATE_RESOURCES', False), RESOURCE_PUBLISHING=getattr( settings, 'RESOURCE_PUBLISHING', False), HAYSTACK_SEARCH=getattr( settings, 'HAYSTACK_SEARCH', False), SKIP_PERMS_FILTER=getattr( settings, 'SKIP_PERMS_FILTER', False), HAYSTACK_FACET_COUNTS=getattr( settings, 'HAYSTACK_FACET_COUNTS', False), CLIENT_RESULTS_LIMIT=getattr( settings, 'CLIENT_RESULTS_LIMIT', 10), API_LIMIT_PER_PAGE=getattr( settings, 'API_LIMIT_PER_PAGE', 20), SRID_DETAIL=getattr( settings, 'SRID', dict()).get( 'DETAIL', 'never'), LICENSES_ENABLED=getattr( settings, 'LICENSES', dict()).get( 'ENABLED', False), LICENSES_DETAIL=getattr( settings, 'LICENSES', dict()).get( 'DETAIL', 'never'), LICENSES_METADATA=getattr( settings, 'LICENSES', dict()).get( 'METADATA', 'never'), USE_GEOSERVER=getattr(settings, 'USE_GEOSERVER', False), USE_NOTIFICATIONS=has_notifications, USE_MONITORING='geonode.monitoring' in settings.INSTALLED_APPS and settings.MONITORING_ENABLED, DEFAULT_ANONYMOUS_VIEW_PERMISSION=getattr(settings, 'DEFAULT_ANONYMOUS_VIEW_PERMISSION', False), DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=getattr(settings, 'DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION', False), EXIF_ENABLED=getattr( settings, "EXIF_ENABLED", False), FAVORITE_ENABLED=getattr( settings, "FAVORITE_ENABLED", False), SEARCH_FILTERS=getattr( settings, 'SEARCH_FILTERS', False ), THESAURI_FILTERS=[t['name'] for t in [settings.THESAURUS, ] if t.get('filter')] if hasattr(settings, 'THESAURUS') else [t.identifier for t in thesaurus], MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS=getattr( settings, 'MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS', False ), SHOW_PROFILE_EMAIL=getattr( settings, "SHOW_PROFILE_EMAIL", False ), OGC_SERVER=getattr(settings, 'OGC_SERVER', None), DELAYED_SECURITY_SIGNALS=getattr(settings, 'DELAYED_SECURITY_SIGNALS', False), READ_ONLY_MODE=getattr(Configuration.load(), 'read_only', False), # GeoNode Apps GEONODE_APPS_ENABLE=getattr(settings, 'GEONODE_APPS_ENABLE', False), GEONODE_APPS_NAME=getattr(settings, 'GEONODE_APPS_NAME', 'Apps'), GEONODE_APPS_NAV_MENU_ENABLE=getattr(settings, 'GEONODE_APPS_NAV_MENU_ENABLE', False), CATALOG_METADATA_TEMPLATE=getattr(settings, "CATALOG_METADATA_TEMPLATE", "catalogue/full_metadata.xml"), UI_REQUIRED_FIELDS=getattr(settings, "UI_REQUIRED_FIELDS", []) ) return defaults
def get_user_menu(context): user = context.get('request').user if not user.is_authenticated: return [ { "label": "Register", "type": "link", "href": "/account/signup/?next=/" } if settings.ACCOUNT_OPEN_SIGNUP and not Configuration.load().read_only else None, { "label": "Sign in", "type": "link", "href": "/account/login/?next=/" }, ] devider = {"type": "divider"} profile = { # get src of user avatar "image": avatar_url(user), "type": "dropdown", "className": "gn-user-menu-dropdown", "items": [ { "type": "link", # get href of user profile "href": user.get_absolute_url(), "label": "Profile" }, { "type": "link", "href": "/social/recent-activity", "label": "Recent activity" }, { "type": "link", "href": "/catalogue/#/search/?f=favorite", "label": "Favorites" }, { "type": "link", "href": "/messages/inbox/", "label": "Inbox" }, devider, ] } general = [{ "type": "link", "href": "/help/", "label": "Help" }, devider, { "type": "link", "href": "/account/logout/?next=/", "label": "Log out" }] admin_only = [ { "type": "link", "href": "/admin/", "label": "Admin" }, { "type": "link", "href": "/geoserver/", "label": "GeoServer" }, devider, { "type": "link", "href": "/monitoring/", "label": "Monitoring & Analytics" }, devider, ] + general if user.is_superuser: profile['items'].extend(admin_only) else: profile['items'].extend(general) return [profile]
def resource_service_permissions(self, request, pk=None): """Instructs the Async dispatcher to execute a 'DELETE' or 'UPDATE' on the permissions of a valid 'uuid' - GET input_params: { id: "<str: ID>" } - DELETE input_params: { id: "<str: ID>" } - PUT input_params: { id: "<str: ID>" owner: str = None permissions: dict = {} created: bool = False } - output_params: { output: { uuid: "<str: UUID>" } } - output: { "status": "ready", "execution_id": "<str: execution ID>", "status_url": "http://localhost:8000/api/v2/resource-service/execution-status/<str: execution ID>" } Sample Requests: - Removes all the permissions (except owner and admin ones) from a Resource: curl -v -X DELETE -u admin:admin -H "Content-Type: application/json" http://localhost:8000/api/v2/resources/<id>/permissions - Changes the owner of a Resource: curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'owner=afabiani' http://localhost:8000/api/v2/resources/<id>/permissions - Assigns View permissions to some users: curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'permissions={"users": {"admin": ["view_resourcebase"]}, "groups": {}}' http://localhost:8000/api/v2/resources/<id>/permissions curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'owner=afabiani' -d 'permissions={"users": {"admin": ["view_resourcebase"]}, "groups": {}}' http://localhost:8000/api/v2/resources/<id>/permissions - Assigns View permissions to anyone: curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'permissions={"users": {"AnonymousUser": ["view_resourcebase"]}, "groups": []}' http://localhost:8000/api/v2/resources/<id>/permissions - Assigns View permissions to anyone and edit (style and data) permissions to a Group on a Dataset: curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'permissions={"users": {"AnonymousUser": ["view_resourcebase"]}, "groups": {"registered-members": ["view_resourcebase", "download_resourcebase", "change_dataset_style", "change_dataset_data"]}}' http://localhost:8000/api/v2/resources/<id>/permissions - Assigns View permissions to anyone and edit permissions to a Group on a Document: curl -v -X PUT -u admin:admin -H "Content-Type: application/json" -d 'permissions={"users": {"AnonymousUser": ["view_resourcebase"]}, "groups": {"registered-members": ["view_resourcebase", "download_resourcebase", "change_resourcebase"]}}' http://localhost:8000/api/v2/resources/<id>/permissions """ config = Configuration.load() resource = self.get_object() if config.read_only or config.maintenance or request.user.is_anonymous or not request.user.is_authenticated or \ resource is None or not request.user.has_perm('change_resourcebase', resource.get_self_resource()): return Response(status=status.HTTP_403_FORBIDDEN) try: perms_spec = PermSpec(resource.get_all_level_info(), resource) request_body = request.body request_params = QueryDict(request_body, mutable=True, encoding="UTF-8") if request.method == 'GET': return Response(perms_spec.compact) elif request.method == 'DELETE': _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='remove_permissions', input_params={ "uuid": request_params.get('uuid', resource.uuid) }) elif request.method == 'PUT': perms_spec_compact = PermSpecCompact( json.loads(request_params.get('permissions', '{}')), resource) _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='set_permissions', input_params={ "uuid": request_params.get('uuid', resource.uuid), "owner": request_params.get('owner', resource.owner.username), "permissions": perms_spec_compact.extended, "created": request_params.get('created', False) }) elif request.method == 'PATCH': perms_spec_compact_patch = PermSpecCompact( json.loads(request_params.get('permissions', '{}')), resource) perms_spec_compact_resource = PermSpecCompact( perms_spec.compact, resource) perms_spec_compact_resource.merge(perms_spec_compact_patch) _exec_request = ExecutionRequest.objects.create( user=request.user, func_name='set_permissions', input_params={ "uuid": request_params.get('uuid', resource.uuid), "owner": request_params.get('owner', resource.owner.username), "permissions": perms_spec_compact_resource.extended, "created": request_params.get('created', False) }) resouce_service_dispatcher.apply_async((_exec_request.exec_id, )) return Response( { 'status': _exec_request.status, 'execution_id': _exec_request.exec_id, 'status_url': urljoin( settings.SITEURL, reverse('rs-execution-status', kwargs={'execution_id': _exec_request.exec_id })) }, status=status.HTTP_200_OK) except Exception as e: logger.exception(e) return Response(status=status.HTTP_400_BAD_REQUEST, exception=e)