udata 8.0.1__py2.py3-none-any.whl → 8.0.1.dev28882__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- udata/__init__.py +1 -1
- udata/api/__init__.py +3 -6
- udata/api/oauth2.py +1 -2
- udata/core/badges/models.py +1 -2
- udata/core/dataset/apiv2.py +0 -2
- udata/core/dataset/models.py +0 -1
- udata/core/dataset/rdf.py +1 -21
- udata/core/metrics/models.py +3 -2
- udata/core/organization/api_fields.py +3 -28
- udata/core/organization/models.py +1 -3
- udata/core/owned.py +2 -39
- udata/core/spatial/api.py +4 -4
- udata/core/user/api.py +7 -11
- udata/core/user/models.py +2 -13
- udata/harvest/backends/dcat.py +8 -14
- udata/harvest/tests/dcat/catalog.xml +0 -1
- udata/harvest/tests/test_dcat_backend.py +0 -3
- udata/routing.py +0 -6
- udata/settings.py +1 -4
- udata/static/admin.css +2 -2
- udata/static/admin.css.map +1 -1
- udata/static/chunks/{0.93c3ae13b5b94753ee80.js → 0.6f1698738c9b0618b673.js} +3 -3
- udata/static/chunks/0.6f1698738c9b0618b673.js.map +1 -0
- udata/static/chunks/{14.e64890872b31c55fcdf7.js → 14.f4037a917d5364cb564b.js} +2 -2
- udata/static/chunks/14.f4037a917d5364cb564b.js.map +1 -0
- udata/static/chunks/{2.614b3e73b072982fd9b1.js → 2.7c89fae92899be371ed3.js} +2 -2
- udata/static/chunks/2.7c89fae92899be371ed3.js.map +1 -0
- udata/static/chunks/{5.48417db6b33328fa9d6a.js → 5.3dc97ea195d251881552.js} +2 -2
- udata/static/chunks/5.3dc97ea195d251881552.js.map +1 -0
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/tests/api/__init__.py +0 -3
- udata/tests/api/test_organizations_api.py +5 -78
- udata/tests/api/test_user_api.py +13 -47
- udata/tests/plugin.py +0 -5
- {udata-8.0.1.dist-info → udata-8.0.1.dev28882.dist-info}/METADATA +3 -12
- {udata-8.0.1.dist-info → udata-8.0.1.dev28882.dist-info}/RECORD +41 -46
- udata/api_fields.py +0 -254
- udata/core/dataservices/__init__.py +0 -0
- udata/core/dataservices/api.py +0 -84
- udata/core/dataservices/models.py +0 -130
- udata/static/chunks/0.93c3ae13b5b94753ee80.js.map +0 -1
- udata/static/chunks/14.e64890872b31c55fcdf7.js.map +0 -1
- udata/static/chunks/2.614b3e73b072982fd9b1.js.map +0 -1
- udata/static/chunks/5.48417db6b33328fa9d6a.js.map +0 -1
- udata/tests/api/test_dataservices_api.py +0 -236
- {udata-8.0.1.dist-info → udata-8.0.1.dev28882.dist-info}/LICENSE +0 -0
- {udata-8.0.1.dist-info → udata-8.0.1.dev28882.dist-info}/WHEEL +0 -0
- {udata-8.0.1.dist-info → udata-8.0.1.dev28882.dist-info}/entry_points.txt +0 -0
- {udata-8.0.1.dist-info → udata-8.0.1.dev28882.dist-info}/top_level.txt +0 -0
udata/__init__.py
CHANGED
udata/api/__init__.py
CHANGED
|
@@ -22,7 +22,7 @@ from udata.auth import (
|
|
|
22
22
|
from udata.utils import safe_unicode
|
|
23
23
|
from udata.mongo.errors import FieldValidationError
|
|
24
24
|
|
|
25
|
-
from . import fields
|
|
25
|
+
from . import fields, oauth2
|
|
26
26
|
from .signals import on_api_call
|
|
27
27
|
|
|
28
28
|
|
|
@@ -129,7 +129,6 @@ class UDataApi(Api):
|
|
|
129
129
|
@wraps(func)
|
|
130
130
|
def wrapper(*args, **kwargs):
|
|
131
131
|
from udata.core.user.models import User
|
|
132
|
-
from udata.api.oauth2 import check_credentials
|
|
133
132
|
|
|
134
133
|
if current_user.is_authenticated:
|
|
135
134
|
return func(*args, **kwargs)
|
|
@@ -144,7 +143,7 @@ class UDataApi(Api):
|
|
|
144
143
|
if not login_user(user, False):
|
|
145
144
|
self.abort(401, 'Inactive user')
|
|
146
145
|
else:
|
|
147
|
-
check_credentials()
|
|
146
|
+
oauth2.check_credentials()
|
|
148
147
|
return func(*args, **kwargs)
|
|
149
148
|
return wrapper
|
|
150
149
|
|
|
@@ -325,7 +324,6 @@ def init_app(app):
|
|
|
325
324
|
import udata.core.user.api # noqa
|
|
326
325
|
import udata.core.dataset.api # noqa
|
|
327
326
|
import udata.core.dataset.apiv2 # noqa
|
|
328
|
-
import udata.core.dataservices.api # noqa
|
|
329
327
|
import udata.core.discussions.api # noqa
|
|
330
328
|
import udata.core.reuse.api # noqa
|
|
331
329
|
import udata.core.reuse.apiv2 # noqa
|
|
@@ -352,6 +350,5 @@ def init_app(app):
|
|
|
352
350
|
app.register_blueprint(apiv1_blueprint)
|
|
353
351
|
app.register_blueprint(apiv2_blueprint)
|
|
354
352
|
|
|
355
|
-
|
|
356
|
-
oauth2_init_app(app)
|
|
353
|
+
oauth2.init_app(app)
|
|
357
354
|
cors.init_app(app)
|
udata/api/oauth2.py
CHANGED
|
@@ -34,7 +34,6 @@ from werkzeug.security import gen_salt
|
|
|
34
34
|
|
|
35
35
|
from udata.app import csrf
|
|
36
36
|
from udata.auth import current_user, login_required, login_user
|
|
37
|
-
from udata.core.organization.models import Organization
|
|
38
37
|
from udata.i18n import I18nBlueprint, lazy_gettext as _
|
|
39
38
|
from udata.mongo import db
|
|
40
39
|
from udata.core.storages import images, default_image_basename
|
|
@@ -67,7 +66,7 @@ class OAuth2Client(ClientMixin, db.Datetimed, db.Document):
|
|
|
67
66
|
description = db.StringField()
|
|
68
67
|
|
|
69
68
|
owner = db.ReferenceField('User')
|
|
70
|
-
organization = db.ReferenceField(Organization, reverse_delete_rule=db.NULLIFY)
|
|
69
|
+
organization = db.ReferenceField('Organization', reverse_delete_rule=db.NULLIFY)
|
|
71
70
|
image = db.ImageField(fs=images, basename=default_image_basename,
|
|
72
71
|
thumbnails=[150, 25])
|
|
73
72
|
|
udata/core/badges/models.py
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import weakref
|
|
2
3
|
|
|
3
4
|
from datetime import datetime
|
|
4
5
|
|
|
5
6
|
from mongoengine.signals import post_save
|
|
6
7
|
|
|
7
|
-
from udata.api_fields import field
|
|
8
8
|
from udata.auth import current_user
|
|
9
9
|
from udata.mongo import db
|
|
10
10
|
|
|
11
11
|
from .signals import on_badge_added, on_badge_removed
|
|
12
|
-
from .fields import badge_fields
|
|
13
12
|
|
|
14
13
|
log = logging.getLogger(__name__)
|
|
15
14
|
|
udata/core/dataset/apiv2.py
CHANGED
|
@@ -8,7 +8,6 @@ from udata import search
|
|
|
8
8
|
from udata.api import apiv2, API, fields
|
|
9
9
|
from udata.utils import multi_to_dict, get_by
|
|
10
10
|
|
|
11
|
-
from udata.core.organization.api_fields import member_user_with_email_fields
|
|
12
11
|
from .api_fields import (
|
|
13
12
|
badge_fields,
|
|
14
13
|
org_ref_fields,
|
|
@@ -166,7 +165,6 @@ specific_resource_fields = apiv2.model('SpecificResource', {
|
|
|
166
165
|
apiv2.inherit('Badge', badge_fields)
|
|
167
166
|
apiv2.inherit('OrganizationReference', org_ref_fields)
|
|
168
167
|
apiv2.inherit('UserReference', user_ref_fields)
|
|
169
|
-
apiv2.inherit('MemberUserWithEmail', member_user_with_email_fields)
|
|
170
168
|
apiv2.inherit('Resource', resource_fields)
|
|
171
169
|
apiv2.inherit('SpatialCoverage', spatial_coverage_fields)
|
|
172
170
|
apiv2.inherit('TemporalCoverage', temporal_coverage_fields)
|
udata/core/dataset/models.py
CHANGED
udata/core/dataset/rdf.py
CHANGED
|
@@ -76,16 +76,6 @@ EU_RDF_REQUENCIES = {
|
|
|
76
76
|
EUFREQ.NEVER: 'punctual',
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
# Map High Value Datasets URIs to keyword categories
|
|
80
|
-
EU_HVD_CATEGORIES = {
|
|
81
|
-
"http://data.europa.eu/bna/c_164e0bf5": "Météorologiques",
|
|
82
|
-
"http://data.europa.eu/bna/c_a9135398": "Entreprises et propriété d'entreprises",
|
|
83
|
-
"http://data.europa.eu/bna/c_ac64a52d": "Géospatiales",
|
|
84
|
-
"http://data.europa.eu/bna/c_b79e35eb": "Mobilité",
|
|
85
|
-
"http://data.europa.eu/bna/c_dd313021": "Observation de la terre et environnement",
|
|
86
|
-
"http://data.europa.eu/bna/c_e1da4e07": "Statistiques"
|
|
87
|
-
}
|
|
88
|
-
|
|
89
79
|
|
|
90
80
|
class HTMLDetector(HTMLParser):
|
|
91
81
|
def __init__(self, *args, **kwargs):
|
|
@@ -479,19 +469,9 @@ def remote_url_from_rdf(rdf):
|
|
|
479
469
|
|
|
480
470
|
|
|
481
471
|
def theme_labels_from_rdf(rdf):
|
|
482
|
-
'''
|
|
483
|
-
Get theme labels to use as keywords.
|
|
484
|
-
Map HVD keywords from known URIs resources if HVD support is activated.
|
|
485
|
-
'''
|
|
486
472
|
for theme in rdf.objects(DCAT.theme):
|
|
487
473
|
if isinstance(theme, RdfResource):
|
|
488
|
-
|
|
489
|
-
if current_app.config['HVD_SUPPORT'] and uri in EU_HVD_CATEGORIES:
|
|
490
|
-
label = EU_HVD_CATEGORIES[uri]
|
|
491
|
-
# Additionnally yield hvd keyword
|
|
492
|
-
yield 'hvd'
|
|
493
|
-
else:
|
|
494
|
-
label = rdf_value(theme, SKOS.prefLabel)
|
|
474
|
+
label = rdf_value(theme, SKOS.prefLabel)
|
|
495
475
|
else:
|
|
496
476
|
label = theme.toPython()
|
|
497
477
|
if label:
|
udata/core/metrics/models.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from datetime import date, timedelta
|
|
2
|
+
|
|
2
3
|
from udata.mongo import db
|
|
3
4
|
|
|
4
5
|
|
|
@@ -6,7 +7,7 @@ __all__ = ('WithMetrics',)
|
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class WithMetrics(object):
|
|
9
|
-
metrics =
|
|
10
|
+
metrics = db.DictField()
|
|
10
11
|
|
|
11
12
|
__metrics_keys__ = []
|
|
12
13
|
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
from flask import request
|
|
2
|
-
|
|
3
1
|
from udata.api import api, fields, base_reference
|
|
4
2
|
from udata.core.badges.fields import badge_fields
|
|
5
|
-
from udata.core.organization.permissions import OrganizationPrivatePermission
|
|
6
3
|
|
|
7
4
|
from .constants import ORG_ROLES, DEFAULT_ROLE, MEMBERSHIP_STATUS, BIGGEST_LOGO_SIZE
|
|
8
5
|
|
|
@@ -30,29 +27,9 @@ org_ref_fields = api.inherit('OrganizationReference', base_reference, {
|
|
|
30
27
|
|
|
31
28
|
from udata.core.user.api_fields import user_ref_fields # noqa: required
|
|
32
29
|
|
|
33
|
-
def check_can_access_email():
|
|
34
|
-
# This endpoint is secure, only organization member has access.
|
|
35
|
-
if request.endpoint == 'api.request_membership':
|
|
36
|
-
return True
|
|
37
|
-
|
|
38
|
-
if request.endpoint != 'api.organization':
|
|
39
|
-
return False
|
|
40
|
-
|
|
41
|
-
org = request.view_args.get('org')
|
|
42
|
-
if org is None:
|
|
43
|
-
return False
|
|
44
|
-
|
|
45
|
-
return OrganizationPrivatePermission(org).can()
|
|
46
|
-
|
|
47
|
-
member_user_with_email_fields = api.inherit('MemberUserWithEmail', user_ref_fields, {
|
|
48
|
-
'email': fields.Raw(
|
|
49
|
-
attribute=lambda o: o.email if check_can_access_email() else None,
|
|
50
|
-
description='The user email (only present on show organization endpoint if the current user has edit permission on the org)', readonly=True),
|
|
51
|
-
})
|
|
52
|
-
|
|
53
30
|
request_fields = api.model('MembershipRequest', {
|
|
54
31
|
'id': fields.String(readonly=True),
|
|
55
|
-
'user': fields.Nested(
|
|
32
|
+
'user': fields.Nested(user_ref_fields),
|
|
56
33
|
'created': fields.ISODateTime(
|
|
57
34
|
description='The request creation date', readonly=True),
|
|
58
35
|
'status': fields.String(
|
|
@@ -63,12 +40,10 @@ request_fields = api.model('MembershipRequest', {
|
|
|
63
40
|
})
|
|
64
41
|
|
|
65
42
|
member_fields = api.model('Member', {
|
|
66
|
-
'user': fields.Nested(
|
|
43
|
+
'user': fields.Nested(user_ref_fields),
|
|
67
44
|
'role': fields.String(
|
|
68
45
|
description='The member role in the organization', required=True,
|
|
69
|
-
enum=list(ORG_ROLES), default=DEFAULT_ROLE)
|
|
70
|
-
'since': fields.ISODateTime(
|
|
71
|
-
description='The date the user joined the organization', readonly=True),
|
|
46
|
+
enum=list(ORG_ROLES), default=DEFAULT_ROLE)
|
|
72
47
|
})
|
|
73
48
|
|
|
74
49
|
org_fields = api.model('Organization', {
|
|
@@ -5,11 +5,9 @@ from blinker import Signal
|
|
|
5
5
|
from mongoengine.signals import pre_save, post_save
|
|
6
6
|
from werkzeug.utils import cached_property
|
|
7
7
|
|
|
8
|
-
from udata.core.badges.models import BadgeMixin
|
|
9
|
-
from udata.core.metrics.models import WithMetrics
|
|
10
8
|
from udata.core.storages import avatars, default_image_basename
|
|
11
9
|
from udata.frontend.markdown import mdstrip
|
|
12
|
-
from udata.
|
|
10
|
+
from udata.models import db, BadgeMixin, WithMetrics
|
|
13
11
|
from udata.i18n import lazy_gettext as _
|
|
14
12
|
from udata.uris import endpoint_for
|
|
15
13
|
from .constants import ASSOCIATION, CERTIFIED, COMPANY, LOCAL_AUTHORITY, LOGO_SIZES, ORG_BID_SIZE_LIMIT, ORG_ROLES, DEFAULT_ROLE, MEMBERSHIP_STATUS, LOGO_MAX_SIZE, PUBLIC_SERVICE
|
udata/core/owned.py
CHANGED
|
@@ -4,15 +4,7 @@ from blinker import signal
|
|
|
4
4
|
from mongoengine import NULLIFY, Q, post_save
|
|
5
5
|
from mongoengine.fields import ReferenceField
|
|
6
6
|
|
|
7
|
-
from udata.api_fields import field
|
|
8
|
-
from udata.core.organization.models import Organization
|
|
9
|
-
from udata.core.user.models import User
|
|
10
7
|
from udata.mongo.queryset import UDataQuerySet
|
|
11
|
-
from udata.core.user.api_fields import user_ref_fields
|
|
12
|
-
from udata.core.organization.api_fields import org_ref_fields
|
|
13
|
-
from udata.core.organization.permissions import OrganizationPrivatePermission
|
|
14
|
-
from udata.mongo.errors import FieldValidationError
|
|
15
|
-
from udata.i18n import lazy_gettext as _
|
|
16
8
|
|
|
17
9
|
log = logging.getLogger(__name__)
|
|
18
10
|
|
|
@@ -23,42 +15,14 @@ class OwnedQuerySet(UDataQuerySet):
|
|
|
23
15
|
for owner in owners:
|
|
24
16
|
qs |= Q(owner=owner) | Q(organization=owner)
|
|
25
17
|
return self(qs)
|
|
26
|
-
|
|
27
|
-
def check_owner_is_current_user(owner):
|
|
28
|
-
from udata.auth import current_user, admin_permission
|
|
29
|
-
if current_user.is_authenticated and owner and not admin_permission and current_user.id != owner:
|
|
30
|
-
raise FieldValidationError(_('You can only set yourself as owner'), field="owner")
|
|
31
|
-
|
|
32
|
-
def check_organization_is_valid_for_current_user(organization):
|
|
33
|
-
from udata.auth import current_user
|
|
34
|
-
from udata.models import Organization
|
|
35
|
-
|
|
36
|
-
org = Organization.objects(id=organization).first()
|
|
37
|
-
if org is None:
|
|
38
|
-
raise FieldValidationError(_("Unknown organization"), field="organization")
|
|
39
|
-
|
|
40
|
-
if current_user.is_authenticated and org and not OrganizationPrivatePermission(org).can():
|
|
41
|
-
raise FieldValidationError(_("Permission denied for this organization"), field="organization")
|
|
42
18
|
|
|
43
19
|
|
|
44
20
|
class Owned(object):
|
|
45
21
|
'''
|
|
46
22
|
A mixin to factorize owning behvaior between users and organizations.
|
|
47
23
|
'''
|
|
48
|
-
owner =
|
|
49
|
-
|
|
50
|
-
nested_fields=user_ref_fields,
|
|
51
|
-
description="Only present if organization is not set. Can only be set to the current authenticated user.",
|
|
52
|
-
check=check_owner_is_current_user,
|
|
53
|
-
allow_null=True,
|
|
54
|
-
)
|
|
55
|
-
organization = field(
|
|
56
|
-
ReferenceField(Organization, reverse_delete_rule=NULLIFY),
|
|
57
|
-
nested_fields=org_ref_fields,
|
|
58
|
-
description="Only present if owner is not set. Can only be set to an organization of the current authenticated user.",
|
|
59
|
-
check=check_organization_is_valid_for_current_user,
|
|
60
|
-
allow_null=True,
|
|
61
|
-
)
|
|
24
|
+
owner = ReferenceField('User', reverse_delete_rule=NULLIFY)
|
|
25
|
+
organization = ReferenceField('Organization', reverse_delete_rule=NULLIFY)
|
|
62
26
|
|
|
63
27
|
on_owner_change = signal('Owned.on_owner_change')
|
|
64
28
|
|
|
@@ -74,7 +38,6 @@ class Owned(object):
|
|
|
74
38
|
'''
|
|
75
39
|
Verify owner consistency and fetch original owner before the new one erase it.
|
|
76
40
|
'''
|
|
77
|
-
|
|
78
41
|
changed_fields = self._get_changed_fields()
|
|
79
42
|
if 'organization' in changed_fields and 'owner' in changed_fields:
|
|
80
43
|
# Ownership changes (org to owner or the other way around) have already been made
|
udata/core/spatial/api.py
CHANGED
|
@@ -85,7 +85,7 @@ dataset_parser.add_argument(
|
|
|
85
85
|
location='args', default=25)
|
|
86
86
|
|
|
87
87
|
|
|
88
|
-
@ns.route('/zones/<
|
|
88
|
+
@ns.route('/zones/<pathlist:ids>/', endpoint='zones')
|
|
89
89
|
class ZonesAPI(API):
|
|
90
90
|
@api.doc('spatial_zones',
|
|
91
91
|
params={'ids': 'A zone identifiers list (comma separated)'})
|
|
@@ -101,7 +101,7 @@ class ZonesAPI(API):
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
@ns.route('/zone/<id>/datasets/', endpoint='zone_datasets')
|
|
104
|
+
@ns.route('/zone/<path:id>/datasets/', endpoint='zone_datasets')
|
|
105
105
|
class ZoneDatasetsAPI(API):
|
|
106
106
|
@api.doc('spatial_zone_datasets', params={'id': 'A zone identifier'})
|
|
107
107
|
@api.expect(dataset_parser)
|
|
@@ -118,7 +118,7 @@ class ZoneDatasetsAPI(API):
|
|
|
118
118
|
return datasets
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
@ns.route('/zone/<id>/', endpoint='zone')
|
|
121
|
+
@ns.route('/zone/<path:id>/', endpoint='zone')
|
|
122
122
|
class ZoneAPI(API):
|
|
123
123
|
@api.doc('spatial_zone', params={'id': 'A zone identifier'})
|
|
124
124
|
def get(self, id):
|
|
@@ -152,7 +152,7 @@ class SpatialGranularitiesAPI(API):
|
|
|
152
152
|
} for id, name in spatial_granularities]
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
@ns.route('/coverage/<level>/', endpoint='spatial_coverage')
|
|
155
|
+
@ns.route('/coverage/<path:level>/', endpoint='spatial_coverage')
|
|
156
156
|
class SpatialCoverageAPI(API):
|
|
157
157
|
@api.doc('spatial_coverage')
|
|
158
158
|
@api.marshal_list_with(feature_collection_fields)
|
udata/core/user/api.py
CHANGED
|
@@ -226,7 +226,6 @@ class UserListAPI(API):
|
|
|
226
226
|
fields = user_fields
|
|
227
227
|
form = UserProfileForm
|
|
228
228
|
|
|
229
|
-
@api.secure(admin_permission)
|
|
230
229
|
@api.doc('list_users')
|
|
231
230
|
@api.expect(user_parser.parser)
|
|
232
231
|
@api.marshal_with(user_page_fields)
|
|
@@ -270,12 +269,6 @@ class UserAvatarAPI(API):
|
|
|
270
269
|
return {'image': user.avatar}
|
|
271
270
|
|
|
272
271
|
|
|
273
|
-
|
|
274
|
-
delete_parser = api.parser()
|
|
275
|
-
delete_parser.add_argument(
|
|
276
|
-
'no_mail', type=bool, help='Do not send a mail to notify the user of the deletion',
|
|
277
|
-
location='args', default=False)
|
|
278
|
-
|
|
279
272
|
@ns.route('/<user:user>/', endpoint='user')
|
|
280
273
|
@api.response(404, 'User not found')
|
|
281
274
|
@api.response(410, 'User is not active or has been deleted')
|
|
@@ -304,19 +297,22 @@ class UserAPI(API):
|
|
|
304
297
|
|
|
305
298
|
@api.secure(admin_permission)
|
|
306
299
|
@api.doc('delete_user')
|
|
307
|
-
@api.expect(delete_parser)
|
|
308
300
|
@api.response(204, 'Object deleted')
|
|
309
301
|
@api.response(403, 'When trying to delete yourself')
|
|
310
302
|
def delete(self, user):
|
|
311
303
|
'''Delete a user given its identifier'''
|
|
312
|
-
args = delete_parser.parse_args()
|
|
313
304
|
if user.deleted:
|
|
314
305
|
api.abort(410, 'User has already been deleted')
|
|
315
306
|
if user == current_user._get_current_object():
|
|
316
307
|
api.abort(403, 'You cannot delete yourself with this API. ' +
|
|
317
308
|
'Use the "me" API instead.')
|
|
318
|
-
|
|
319
|
-
|
|
309
|
+
if user.avatar.filename is not None:
|
|
310
|
+
storage = storages.avatars
|
|
311
|
+
storage.delete(user.avatar.filename)
|
|
312
|
+
storage.delete(user.avatar.original)
|
|
313
|
+
for key, value in user.avatar.thumbnails.items():
|
|
314
|
+
storage.delete(value)
|
|
315
|
+
user.mark_as_deleted()
|
|
320
316
|
return '', 204
|
|
321
317
|
|
|
322
318
|
|
udata/core/user/models.py
CHANGED
|
@@ -13,7 +13,6 @@ from mongoengine.signals import pre_save, post_save
|
|
|
13
13
|
from werkzeug.utils import cached_property
|
|
14
14
|
|
|
15
15
|
from udata import mail
|
|
16
|
-
from udata.core import storages
|
|
17
16
|
from udata.uris import endpoint_for
|
|
18
17
|
from udata.frontend.markdown import mdstrip
|
|
19
18
|
from udata.i18n import lazy_gettext as _
|
|
@@ -234,15 +233,7 @@ class User(WithMetrics, UserMixin, db.Document):
|
|
|
234
233
|
raise NotImplementedError('''This method should not be using directly.
|
|
235
234
|
Use `mark_as_deleted` (or `_delete` if you know what you're doing)''')
|
|
236
235
|
|
|
237
|
-
def mark_as_deleted(self
|
|
238
|
-
if self.avatar.filename is not None:
|
|
239
|
-
storage = storages.avatars
|
|
240
|
-
storage.delete(self.avatar.filename)
|
|
241
|
-
storage.delete(self.avatar.original)
|
|
242
|
-
for key, value in self.avatar.thumbnails.items():
|
|
243
|
-
storage.delete(value)
|
|
244
|
-
|
|
245
|
-
|
|
236
|
+
def mark_as_deleted(self):
|
|
246
237
|
copied_user = copy(self)
|
|
247
238
|
self.email = '{}@deleted'.format(self.id)
|
|
248
239
|
self.slug = 'deleted'
|
|
@@ -279,9 +270,7 @@ class User(WithMetrics, UserMixin, db.Document):
|
|
|
279
270
|
from udata.models import ContactPoint
|
|
280
271
|
ContactPoint.objects(owner=self).delete()
|
|
281
272
|
|
|
282
|
-
|
|
283
|
-
if notify:
|
|
284
|
-
mail.send(_('Account deletion'), copied_user, 'account_deleted')
|
|
273
|
+
mail.send(_('Account deletion'), copied_user, 'account_deleted')
|
|
285
274
|
|
|
286
275
|
def count_datasets(self):
|
|
287
276
|
from udata.models import Dataset
|
udata/harvest/backends/dcat.py
CHANGED
|
@@ -268,6 +268,7 @@ class CswDcatBackend(DcatBackend):
|
|
|
268
268
|
headers=headers).content)
|
|
269
269
|
|
|
270
270
|
return graphs
|
|
271
|
+
|
|
271
272
|
|
|
272
273
|
|
|
273
274
|
class CswIso19139DcatBackend(DcatBackend):
|
|
@@ -294,7 +295,6 @@ class CswIso19139DcatBackend(DcatBackend):
|
|
|
294
295
|
transform = ET.XSLT(xsl)
|
|
295
296
|
|
|
296
297
|
# Start querying and parsing graph
|
|
297
|
-
# Filter on dataset or serie records
|
|
298
298
|
body = '''<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
|
|
299
299
|
xmlns:gmd="http://www.isotc211.org/2005/gmd"
|
|
300
300
|
service="CSW" version="2.0.2" resultType="results"
|
|
@@ -304,16 +304,10 @@ class CswIso19139DcatBackend(DcatBackend):
|
|
|
304
304
|
<csw:ElementSetName>full</csw:ElementSetName>
|
|
305
305
|
<csw:Constraint version="1.1.0">
|
|
306
306
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
|
307
|
-
<ogc:
|
|
308
|
-
<ogc:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
</ogc:PropertyIsEqualTo>
|
|
312
|
-
<ogc:PropertyIsEqualTo>
|
|
313
|
-
<ogc:PropertyName>dc:type</ogc:PropertyName>
|
|
314
|
-
<ogc:Literal>series</ogc:Literal>
|
|
315
|
-
</ogc:PropertyIsEqualTo>
|
|
316
|
-
</ogc:Or>
|
|
307
|
+
<ogc:PropertyIsEqualTo>
|
|
308
|
+
<ogc:PropertyName>dc:type</ogc:PropertyName>
|
|
309
|
+
<ogc:Literal>dataset</ogc:Literal>
|
|
310
|
+
</ogc:PropertyIsEqualTo>
|
|
317
311
|
</ogc:Filter>
|
|
318
312
|
</csw:Constraint>
|
|
319
313
|
</csw:Query>
|
|
@@ -325,7 +319,7 @@ class CswIso19139DcatBackend(DcatBackend):
|
|
|
325
319
|
start = 1
|
|
326
320
|
|
|
327
321
|
response = self.post(url, data=body.format(start=start, schema=self.ISO_SCHEMA),
|
|
328
|
-
|
|
322
|
+
headers=headers)
|
|
329
323
|
response.raise_for_status()
|
|
330
324
|
|
|
331
325
|
tree_before_transform = ET.fromstring(response.content)
|
|
@@ -357,12 +351,12 @@ class CswIso19139DcatBackend(DcatBackend):
|
|
|
357
351
|
next_record = self.next_record_if_should_continue(start, search_results)
|
|
358
352
|
if not next_record:
|
|
359
353
|
break
|
|
360
|
-
|
|
354
|
+
|
|
361
355
|
start = next_record
|
|
362
356
|
page += 1
|
|
363
357
|
|
|
364
358
|
response = self.post(url, data=body.format(start=start, schema=self.ISO_SCHEMA),
|
|
365
|
-
|
|
359
|
+
headers=headers)
|
|
366
360
|
response.raise_for_status()
|
|
367
361
|
|
|
368
362
|
tree_before_transform = ET.fromstring(response.content)
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
<dcterms:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2016-12-14T18:59:02.737480</dcterms:issued>
|
|
24
24
|
<dcterms:description>Dataset 3 description</dcterms:description>
|
|
25
25
|
<dcat:keyword>Tag 1</dcat:keyword>
|
|
26
|
-
<dcat:theme rdf:resource="http://data.europa.eu/bna/c_dd313021"/>
|
|
27
26
|
<dcat:distribution rdf:resource="datasets/3/resources/1"/>
|
|
28
27
|
<dct:license>Licence Ouverte Version 2.0</dct:license>
|
|
29
28
|
<dct:accessRights rdf:resource="http://inspire.ec.europa.eu/metadata-codelist/LimitationsOnPublicAccess/INSPIRE_Directive_Article13_1e"/>
|
|
@@ -440,9 +440,6 @@ class DcatBackendTest:
|
|
|
440
440
|
assert dataset.extras["harvest"]["dct:accessRights"] == "http://inspire.ec.europa.eu/metadata-codelist/LimitationsOnPublicAccess/INSPIRE_Directive_Article13_1e"
|
|
441
441
|
assert dataset.extras["harvest"]["dct:provenance"] == ["Description de la provenance des données"]
|
|
442
442
|
|
|
443
|
-
assert 'observation-de-la-terre-et-environnement' in dataset.tags
|
|
444
|
-
assert 'hvd' in dataset.tags
|
|
445
|
-
|
|
446
443
|
dataset = Dataset.objects.get(harvest__dct_identifier='1')
|
|
447
444
|
# test html abstract description support
|
|
448
445
|
assert dataset.description == '# h1 title\n\n## h2 title\n\n **and bold text**'
|
udata/routing.py
CHANGED
|
@@ -10,7 +10,6 @@ from werkzeug.urls import url_quote
|
|
|
10
10
|
from udata import models
|
|
11
11
|
from udata.mongo import db
|
|
12
12
|
from udata.core.spatial.models import GeoZone
|
|
13
|
-
from udata.core.dataservices.models import Dataservice
|
|
14
13
|
from udata.i18n import ISO_639_1_CODES
|
|
15
14
|
|
|
16
15
|
|
|
@@ -122,10 +121,6 @@ class DatasetConverter(ModelConverter):
|
|
|
122
121
|
model = models.Dataset
|
|
123
122
|
|
|
124
123
|
|
|
125
|
-
class DataserviceConverter(ModelConverter):
|
|
126
|
-
model = Dataservice
|
|
127
|
-
|
|
128
|
-
|
|
129
124
|
class CommunityResourceConverter(ModelConverter):
|
|
130
125
|
model = models.CommunityResource
|
|
131
126
|
|
|
@@ -227,7 +222,6 @@ def init_app(app):
|
|
|
227
222
|
app.url_map.converters['pathlist'] = PathListConverter
|
|
228
223
|
app.url_map.converters['uuid'] = UUIDConverter
|
|
229
224
|
app.url_map.converters['dataset'] = DatasetConverter
|
|
230
|
-
app.url_map.converters['dataservice'] = DataserviceConverter
|
|
231
225
|
app.url_map.converters['crid'] = CommunityResourceConverter
|
|
232
226
|
app.url_map.converters['org'] = OrganizationConverter
|
|
233
227
|
app.url_map.converters['reuse'] = ReuseConverter
|
udata/settings.py
CHANGED
|
@@ -269,10 +269,7 @@ class Defaults(object):
|
|
|
269
269
|
# S3 connection details
|
|
270
270
|
S3_URL = None
|
|
271
271
|
S3_ACCESS_KEY_ID = None
|
|
272
|
-
S3_SECRET_ACCESS_KEY = None
|
|
273
|
-
|
|
274
|
-
# Specific support for hvd (map HVD categories URIs to keywords)
|
|
275
|
-
HVD_SUPPORT = True
|
|
272
|
+
S3_SECRET_ACCESS_KEY = None
|
|
276
273
|
|
|
277
274
|
ACTIVATE_TERRITORIES = False
|
|
278
275
|
# The order is important to compute parents/children, smaller first.
|