Esempio n. 1
0
    def post(self, request, id, *args, **kwargs):

        instance = get_object_or_404(Organisation, id=id, is_active=True)

        if not request.is_ajax():
            if 'delete' in request.POST and instance.geonet_id:
                try:
                    geonet.delete_record(instance.geonet_id)
                    instance.geonet_id = None
                    instance.save()
                except Exception as e:
                    messages.error(
                        request,
                        "La fiche de metadonnées a été supprimée avec succès.")
                else:
                    messages.success(
                        request,
                        "La fiche de metadonnées a été supprimée avec succès.")
            return redirect(reverse(self.namespace, id=instance.id))

        root = ET.fromstring(request.body)
        ns = {
            'gmd': 'http://www.isotc211.org/2005/gmd',
            'gco': 'http://www.isotc211.org/2005/gco'
        }
        id = root.find('gmd:fileIdentifier/gco:CharacterString', ns).text

        record = ET.tostring(root,
                             encoding='utf-8',
                             method='xml',
                             short_empty_elements=True)

        if not geonet.is_record_exists(id):
            try:
                geonet.create_record(id, record)
            except Exception:
                messages.error(
                    request,
                    'La création de la fiche de métadonnées a échoué.')
            else:
                geonet.publish(id)  # Toujours publier la fiche
                instance.geonet_id = id
                instance.save()
                messages.success(
                    request,
                    'La fiche de metadonnées a été créée avec succès.')
        else:
            try:
                geonet.update_record(id, record)
            except Exception:
                messages.error(
                    request,
                    'La mise à jour de la fiche de métadonnées a échoué.')
            else:
                messages.success(
                    request,
                    'La fiche de metadonnées a été créée avec succès.')

        return HttpResponse()
Esempio n. 2
0
    def get(self, request, id, *args, **kwargs):
        user, profile = user_and_profile(request)
        instance = get_object_or_404(Dataset, id=id)

        config = {
            'app_name': 'mdEdit',
            'app_title': 'mdEdit',
            'app_version': '0.14.9',
            'app_copyrights': '(c) CIGAL 2016',
            'languages': {'locales': ['fr']},
            'defaultLanguage': 'fr',
            'server_url_md': GEONETWORK_URL,
            'views': {
                'list': [{
                    # 'path': '{id}/edit/'.format(id=id),
                    'path': reverse('idgo_admin:dataset_mdedit_tpl_edit', kwargs={'id': instance.id}),
                    'values': {'fr': 'Edition'},
                    'locales': {'fr': join_url('views/edit/tpl-edit_fr.json')}
                    }, {
                    'path': join_url('tpl-view.html', path=MDEDIT_HTML_PATH),
                    'values': {'fr': 'Vue'},
                    'locales': {'fr': join_url('views/view/tpl-view_fr.json')}
                    }]},
            'models': {
                'list': [{
                    'path': join_url(MDEDIT_DATASET_MODEL),
                    'value': 'Modèle de fiche vierge'
                    }]},
            'locales': MDEDIT_LOCALES,
            'locales_path': join_url('locales/'),
            'geographicextents_list': join_url('list_geographicextents.json'),
            'referencesystems_list': join_url('list_referencesystems.json'),
            'static_root': join_url('libs/mdedit/', path=STATIC_URL),
            'modal_template': {
                'help': join_url('modal-help.html', path=MDEDIT_HTML_PATH)}}

        context = {'dataset': instance,
                   'doc_url': READTHEDOC_URL_INSPIRE,
                   'config': config}

        record = instance.geonet_id and geonet.get_record(str(instance.geonet_id)) or None

        if record:
            xml = record.xml.decode(encoding='utf-8')
            context['record_xml'] = re.sub('\n', '', xml).replace("'", "\\'")  # C'est moche
        else:
            context['record_obj'] = prefill_dataset_model(instance)

        return render_with_info_profile(request, self.template, context=context)
