def dataset_metadata_detail(request, layername, template='datasets/dataset_metadata_detail.html'): try: layer = _resolve_dataset(request, layername, 'view_resourcebase', _PERMISSION_MSG_METADATA) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not layer: raise Http404(_("Not found")) group = None if layer.group: try: group = GroupProfile.objects.get(slug=layer.group.name) except GroupProfile.DoesNotExist: group = None site_url = settings.SITEURL.rstrip('/') if settings.SITEURL.startswith( 'http') else settings.SITEURL register_event(request, 'view_metadata', layer) perms_list = list(layer.get_self_resource().get_user_perms( request.user).union(layer.get_user_perms(request.user))) return render(request, template, context={ "resource": layer, "perms_list": perms_list, "group": group, 'SITEURL': site_url })
def map_metadata_detail(request, mapid, template="maps/map_metadata_detail.html"): try: map_obj = _resolve_map(request, mapid, "view_resourcebase") except PermissionDenied: return HttpResponse(MSG_NOT_ALLOWED, status=403) except Exception: raise Http404(MSG_NOT_FOUND) if not map_obj: raise Http404(MSG_NOT_FOUND) group = None if map_obj.group: try: group = GroupProfile.objects.get(slug=map_obj.group.name) except GroupProfile.DoesNotExist: group = None site_url = settings.SITEURL.rstrip("/") if settings.SITEURL.startswith( "http") else settings.SITEURL register_event(request, EventType.EVENT_VIEW_METADATA, map_obj) return render(request, template, context={ "resource": map_obj, "group": group, "SITEURL": site_url })
def dataset_feature_catalogue( request, layername, template='../../catalogue/templates/catalogue/feature_catalogue.xml'): try: layer = _resolve_dataset(request, layername) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not layer: raise Http404(_("Not found")) if layer.subtype != 'vector': out = {'success': False, 'errors': 'layer is not a feature type'} return HttpResponse(json.dumps(out), content_type='application/json', status=400) attributes = [] for attrset in layer.attribute_set.order_by('display_order'): attr = {'name': attrset.attribute, 'type': attrset.attribute_type} attributes.append(attr) context_dict = { 'dataset': layer, 'attributes': attributes, 'metadata': settings.PYCSW['CONFIGURATION']['metadata:main'] } register_event(request, 'view', layer) return render(request, template, context=context_dict, content_type='application/xml')
def document_remove(request): docid = request.POST['docid'] try: document = _resolve_document( request, docid, 'base.delete_resourcebase', _PERMISSION_MSG_DELETE) logger.debug(f'Deleting Document {document}') document.delete() out = {'success': True} out['status_code'] = 200 register_event(request, EventType.EVENT_REMOVE, document) except PermissionDenied: out = {'success': False} out['status_code'] = 403 except Exception: traceback.print_exc() message = f'{_("Unable to delete document")}: {document.title}.' out = {'success': False} out['status_code'] = 500 out['message'] = message return render(request, 'documents/document_list.html')
def form_valid(self, form): """ If the form is valid, save the associated model. """ doc_form = form.cleaned_data file = doc_form.pop('doc_file', None) if file: tempdir = tempfile.mkdtemp(dir=settings.STATIC_ROOT) dirname = os.path.basename(tempdir) filepath = storage_manager.save(f"{dirname}/{file.name}", file) storage_path = storage_manager.path(filepath) self.object = resource_manager.update( self.object.uuid, instance=self.object, vals=dict( owner=self.request.user, files=[storage_path]) ) if tempdir != os.path.dirname(storage_path): shutil.rmtree(tempdir, ignore_errors=True) register_event(self.request, EventType.EVENT_CHANGE, self.object) url = hookset.document_detail_url(self.object) return HttpResponseRedirect(url)
def dataset_detail(request, layername, template='datasets/dataset_detail.html'): try: layer = _resolve_dataset(request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not layer: raise Http404(_("Not found")) # Update count for popularity ranking, # but do not includes admins or resource owners layer.view_count_up(request.user) access_token = None if request and request.user: access_token = get_or_create_token(request.user) if access_token and not access_token.is_expired(): access_token = access_token.token else: access_token = None context_dict = { 'access_token': access_token, 'resource': layer, } register_event(request, 'view', layer) return TemplateResponse(request, template, context=context_dict)
def document_metadata_detail(request, docid, template='documents/document_metadata_detail.html' ): try: document = _resolve_document(request, docid, 'view_resourcebase', _PERMISSION_MSG_METADATA) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not document: raise Http404(_("Not found")) group = None if document.group: try: group = GroupProfile.objects.get(slug=document.group.name) except ObjectDoesNotExist: group = None site_url = settings.SITEURL.rstrip('/') if settings.SITEURL.startswith( 'http') else settings.SITEURL register_event(request, EventType.EVENT_VIEW_METADATA, document) return render(request, template, context={ "resource": document, "group": group, 'SITEURL': site_url })
def get_download_response(request, docid, attachment=False): """ Returns a download response if user has access to download the document of a given id, and an http response if they have no permissions to download it. """ document = get_object_or_404(Document, pk=docid) if not request.user.has_perm('base.download_resourcebase', obj=document.get_self_resource()): return HttpResponse(loader.render_to_string( '401.html', context={ 'error_message': _("You are not allowed to view this document.") }, request=request), status=401) if attachment: register_event(request, EventType.EVENT_DOWNLOAD, document) filename = slugify(os.path.splitext(os.path.basename(document.title))[0]) if document.files and storage_manager.exists(document.files[0]): return DownloadResponse(storage_manager.open(document.files[0]).file, basename=f'{filename}.{document.extension}', attachment=attachment) return HttpResponse("File is not available", status=404)
def map_json_handle_put(request, mapid): if not request.user.is_authenticated: return HttpResponse(_PERMISSION_MSG_LOGIN, status=401, content_type="text/plain") map_obj = Map.objects.get(id=mapid) if not request.user.has_perm('change_resourcebase', map_obj.get_self_resource()): return HttpResponse(_PERMISSION_MSG_SAVE, status=401, content_type="text/plain") try: map_obj.update_from_viewer(request.body, context={ 'request': request, 'mapId': mapid, 'map': map_obj }) register_event(request, EventType.EVENT_CHANGE, map_obj) return HttpResponse(json.dumps(map_obj.viewer_json(request))) except ValueError as e: return HttpResponse( f"The server could not understand the request.{str(e)}", content_type="text/plain", status=400)
def map_metadata_detail(request, mapid, template='maps/map_metadata_detail.html'): try: map_obj = _resolve_map(request, mapid, 'view_resourcebase') except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not map_obj: raise Http404(_("Not found")) group = None if map_obj.group: try: group = GroupProfile.objects.get(slug=map_obj.group.name) except GroupProfile.DoesNotExist: group = None site_url = settings.SITEURL.rstrip('/') if settings.SITEURL.startswith( 'http') else settings.SITEURL register_event(request, EventType.EVENT_VIEW_METADATA, map_obj) return render(request, template, context={ "resource": map_obj, "group": group, 'SITEURL': site_url })
def map_embed(request, mapid=None, template='maps/map_embed.html'): try: map_obj = _resolve_map(request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(MSG_NOT_ALLOWED, status=403) except Exception: raise Http404(MSG_NOT_FOUND) if not map_obj: raise Http404(MSG_NOT_FOUND) access_token = None if request and request.user: access_token = get_or_create_token(request.user) if access_token and not access_token.is_expired(): access_token = access_token.token else: access_token = None context_dict = { 'access_token': access_token, 'resource': map_obj, } register_event(request, EventType.EVENT_VIEW, map_obj) return render(request, template, context=context_dict)
def map_remove(request, mapid, template='maps/map_remove.html'): ''' Delete a map, and its constituent layers. ''' try: map_obj = _resolve_map( request, mapid, 'base.delete_resourcebase', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not map_obj: raise Http404(_("Not found")) if request.method == 'GET': return render(request, template, context={ "map": map_obj }) elif request.method == 'POST': resource_manager.delete(map_obj.uuid, instance=map_obj) register_event(request, EventType.EVENT_REMOVE, map_obj) return HttpResponseRedirect(reverse("maps_browse"))
def map_embed(request, mapid=None, template='maps/map_embed.html'): if mapid is None: config = default_map_config(request)[0] else: map_obj = _resolve_map(request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) config = map_obj.viewer_json(request) register_event(request, EventType.EVENT_VIEW, map_obj) return render(request, template, context={'config': json.dumps(config)})
def form_valid(self, form): """ If the form is valid, save the associated model. """ self.object = form.save() register_event(self.request, EventType.EVENT_CHANGE, self.object) return HttpResponseRedirect( reverse( 'document_detail', args=( self.object.id, )))
def form_valid(self, form): """ If the form is valid, save the associated model. """ self.object = resource_manager.replace( self.object, vals={ 'files': form.cleaned_data.get('doc_file'), 'doc_url': form.cleaned_data.get('doc_url'), 'user': self.request.user }) url = hookset.document_detail_url(self.object) register_event(self.request, EventType.EVENT_CHANGE, self.object) return HttpResponseRedirect(url)
def new_map_json(request): if request.method == 'GET': map_obj, config = new_map_config(request) if isinstance(config, HttpResponse): return config else: return HttpResponse(config) elif request.method == 'POST': if not request.user.is_authenticated: return HttpResponse('You must be logged in to save new maps', content_type="text/plain", status=401) map_obj = resource_manager.create(None, resource_type=Map, defaults=dict(zoom=0, center_x=0, center_y=0, owner=request.user)) resource_manager.set_permissions(None, instance=map_obj, permissions=None, created=True) # If the body has been read already, use an empty string. # See https://github.com/django/django/commit/58d555caf527d6f1bdfeab14527484e4cca68648 # for a better exception to catch when we move to Django 1.7. try: body = request.body except Exception: body = '' try: map_obj.update_from_viewer(body, context={ 'request': request, 'mapId': map_obj.id, 'map': map_obj }) except ValueError as e: return HttpResponse(str(e), status=400) else: register_event(request, EventType.EVENT_UPLOAD, map_obj) return HttpResponse(json.dumps({'id': map_obj.id}), status=200, content_type='application/json') else: return HttpResponse(status=405)
def map_wms(request, mapid): """ Publish local map layers as group layer in local OWS. /maps/:id/wms GET: return endpoint information for group layer, PUT: update existing or create new group layer. """ try: map_obj = _resolve_map( request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not map_obj: raise Http404(_("Not found")) if request.method == 'PUT': try: layerGroupName = map_obj.publish_dataset_group() response = dict( layerGroupName=layerGroupName, ows=getattr(ogc_server_settings, 'ows', ''), ) register_event(request, EventType.EVENT_PUBLISH, map_obj) return HttpResponse( json.dumps(response), content_type="application/json") except Exception: return HttpResponseServerError() if request.method == 'GET': response = dict( layerGroupName=getattr(map_obj.dataset_group, 'name', ''), ows=getattr(ogc_server_settings, 'ows', ''), ) return HttpResponse( json.dumps(response), content_type="application/json") return HttpResponseNotAllowed(['PUT', 'GET'])
def _post_change_routines(self, instance: Map, create_action_perfomed: bool, additional_data: dict): # Step 1: Handle Maplayers signals if this is and update action if not create_action_perfomed: dataset_names_before_changes = additional_data.pop( "dataset_names_before_changes", []) dataset_names_after_changes = [ lyr.alternate for lyr in instance.datasets ] if dataset_names_before_changes != dataset_names_after_changes: map_changed_signal.send_robust(sender=instance, what_changed="datasets") # Step 2: Register Event event_type = EventType.EVENT_CREATE if create_action_perfomed else EventType.EVENT_CHANGE register_event(self.request, event_type, instance) # Step 3: Resource Manager resource_manager.update(instance.uuid, instance=instance, notify=True)
def geoapp_remove(request, geoappid, template='apps/app_remove.html'): try: geoapp_obj = _resolve_geoapp(request, geoappid, 'base.delete_resourcebase', _PERMISSION_MSG_DELETE) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not geoapp_obj: raise Http404(_("Not found")) if request.method == 'GET': return render(request, template, context={"resource": geoapp_obj}) elif request.method == 'POST': resource_manager.delete(geoapp_obj.uuid, instance=geoapp_obj) register_event(request, EventType.EVENT_REMOVE, geoapp_obj) return HttpResponseRedirect(reverse("apps_browse")) else: return HttpResponse("Not allowed", status=403)
def document_remove(request, docid, template='documents/document_remove.html'): try: document = _resolve_document(request, docid, 'base.delete_resourcebase', _PERMISSION_MSG_DELETE) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not document: raise Http404(_("Not found")) if request.method == 'GET': return render(request, template, context={"document": document}) if request.method == 'POST': resource_manager.delete(document.uuid, instance=document) register_event(request, EventType.EVENT_REMOVE, document) return HttpResponseRedirect(reverse("document_browse")) else: return HttpResponse(_("Not allowed"), status=403)
def map_view(request, mapid, dataset_name=None, template='maps/map_view.html'): """ The view that returns the map composer opened to the map with the given map ID. """ try: map_obj = _resolve_map( request, mapid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not map_obj: raise Http404(_("Not found")) config = map_obj.viewer_json(request) perms_list = list( map_obj.get_self_resource().get_user_perms(request.user) .union(map_obj.get_user_perms(request.user)) ) if dataset_name: config = add_datasets_to_map_config( request, map_obj, (dataset_name, ), False) register_event(request, EventType.EVENT_VIEW, request.path) return render(request, template, context={ 'config': json.dumps(config), 'map': map_obj, 'perms_list': perms_list, 'preview': getattr( settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'mapstore') })
def resource_clone(request): try: uuid = request.POST['uuid'] resource = resolve_object( request, ResourceBase, { 'uuid': uuid}, 'base.change_resourcebase') except PermissionDenied: return HttpResponse("Not allowed", status=403) except Exception: raise Http404("Not found") if not resource: raise Http404("Not found") out = {} try: getattr(resource_manager, "copy")( resource.get_real_instance(), uuid=None, defaults={ 'user': request.user}) out['success'] = True out['message'] = _("Resource Cloned Successfully!") except Exception as e: logger.exception(e) out['success'] = False out['message'] = _(f"Error Occurred while Cloning the Resource: {e}") out['errors'] = str(e) if out['success']: status_code = 200 register_event(request, 'change', resource) else: status_code = 400 return HttpResponse( json.dumps(out), content_type='application/json', status=status_code)
def map_download(request, mapid, template="maps/map_download.html"): """ Download all the layers of a map as a batch XXX To do, remove layer status once progress id done This should be fix because """ try: map_obj = _resolve_map(request, mapid, "base.download_resourcebase", _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(MSG_NOT_ALLOWED, status=403) except Exception: raise Http404(MSG_NOT_FOUND) if not map_obj: raise Http404(MSG_NOT_FOUND) map_status = dict() if request.method == "POST": def perm_filter(layer): return request.user.has_perm("base.view_resourcebase", obj=layer.get_self_resource()) mapJson = map_obj.json(perm_filter) # we need to remove duplicate layers j_map = json.loads(mapJson) j_datasets = j_map["layers"] for j_dataset in j_datasets: if j_dataset["service"] is None: j_datasets.remove(j_dataset) continue if (len([_l for _l in j_datasets if _l == j_dataset])) > 1: j_datasets.remove(j_dataset) mapJson = json.dumps(j_map) # the path to geoserver backend continue here url = urljoin(settings.SITEURL, reverse("download-map", kwargs={"mapid": mapid})) resp, content = http_client.request(url, "POST", data=mapJson) status = int(resp.status_code) if status == 200: map_status = json.loads(content) request.session["map_status"] = map_status else: raise Exception( f"Could not start the download of {map_obj.title}. Error was: {content}" ) locked_datasets = [] remote_datasets = [] downloadable_datasets = [] for lyr in map_obj.maplayers.iterator(): if lyr.group != "background": if not lyr.local: remote_datasets.append(lyr) else: ownable_dataset = Dataset.objects.get(alternate=lyr.name) if not request.user.has_perm( "download_resourcebase", obj=ownable_dataset.get_self_resource()): locked_datasets.append(lyr) else: # we need to add the layer only once if len([ _l for _l in downloadable_datasets if _l.name == lyr.name ]) == 0: downloadable_datasets.append(lyr) site_url = settings.SITEURL.rstrip("/") if settings.SITEURL.startswith( "http") else settings.SITEURL register_event(request, EventType.EVENT_DOWNLOAD, map_obj) return render( request, template, context={ "geoserver": ogc_server_settings.PUBLIC_LOCATION, "map_status": map_status, "map": map_obj, "locked_datasets": locked_datasets, "remote_datasets": remote_datasets, "downloadable_datasets": downloadable_datasets, "site": site_url, }, )
def document_metadata(request, docid, template='documents/document_metadata.html', ajax=True): document = None try: document = _resolve_document(request, docid, 'base.change_resourcebase_metadata', _PERMISSION_MSG_METADATA) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not document: raise Http404(_("Not found")) # Add metadata_author or poc if missing document.add_missing_metadata_author_or_poc() poc = document.poc metadata_author = document.metadata_author topic_category = document.category current_keywords = [keyword.name for keyword in document.keywords.all()] if request.method == "POST": document_form = DocumentForm(request.POST, instance=document, prefix="resource") category_form = CategoryForm( request.POST, prefix="category_choice_field", initial=int(request.POST["category_choice_field"]) if "category_choice_field" in request.POST and request.POST["category_choice_field"] else None) if hasattr(settings, 'THESAURUS'): tkeywords_form = TKeywordForm(request.POST) else: tkeywords_form = ThesaurusAvailableForm(request.POST, prefix='tkeywords') else: document_form = DocumentForm(instance=document, prefix="resource") document_form.disable_keywords_widget_for_non_superuser(request.user) category_form = CategoryForm( prefix="category_choice_field", initial=topic_category.id if topic_category else None) # Keywords from THESAURUS management doc_tkeywords = document.tkeywords.all() if hasattr(settings, 'THESAURUS') and settings.THESAURUS: warnings.warn( 'The settings for Thesaurus has been moved to Model, \ this feature will be removed in next releases', DeprecationWarning) tkeywords_list = '' lang = 'en' # TODO: use user's language if doc_tkeywords and len(doc_tkeywords) > 0: tkeywords_ids = doc_tkeywords.values_list('id', flat=True) if hasattr(settings, 'THESAURUS') and settings.THESAURUS: el = settings.THESAURUS thesaurus_name = el['name'] try: t = Thesaurus.objects.get(identifier=thesaurus_name) for tk in t.thesaurus.filter(pk__in=tkeywords_ids): tkl = tk.keyword.filter(lang=lang) if len(tkl) > 0: tkl_ids = ",".join( map(str, tkl.values_list('id', flat=True))) tkeywords_list += f",{tkl_ids}" if len( tkeywords_list) > 0 else tkl_ids except Exception: tb = traceback.format_exc() logger.error(tb) tkeywords_form = TKeywordForm(instance=document) else: tkeywords_form = ThesaurusAvailableForm(prefix='tkeywords') # set initial values for thesaurus form for tid in tkeywords_form.fields: values = [] values = [ keyword.id for keyword in doc_tkeywords if int(tid) == keyword.thesaurus.id ] tkeywords_form.fields[tid].initial = values if request.method == "POST" and document_form.is_valid( ) and category_form.is_valid() and tkeywords_form.is_valid(): new_poc = document_form.cleaned_data['poc'] new_author = document_form.cleaned_data['metadata_author'] new_keywords = current_keywords if request.keyword_readonly else document_form.cleaned_data[ 'keywords'] new_regions = document_form.cleaned_data['regions'] new_category = None if category_form and 'category_choice_field' in category_form.cleaned_data and \ category_form.cleaned_data['category_choice_field']: new_category = TopicCategory.objects.get( id=int(category_form.cleaned_data['category_choice_field'])) if new_poc is None: if poc is None: poc_form = ProfileForm(request.POST, prefix="poc", instance=poc) else: poc_form = ProfileForm(request.POST, prefix="poc") if poc_form.is_valid(): if len(poc_form.cleaned_data['profile']) == 0: # FIXME use form.add_error in django > 1.7 errors = poc_form._errors.setdefault( 'profile', ErrorList()) errors.append( _('You must set a point of contact for this resource')) if poc_form.has_changed and poc_form.is_valid(): new_poc = poc_form.save() if new_author is None: if metadata_author is None: author_form = ProfileForm(request.POST, prefix="author", instance=metadata_author) else: author_form = ProfileForm(request.POST, prefix="author") if author_form.is_valid(): if len(author_form.cleaned_data['profile']) == 0: # FIXME use form.add_error in django > 1.7 errors = author_form._errors.setdefault( 'profile', ErrorList()) errors.append( _('You must set an author for this resource')) if author_form.has_changed and author_form.is_valid(): new_author = author_form.save() document = document_form.instance resource_manager.update(document.uuid, instance=document, keywords=new_keywords, regions=new_regions, vals=dict(poc=new_poc or document.poc, metadata_author=new_author or document.metadata_author, category=new_category), notify=True) resource_manager.set_thumbnail(document.uuid, instance=document, overwrite=False) document_form.save_many2many() register_event(request, EventType.EVENT_CHANGE_METADATA, document) url = hookset.document_detail_url(document) if not ajax: return HttpResponseRedirect(url) message = document.id try: # Keywords from THESAURUS management # Rewritten to work with updated autocomplete if not tkeywords_form.is_valid(): return HttpResponse( json.dumps({'message': "Invalid thesaurus keywords"}, status_code=400)) thesaurus_setting = getattr(settings, 'THESAURUS', None) if thesaurus_setting: tkeywords_data = tkeywords_form.cleaned_data['tkeywords'] tkeywords_data = tkeywords_data.filter( thesaurus__identifier=thesaurus_setting['name']) document.tkeywords.set(tkeywords_data) elif Thesaurus.objects.all().exists(): fields = tkeywords_form.cleaned_data document.tkeywords.set(tkeywords_form.cleanx(fields)) except Exception: tb = traceback.format_exc() logger.error(tb) return HttpResponse(json.dumps({'message': message})) # - POST Request Ends here - # Request.GET if poc is not None: document_form.fields['poc'].initial = poc.id poc_form = ProfileForm(prefix="poc") poc_form.hidden = True if metadata_author is not None: document_form.fields['metadata_author'].initial = metadata_author.id author_form = ProfileForm(prefix="author") author_form.hidden = True metadata_author_groups = get_user_visible_groups(request.user) if settings.ADMIN_MODERATE_UPLOADS: if not request.user.is_superuser: can_change_metadata = request.user.has_perm( 'change_resourcebase_metadata', document.get_self_resource()) try: is_manager = request.user.groupmember_set.all().filter( role='manager').exists() except Exception: is_manager = False if not is_manager or not can_change_metadata: if settings.RESOURCE_PUBLISHING: document_form.fields['is_published'].widget.attrs.update( {'disabled': 'true'}) document_form.fields['is_approved'].widget.attrs.update( {'disabled': 'true'}) register_event(request, EventType.EVENT_VIEW_METADATA, document) return render( request, template, context={ "resource": document, "document": document, "document_form": document_form, "poc_form": poc_form, "author_form": author_form, "category_form": category_form, "tkeywords_form": tkeywords_form, "metadata_author_groups": metadata_author_groups, "TOPICCATEGORY_MANDATORY": getattr(settings, 'TOPICCATEGORY_MANDATORY', False), "GROUP_MANDATORY_RESOURCES": getattr(settings, 'GROUP_MANDATORY_RESOURCES', False), "UI_MANDATORY_FIELDS": list( set(getattr(settings, 'UI_DEFAULT_MANDATORY_FIELDS', [])) | set(getattr(settings, 'UI_REQUIRED_FIELDS', []))) })
def form_valid(self, form): """ If the form is valid, save the associated model. """ doc_form = form.cleaned_data file = doc_form.pop('doc_file', None) if file: tempdir = tempfile.mkdtemp(dir=settings.STATIC_ROOT) dirname = os.path.basename(tempdir) filepath = storage_manager.save(f"{dirname}/{file.name}", file) storage_path = storage_manager.path(filepath) self.object = resource_manager.create( None, resource_type=Document, defaults=dict(owner=self.request.user, doc_url=doc_form.pop('doc_url', None), title=doc_form.pop('title', file.name), files=[storage_path])) if tempdir != os.path.dirname(storage_path): shutil.rmtree(tempdir, ignore_errors=True) else: self.object = resource_manager.create( None, resource_type=Document, defaults=dict(owner=self.request.user, doc_url=doc_form.pop('doc_url', None), title=doc_form.pop('title', None))) if settings.ADMIN_MODERATE_UPLOADS: self.object.is_approved = False if settings.RESOURCE_PUBLISHING: self.object.is_published = False resource_manager.set_permissions( None, instance=self.object, permissions=form.cleaned_data["permissions"], created=True) abstract = None date = None regions = [] keywords = [] bbox = None url = hookset.document_detail_url(self.object) out = {'success': False} if getattr(settings, 'EXIF_ENABLED', False): try: from geonode.documents.exif.utils import exif_extract_metadata_doc exif_metadata = exif_extract_metadata_doc(self.object) if exif_metadata: date = exif_metadata.get('date', None) keywords.extend(exif_metadata.get('keywords', [])) bbox = exif_metadata.get('bbox', None) abstract = exif_metadata.get('abstract', None) except Exception: logger.debug("Exif extraction failed.") resource_manager.update( self.object.uuid, instance=self.object, keywords=keywords, regions=regions, vals=dict(abstract=abstract, date=date, date_type="Creation", bbox_polygon=BBOXHelper.from_xy(bbox).as_polygon() if bbox else None), notify=True) resource_manager.set_thumbnail(self.object.uuid, instance=self.object, overwrite=False) register_event(self.request, EventType.EVENT_UPLOAD, self.object) if self.request.GET.get('no__redirect', False): out['success'] = True out['url'] = url if out['success']: status_code = 200 else: status_code = 400 return HttpResponse(json.dumps(out), content_type='application/json', status=status_code) else: return HttpResponseRedirect(url)
def download(request, resourceid, sender=Dataset): _not_authorized = _("You are not authorized to download this resource.") _not_permitted = _("You are not permitted to save or edit this resource.") _no_files_found = _( "No files have been found for this resource. Please, contact a system administrator." ) instance = resolve_object(request, sender, {'pk': resourceid}, permission='base.download_resourcebase', permission_msg=_not_permitted) if isinstance(instance, ResourceBase): dataset_files = [] file_list = [] # Store file info to be returned try: files = instance.resourcebase_ptr.files # Copy all Dataset related files into a temporary folder for file_path in files: if storage_manager.exists(file_path): dataset_files.append(file_path) filename = os.path.basename(file_path) file_list.append({ "name": filename, "data_iter": storage_manager.open(file_path), }) else: return HttpResponse(loader.render_to_string( '401.html', context={ 'error_title': _("No files found."), 'error_message': _no_files_found }, request=request), status=404) # Check we can access the original files if not dataset_files: return HttpResponse(loader.render_to_string( '401.html', context={ 'error_title': _("No files found."), 'error_message': _no_files_found }, request=request), status=404) # ZIP everything and return target_file_name = "".join([instance.name, ".zip"]) target_zip = zipstream.ZipFile(mode='w', compression=zipstream.ZIP_DEFLATED, allowZip64=True) # Iterable: Needed when the file_info has it's data as a stream def _iterable(source_iter): while True: buf = source_iter.read(BUFFER_CHUNK_SIZE) if not buf: break yield buf # Add files to zip for file_info in file_list: target_zip.write_iter(arcname=file_info['name'], iterable=_iterable( file_info['data_iter'])) register_event(request, 'download', instance) # Streaming content response response = StreamingHttpResponse(target_zip, content_type='application/zip') response[ 'Content-Disposition'] = f'attachment; filename="{target_file_name}"' return response except (NotImplementedError, Upload.DoesNotExist): traceback.print_exc() tb = traceback.format_exc() logger.debug(tb) return HttpResponse(loader.render_to_string( '401.html', context={ 'error_title': _("No files found."), 'error_message': _no_files_found }, request=request), status=404) return HttpResponse(loader.render_to_string('401.html', context={ 'error_title': _("Not Authorized"), 'error_message': _not_authorized }, request=request), status=403)
def document_detail(request, docid): """ The view that show details of each document """ try: document = _resolve_document(request, docid, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: raise Http404(_("Not found")) if not document: raise Http404(_("Not found")) permission_manager = ManageResourceOwnerPermissions(document) permission_manager.set_owner_permissions_according_to_workflow() # Add metadata_author or poc if missing document.add_missing_metadata_author_or_poc() related = get_related_resources(document) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != document.owner and not request.user.is_superuser: Document.objects.filter(id=document.id).update( popular_count=F('popular_count') + 1) metadata = document.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) # Call this first in order to be sure "perms_list" is correct permissions_json = _perms_info_json(document) perms_list = list(document.get_self_resource().get_user_perms( request.user).union(document.get_user_perms(request.user))) group = None if document.group: try: group = GroupProfile.objects.get(slug=document.group.name) except ObjectDoesNotExist: group = None access_token = None if request and request.user: access_token = get_or_create_token(request.user) if access_token and not access_token.is_expired(): access_token = access_token.token else: access_token = None AUDIOTYPES = [_e for _e, _t in DOCUMENT_TYPE_MAP.items() if _t == 'audio'] IMGTYPES = [_e for _e, _t in DOCUMENT_TYPE_MAP.items() if _t == 'image'] VIDEOTYPES = [_e for _e, _t in DOCUMENT_TYPE_MAP.items() if _t == 'video'] context_dict = { 'access_token': access_token, 'resource': document, 'perms_list': perms_list, 'permissions_json': permissions_json, 'group': group, 'metadata': metadata, 'audiotypes': AUDIOTYPES, 'imgtypes': IMGTYPES, 'videotypes': VIDEOTYPES, 'mimetypemap': DOCUMENT_MIMETYPE_MAP, 'related': related } if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, document) if getattr(settings, 'EXIF_ENABLED', False): try: from geonode.documents.exif.utils import exif_extract_dict exif = exif_extract_dict(document) if exif: context_dict['exif_data'] = exif except Exception: logger.debug("Exif extraction failed.") if request.user.is_authenticated: if getattr(settings, 'FAVORITE_ENABLED', False): from geonode.favorite.utils import get_favorite_info context_dict["favorite_info"] = get_favorite_info( request.user, document) register_event(request, EventType.EVENT_VIEW, document) return render(request, "documents/document_detail.html", context=context_dict)
def map_metadata(request, mapid, template="maps/map_metadata.html", ajax=True): try: map_obj = _resolve_map(request, mapid, "base.change_resourcebase_metadata", _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse(MSG_NOT_ALLOWED, status=403) except Exception: raise Http404(MSG_NOT_FOUND) if not map_obj: raise Http404(MSG_NOT_FOUND) # Add metadata_author or poc if missing map_obj.add_missing_metadata_author_or_poc() current_keywords = [keyword.name for keyword in map_obj.keywords.all()] poc = map_obj.poc topic_thesaurus = map_obj.tkeywords.all() metadata_author = map_obj.metadata_author topic_category = map_obj.category if request.method == "POST": map_form = MapForm(request.POST, instance=map_obj, prefix="resource", user=request.user) category_form = CategoryForm( request.POST, prefix="category_choice_field", initial=int(request.POST["category_choice_field"]) if "category_choice_field" in request.POST and request.POST["category_choice_field"] else None) if hasattr(settings, 'THESAURUS'): tkeywords_form = TKeywordForm(request.POST) else: tkeywords_form = ThesaurusAvailableForm(request.POST, prefix='tkeywords') else: map_form = MapForm(instance=map_obj, prefix="resource", user=request.user) map_form.disable_keywords_widget_for_non_superuser(request.user) category_form = CategoryForm( prefix="category_choice_field", initial=topic_category.id if topic_category else None) # Keywords from THESAURUS management map_tkeywords = map_obj.tkeywords.all() tkeywords_list = '' # Create THESAURUS widgets lang = 'en' if hasattr(settings, 'THESAURUS') and settings.THESAURUS: warnings.warn( 'The settings for Thesaurus has been moved to Model, \ this feature will be removed in next releases', DeprecationWarning) tkeywords_list = '' if map_tkeywords and len(map_tkeywords) > 0: tkeywords_ids = map_tkeywords.values_list('id', flat=True) if hasattr(settings, 'THESAURUS') and settings.THESAURUS: el = settings.THESAURUS thesaurus_name = el['name'] try: t = Thesaurus.objects.get(identifier=thesaurus_name) for tk in t.thesaurus.filter(pk__in=tkeywords_ids): tkl = tk.keyword.filter(lang=lang) if len(tkl) > 0: tkl_ids = ",".join( map(str, tkl.values_list('id', flat=True))) tkeywords_list += f",{tkl_ids}" if len( tkeywords_list) > 0 else tkl_ids except Exception: tb = traceback.format_exc() logger.error(tb) tkeywords_form = TKeywordForm(instance=map_obj) else: tkeywords_form = ThesaurusAvailableForm(prefix='tkeywords') # set initial values for thesaurus form for tid in tkeywords_form.fields: values = [] values = [ keyword.id for keyword in topic_thesaurus if int(tid) == keyword.thesaurus.id ] tkeywords_form.fields[tid].initial = values if request.method == "POST" and map_form.is_valid( ) and category_form.is_valid() and tkeywords_form.is_valid(): new_poc = map_form.cleaned_data['poc'] new_author = map_form.cleaned_data['metadata_author'] new_keywords = current_keywords if request.keyword_readonly else map_form.cleaned_data[ 'keywords'] new_regions = map_form.cleaned_data['regions'] new_title = map_form.cleaned_data['title'] new_abstract = map_form.cleaned_data['abstract'] new_category = None if category_form and 'category_choice_field' in category_form.cleaned_data and\ category_form.cleaned_data['category_choice_field']: new_category = TopicCategory.objects.get( id=int(category_form.cleaned_data['category_choice_field'])) if new_poc is None: if poc is None: poc_form = ProfileForm(request.POST, prefix="poc", instance=poc) else: poc_form = ProfileForm(request.POST, prefix="poc") if poc_form.has_changed and poc_form.is_valid(): new_poc = poc_form.save() if new_author is None: if metadata_author is None: author_form = ProfileForm(request.POST, prefix="author", instance=metadata_author) else: author_form = ProfileForm(request.POST, prefix="author") if author_form.has_changed and author_form.is_valid(): new_author = author_form.save() if new_poc is not None and new_author is not None: map_obj.poc = new_poc map_obj.metadata_author = new_author map_obj.title = new_title map_obj.abstract = new_abstract map_obj.keywords.clear() map_obj.keywords.add(*new_keywords) map_obj.regions.clear() map_obj.regions.add(*new_regions) map_obj.category = new_category register_event(request, EventType.EVENT_CHANGE_METADATA, map_obj) if not ajax: return HttpResponseRedirect(hookset.map_detail_url(map_obj)) message = map_obj.id try: # Keywords from THESAURUS management # Rewritten to work with updated autocomplete if not tkeywords_form.is_valid(): return HttpResponse( json.dumps({'message': "Invalid thesaurus keywords"}, status_code=400)) thesaurus_setting = getattr(settings, 'THESAURUS', None) if thesaurus_setting: tkeywords_data = tkeywords_form.cleaned_data['tkeywords'] tkeywords_data = tkeywords_data.filter( thesaurus__identifier=thesaurus_setting['name']) map_obj.tkeywords.set(tkeywords_data) elif Thesaurus.objects.all().exists(): fields = tkeywords_form.cleaned_data map_obj.tkeywords.set(tkeywords_form.cleanx(fields)) except Exception: tb = traceback.format_exc() logger.error(tb) map_obj.save(notify=True) return HttpResponse(json.dumps({'message': message})) # - POST Request Ends here - # Request.GET if poc is None: poc_form = ProfileForm(request.POST, prefix="poc") else: map_form.fields['poc'].initial = poc.id poc_form = ProfileForm(prefix="poc") poc_form.hidden = True if metadata_author is None: author_form = ProfileForm(request.POST, prefix="author") else: map_form.fields['metadata_author'].initial = metadata_author.id author_form = ProfileForm(prefix="author") author_form.hidden = True layers = MapLayer.objects.filter(map=map_obj.id) metadata_author_groups = get_user_visible_groups(request.user) if settings.ADMIN_MODERATE_UPLOADS: if not request.user.is_superuser: can_change_metadata = request.user.has_perm( 'change_resourcebase_metadata', map_obj.get_self_resource()) try: is_manager = request.user.groupmember_set.all().filter( role='manager').exists() except Exception: is_manager = False if not is_manager or not can_change_metadata: if settings.RESOURCE_PUBLISHING: map_form.fields['is_published'].widget.attrs.update( {'disabled': 'true'}) map_form.fields['is_approved'].widget.attrs.update( {'disabled': 'true'}) register_event(request, EventType.EVENT_VIEW_METADATA, map_obj) return render( request, template, context={ "resource": map_obj, "map": map_obj, "map_form": map_form, "poc_form": poc_form, "author_form": author_form, "category_form": category_form, "tkeywords_form": tkeywords_form, "layers": layers, "preview": getattr(settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'mapstore'), "crs": getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857'), "metadata_author_groups": metadata_author_groups, "TOPICCATEGORY_MANDATORY": getattr(settings, 'TOPICCATEGORY_MANDATORY', False), "GROUP_MANDATORY_RESOURCES": getattr(settings, 'GROUP_MANDATORY_RESOURCES', False), "UI_MANDATORY_FIELDS": list( set(getattr(settings, 'UI_DEFAULT_MANDATORY_FIELDS', [])) | set(getattr(settings, 'UI_REQUIRED_FIELDS', []))) })
def final_step_view(req, upload_session): _json_response = None if not upload_session: upload_session = _get_upload_session(req) if upload_session: import_session = upload_session.import_session _log('Checking session %s validity', import_session.id) if not check_import_session_is_valid(req, upload_session, import_session): error_msg = upload_session.import_session.tasks[0].error_message url = "/upload/layer_upload_invalid.html" _json_response = json_response({ 'url': url, 'status': 'error', 'id': import_session.id, 'error_msg': error_msg or 'Import Session is Invalid!', 'success': False }) return _json_response else: try: layer_id = None if req and 'layer_id' in req.GET: _layer = Layer.objects.filter(id=req.GET['layer_id']) if _layer.exists(): layer_id = _layer.first().resourcebase_ptr_id saved_layer = final_step(upload_session, upload_session.user, layer_id) assert saved_layer # this response is different then all of the other views in the # upload as it does not return a response as a json object _json_response = json_response({ 'status': 'finished', 'id': import_session.id, 'url': saved_layer.get_absolute_url(), 'bbox': saved_layer.bbox_string, 'crs': { 'type': 'name', 'properties': saved_layer.srid }, 'success': True }) register_event(req, EventType.EVENT_UPLOAD, saved_layer) return _json_response except (LayerNotReady, AssertionError): force_ajax = '&force_ajax=true' if req and 'force_ajax' in req.GET and req.GET[ 'force_ajax'] == 'true' else '' return json_response({ 'status': 'pending', 'success': True, 'id': import_session.id, 'redirect_to': f"/upload/final?id={import_session.id}{force_ajax}" }) except Exception as e: logger.exception(e) url = "upload/layer_upload_invalid.html" _json_response = json_response({ 'status': 'error', 'url': url, 'error_msg': str(e), 'success': False }) return _json_response else: url = "upload/layer_upload_invalid.html" _json_response = json_response({ 'status': 'error', 'url': url, 'error_msg': _('Upload Session invalid or no more accessible!'), 'success': False }) return _json_response
def form_valid(self, form): """ If the form is valid, save the associated model. """ self.object = form.save(commit=False) self.object.owner = self.request.user if settings.ADMIN_MODERATE_UPLOADS: self.object.is_approved = False if settings.RESOURCE_PUBLISHING: self.object.is_published = False self.object.save() form.save_many2many() self.object.set_permissions(form.cleaned_data['permissions']) abstract = None date = None regions = [] keywords = [] bbox = None out = {'success': False} if getattr(settings, 'EXIF_ENABLED', False): try: from geonode.documents.exif.utils import exif_extract_metadata_doc exif_metadata = exif_extract_metadata_doc(self.object) if exif_metadata: date = exif_metadata.get('date', None) keywords.extend(exif_metadata.get('keywords', [])) bbox = exif_metadata.get('bbox', None) abstract = exif_metadata.get('abstract', None) except Exception: logger.error("Exif extraction failed.") if abstract: self.object.abstract = abstract if date: self.object.date = date self.object.date_type = "Creation" if len(regions) > 0: self.object.regions.add(*regions) if len(keywords) > 0: self.object.keywords.add(*keywords) if bbox: bbox = BBOXHelper.from_xy(bbox) self.object.bbox_polygon = bbox.as_polygon() if getattr(settings, 'SLACK_ENABLED', False): try: from geonode.contrib.slack.utils import build_slack_message_document, send_slack_message send_slack_message( build_slack_message_document( "document_new", self.object)) except Exception: logger.error("Could not send slack message for new document.") self.object.save(notify=True) register_event(self.request, EventType.EVENT_UPLOAD, self.object) if self.request.GET.get('no__redirect', False): out['success'] = True out['url'] = reverse( 'document_detail', args=( self.object.id, )) if out['success']: status_code = 200 else: status_code = 400 return HttpResponse( json.dumps(out), content_type='application/json', status=status_code) else: return HttpResponseRedirect( reverse( 'document_detail', args=( self.object.id, )))