Esempio n. 3
0
 def get(self, request, dataset_name):
     """Voir la fiche de metadonnées du jeu de données."""
     instance = None
     for dataset in handler_get_request(request):
         if dataset.slug == dataset_name:
             instance = dataset
             break
     if not instance or (instance and not instance.geonet_id):
         raise Http404()
     try:
         record = geonet.get_record(str(instance.geonet_id))
     except Exception as e:
         return JsonResponse({'error': e.__str__()}, status=400)
     else:
         return HttpResponse(record.xml, content_type='application/xml')
Esempio n. 4
0
    def put(self, request, dataset_name):
        """Enregistrer la ficher de métadonnées du jeu de données."""
        request.PUT, _ = parse_request(request)
        request.PUT._mutable = True

        instance = None
        for dataset in handler_get_request(request):
            if dataset.slug == dataset_name:
                instance = dataset
                break
        if not instance:
            raise Http404()

        root = ET.fromstring(request.PUT.get('xml'))
        ns = {
            'gmd': 'http://www.isotc211.org/2005/gmd',
            'gco': 'http://www.isotc211.org/2005/gco'
        }
        geonet_id = root.find('gmd:fileIdentifier/gco:CharacterString',
                              ns).text
        if not geonet_id:
            return JsonResponse({'error': 'fileIdentifier not found'},
                                status=400)

        record = ET.tostring(root,
                             encoding='utf-8',
                             method='xml',
                             short_empty_elements=True)
        try:
            if not geonet.get_record(geonet_id):
                try:
                    geonet.create_record(geonet_id, record)
                except Exception as e:
                    return JsonResponse({'error': e.__str__()}, status=400)
                else:
                    geonet.publish(geonet_id)
                    dataset.geonet_id = geonet_id
            else:
                try:
                    geonet.update_record(geonet_id, record)
                except Exception as e:
                    return JsonResponse({'error': e.__str__()}, status=400)
            dataset.save(synchronize=True)

        except GenericException as e:
            return JsonResponse({'error': e.details}, status=400)

        return HttpResponse(status=204)
Esempio n. 5
0
    def post(self, request, id, *args, **kwargs):

        user, profile = user_and_profile(request)

        dataset = get_object_or_404(Dataset, id=id)

        if not request.is_ajax():
            return HttpResponseRedirect(
                reverse(self.namespace, kwargs={'dataset_id': id}))

        root = ET.fromstring(request.body)
        ns = {'gmd': 'http://www.isotc211.org/2005/gmd',
              'gco': 'http://www.isotc211.org/2005/gco'}
        id = root.find('gmd:fileIdentifier/gco:CharacterString', ns).text

        record = ET.tostring(
            root, encoding='utf-8', method='xml', short_empty_elements=True)

        # Ça marche mais c'est moche et illisible...
        # TODO: faire du code plus beau ; gérer les exceptions mieux que ça.
        if not geonet.get_record(id):
            try:
                geonet.create_record(id, record)
            except Exception:
                messages.error(request, 'La création de la fiche de métadonnées a échoué.')
            else:
                geonet.publish(id)  # Toujours publier la fiche
                dataset.geonet_id = UUID(id)
                dataset.save(current_user=None)
                messages.success(
                    request, 'La fiche de metadonnées a été créée avec succès.')
        else:
            try:
                geonet.update_record(id, record)
            except Exception:
                messages.error(request, 'La mise à jour de la fiche de métadonnées a échoué.')
            else:
                messages.success(
                    request, 'La fiche de metadonnées a été créée avec succès.')

        return HttpResponse()
Esempio n. 6
0
    def save(self, *args, harvest=True, **kwargs):
        Category = apps.get_model(app_label='idgo_admin',
                                  model_name='Category')
        Dataset = apps.get_model(app_label='idgo_admin', model_name='Dataset')
        License = apps.get_model(app_label='idgo_admin', model_name='License')
        Resource = apps.get_model(app_label='idgo_admin',
                                  model_name='Resource')
        ResourceFormats = apps.get_model(app_label='idgo_admin',
                                         model_name='ResourceFormats')

        # (1) Supprimer les jeux de données qui ne sont plus synchronisés
        previous = self.pk and RemoteCsw.objects.get(pk=self.pk)
        if previous:
            for dataset in Dataset.harvested_csw.filter(
                    remote_instance=previous):
                dataset.delete()
        else:
            # Dans le cas d'une création, on vérifie si l'URL CSW est valide
            try:
                with CswBaseHandler(self.url):
                    pass
            except CswBaseError as e:
                raise ValidationError(e.__str__(), code='url')

        # (2) Sauver l'instance
        super().save(*args, **kwargs)

        # (3) Créer/Mettre à jour les jeux de données synchronisés

        # On récupère dans le `stack` l'utilisateur effectuant l'opération
        editor = None
        for entry in inspect.stack():
            try:
                editor = entry[0].f_locals['request'].user._wrapped
            except (KeyError, AttributeError):
                continue
            break

        if not previous:
            return

        if harvest:
            # Puis on moissonne le catalogue
            try:
                ckan_ids = []
                geonet_ids = []
                with transaction.atomic():

                    with CswBaseHandler(self.url) as csw:
                        packages = csw.get_packages(
                            xml=self.getrecords or None)

                    for package in packages:
                        if not package['type'] == 'dataset':
                            continue

                        geonet_id = package['id']
                        update_frequency = dict(Dataset.FREQUENCY_CHOICES).get(
                            package.get('frequency'), 'unknown')
                        update_frequency = package.get('frequency')
                        if not (update_frequency and update_frequency in dict(
                                Dataset.FREQUENCY_CHOICES).keys()):
                            update_frequency = 'unknown'

                        date_creation = package.get('dataset_creation_date',
                                                    None)
                        if date_creation:
                            try:
                                date_creation = datetime.strptime(
                                    date_creation, ISOFORMAT_DATE)
                            except ValueError as e:
                                logger.warning(e)
                                date_creation = None

                        date_modification = package.get(
                            'dataset_modification_date', None)
                        if date_modification:
                            try:
                                date_modification = datetime.strptime(
                                    date_modification, ISOFORMAT_DATE)
                            except ValueError as e:
                                logger.warning(e)
                                date_modification = None

                        date_publication = package.get(
                            'dataset_publication_date', None)
                        if date_publication:
                            try:
                                date_publication = datetime.strptime(
                                    date_publication, ISOFORMAT_DATE)
                            except ValueError as e:
                                logger.warning(e)
                                date_publication = None

                        # Licence
                        license_titles = package.get('license_titles')
                        filters = [
                            Q(slug__in=license_titles),
                            Q(title__in=license_titles),
                            Q(alternate_titles__overlap=license_titles),
                        ]
                        license = License.objects.filter(reduce(
                            ior, filters)).distinct().first()
                        if not license:
                            try:
                                license = License.objects.get(
                                    slug=settings.DEFAULTS_VALUES.get(
                                        'LICENSE'))
                            except License.DoesNotExist:
                                license = License.objects.first()

                        # On pousse la fiche de MD dans Geonet
                        if not geonet.get_record(geonet_id):
                            try:
                                geonet.create_record(geonet_id, package['xml'])
                            except Exception as e:
                                logger.warning(
                                    'La création de la fiche de métadonnées a échoué.'
                                )
                                logger.error(e)
                            else:
                                geonet_ids.append(geonet_id)
                                geonet.publish(
                                    geonet_id)  # Toujours publier la fiche
                        else:
                            try:
                                geonet.update_record(geonet_id, package['xml'])
                            except Exception as e:
                                logger.warning(
                                    'La mise à jour de la fiche de métadonnées a échoué.'
                                )
                                logger.error(e)

                        slug = 'sync{}-{}'.format(
                            str(uuid.uuid4())[:7].lower(),
                            slugify(geonet_id))[:100]
                        kvp = {
                            'slug':
                            slug,
                            'title':
                            package.get('title'),
                            'description':
                            package.get('notes'),
                            'date_creation':
                            date_creation and date_creation.date(),
                            'date_modification':
                            date_modification and date_modification.date(),
                            'date_publication':
                            date_publication and date_publication.date(),
                            'editor':
                            editor,
                            'license':
                            license,
                            'owner_email':
                            self.organisation.email or DEFAULT_CONTACT_EMAIL,
                            'owner_name':
                            self.organisation.legal_name
                            or DEFAULT_PLATFORM_NAME,
                            'organisation':
                            self.organisation,
                            'published':
                            not package.get('private'),
                            'remote_instance':
                            self,
                            'remote_dataset':
                            geonet_id,
                            'update_frequency':
                            update_frequency,
                            'bbox':
                            package.get('bbox'),
                            # broadcaster_email
                            # broadcaster_name
                            # data_type
                            # geocover
                            'geonet_id':
                            geonet_id,
                            # granularity
                            # thumbnail
                            # support
                        }

                        dataset, created = Dataset.harvested_csw.update_or_create(
                            **kvp)
                        if created:
                            ckan_ids.append(dataset.ckan_id)

                        categories_name = [
                            m['name'] for m in package.get('groups', [])
                        ]
                        iso_topic_reverse = dict(
                            (v, k)
                            for k, v in Category._meta.fields[5].choices)

                        filters = [
                            Q(slug__in=categories_name),
                            Q(name__in=categories_name),
                            Q(iso_topic__in=[
                                m['name'] for m in package.get('groups', [])
                            ]),
                            Q(iso_topic__in=[
                                iso_topic_reverse.get(name)
                                for name in categories_name
                            ]),
                            Q(alternate_titles__overlap=categories_name),
                        ]

                        categories = Category.objects.filter(
                            reduce(ior, filters)).distinct()
                        if categories:
                            dataset.categories.set(categories, clear=True)

                        if not created:
                            dataset.keywords.clear()
                        keywords = [
                            tag['display_name'] for tag in package.get('tags')
                        ]
                        dataset.keywords.add(*keywords)

                        dataset.save(current_user=None,
                                     synchronize=True,
                                     activate=False)

                        for resource in package.get('resources', []):
                            try:
                                ckan_id = uuid.uuid4()
                            except ValueError as e:
                                logger.exception(e)
                                logger.error(
                                    "I can't crash here, so I do not pay any attention to this error."
                                )
                                continue

                            filters = []
                            protocol = resource.get('protocol')
                            protocol and filters.append(Q(protocol=protocol))
                            mimetype = resource.get('mimetype')
                            mimetype and filters.append(
                                Q(mimetype__overlap=[mimetype]))
                            try:
                                format_type = ResourceFormats.objects.get(
                                    reduce(iand, filters))
                            except (ResourceFormats.MultipleObjectsReturned,
                                    ResourceFormats.DoesNotExist, TypeError):
                                format_type = None

                            kvp = {
                                'ckan_id': ckan_id,
                                'dataset': dataset,
                                'format_type': format_type,
                                'title': resource['name'] or resource['url'],
                                'referenced_url': resource['url'],
                            }

                            try:
                                resource = Resource.objects.get(
                                    ckan_id=ckan_id)
                            except Resource.DoesNotExist:
                                resource = Resource.default.create(save_opts={
                                    'current_user':
                                    editor,
                                    'synchronize':
                                    True
                                },
                                                                   **kvp)
                            else:
                                for k, v in kvp.items():
                                    setattr(resource, k, v)
                            resource.save(current_user=editor,
                                          synchronize=True)

            except Exception as e:
                for id in ckan_ids:
                    logger.warning(
                        'Delete CKAN package : {id}.'.format(id=str(id)))
                    CkanHandler.purge_dataset(str(id))
                for id in geonet_ids:
                    logger.warning('Delete MD : {id}.'.format(id=str(id)))
                    geonet.delete_record(id)
                logger.error(e)
                raise CriticalError()
            else:
                for id in ckan_ids:
                    CkanHandler.publish_dataset(id=str(id), state='active')
Esempio n. 7
0
    def post(self, request, id, *args, **kwargs):
        user = request.user
        dataset = get_object_or_404(Dataset, id=id)

        delete = 'delete' in request.POST
        save = 'save' in request.POST
        save_and_continue = 'continue' in request.POST

        if delete and dataset.geonet_id:
            try:
                geonet.delete_record(dataset.geonet_id)
                dataset.geonet_id = None
                dataset.save(current_user=None)
            except Exception:
                messages.error(
                    request,
                    "La fiche de metadonnées a été supprimée avec succès.")
            else:
                messages.success(
                    request,
                    "La fiche de metadonnées a été supprimée avec succès.")
            # finally:
            return redirect('idgo_admin:dataset_mdedit', id=id)

        if save or save_and_continue:
            data = dict(request.POST)

            dataset.title = data['dataTitle'][0] or dataset.title
            dataset.description = data['dataAbstract'][0] or None

            date_creation = data['dataDateCreation'][0] or None
            if date_creation:
                dataset.date_creation = datetime.strptime(
                    date_creation, "%Y-%m-%d").date()

            date_modification = data['dataDateRevision'][0] or None
            if date_modification:
                dataset.date_modification = datetime.strptime(
                    date_modification, "%Y-%m-%d").date()

            date_publication = data['dataDatePublication'][0] or None
            if date_publication:
                dataset.date_publication = datetime.strptime(
                    date_publication, "%Y-%m-%d").date()

            dataset.update_frequency = {
                'notPlanned': 'never',  # [011]
                'asNeeded': 'asneeded',  # [009]
                'irregular': 'intermittently',  # [010]
                'continual': 'continuously',  # [001]
                'daily': 'daily',  # [002]
                'weekly': 'weekly',  # [003]
                'fortnightly': 'fortnightly',  # [004]
                'monthly': 'monthly',  # [005]
                'quarterly': 'quaterly',  # [006]
                'semiannual': 'biannually',  # [007]
                'annual': 'annually'  # [008]
            }.get(data['dataMaintenanceFrequency'][0], 'unknown')  # [012]

            keywords = [
                k.strip() for l in [s.split(',') for s in data['keyword']]
                for k in l if k
            ]
            if keywords:
                dataset.keywords.clear()
                for k in keywords:
                    dataset.keywords.add(k)

            root = ET.fromstring(request.POST.get('xml'))
            ns = {
                'gmd': 'http://www.isotc211.org/2005/gmd',
                'gco': 'http://www.isotc211.org/2005/gco'
            }
            geonet_id = root.find('gmd:fileIdentifier/gco:CharacterString',
                                  ns).text

            record = ET.tostring(root,
                                 encoding='utf-8',
                                 method='xml',
                                 short_empty_elements=True)

            error = False
            if not geonet.get_record(geonet_id):
                try:
                    geonet.create_record(geonet_id, record)
                except Exception:
                    error = True
                    messages.error(
                        request,
                        "La création de la fiche de métadonnées a échoué.")
                else:
                    # Toujours publier la fiche
                    geonet.publish(geonet_id)
                    dataset.geonet_id = geonet_id
                    messages.success(
                        request,
                        "La fiche de metadonnées a été créée avec succès.")
            else:
                try:
                    geonet.update_record(geonet_id, record)
                except Exception:
                    error = True
                    messages.error(
                        request,
                        "La mise à jour de la fiche de métadonnées a échoué.")
                else:
                    messages.success(
                        request,
                        "La fiche de metadonnées a été mise à jour avec succès."
                    )
            if not error:
                dataset.save(current_user=user, synchronize=True)

        if save_and_continue:
            return redirect('idgo_admin:dataset_mdedit', id=id)
        else:
            return redirect('idgo_admin:list_my_datasets')
Esempio n. 8
0
def delete_attached_md(sender, instance, **kwargs):
    if instance.geonet_id:
        geonet.delete_record(instance.geonet_id)
        logger.info("Dataset MD '%s' has been deleted." % instance.geonet_id)