udata 8.0.1.dev29075__py2.py3-none-any.whl → 8.0.1.dev29111__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.
Potentially problematic release.
This version of udata might be problematic. Click here for more details.
- udata/core/dataset/apiv2.py +2 -0
- udata/core/dataset/models.py +1 -0
- udata/core/organization/api_fields.py +28 -3
- udata/tests/api/test_organizations_api.py +78 -5
- {udata-8.0.1.dev29075.dist-info → udata-8.0.1.dev29111.dist-info}/METADATA +3 -1
- {udata-8.0.1.dev29075.dist-info → udata-8.0.1.dev29111.dist-info}/RECORD +10 -10
- {udata-8.0.1.dev29075.dist-info → udata-8.0.1.dev29111.dist-info}/LICENSE +0 -0
- {udata-8.0.1.dev29075.dist-info → udata-8.0.1.dev29111.dist-info}/WHEEL +0 -0
- {udata-8.0.1.dev29075.dist-info → udata-8.0.1.dev29111.dist-info}/entry_points.txt +0 -0
- {udata-8.0.1.dev29075.dist-info → udata-8.0.1.dev29111.dist-info}/top_level.txt +0 -0
udata/core/dataset/apiv2.py
CHANGED
|
@@ -8,6 +8,7 @@ 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
|
|
11
12
|
from .api_fields import (
|
|
12
13
|
badge_fields,
|
|
13
14
|
org_ref_fields,
|
|
@@ -165,6 +166,7 @@ specific_resource_fields = apiv2.model('SpecificResource', {
|
|
|
165
166
|
apiv2.inherit('Badge', badge_fields)
|
|
166
167
|
apiv2.inherit('OrganizationReference', org_ref_fields)
|
|
167
168
|
apiv2.inherit('UserReference', user_ref_fields)
|
|
169
|
+
apiv2.inherit('MemberUserWithEmail', member_user_with_email_fields)
|
|
168
170
|
apiv2.inherit('Resource', resource_fields)
|
|
169
171
|
apiv2.inherit('SpatialCoverage', spatial_coverage_fields)
|
|
170
172
|
apiv2.inherit('TemporalCoverage', temporal_coverage_fields)
|
udata/core/dataset/models.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from flask import request
|
|
2
|
+
|
|
1
3
|
from udata.api import api, fields, base_reference
|
|
2
4
|
from udata.core.badges.fields import badge_fields
|
|
5
|
+
from udata.core.organization.permissions import OrganizationPrivatePermission
|
|
3
6
|
|
|
4
7
|
from .constants import ORG_ROLES, DEFAULT_ROLE, MEMBERSHIP_STATUS, BIGGEST_LOGO_SIZE
|
|
5
8
|
|
|
@@ -27,9 +30,29 @@ org_ref_fields = api.inherit('OrganizationReference', base_reference, {
|
|
|
27
30
|
|
|
28
31
|
from udata.core.user.api_fields import user_ref_fields # noqa: required
|
|
29
32
|
|
|
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
|
+
|
|
30
53
|
request_fields = api.model('MembershipRequest', {
|
|
31
54
|
'id': fields.String(readonly=True),
|
|
32
|
-
'user': fields.Nested(
|
|
55
|
+
'user': fields.Nested(member_user_with_email_fields),
|
|
33
56
|
'created': fields.ISODateTime(
|
|
34
57
|
description='The request creation date', readonly=True),
|
|
35
58
|
'status': fields.String(
|
|
@@ -40,10 +63,12 @@ request_fields = api.model('MembershipRequest', {
|
|
|
40
63
|
})
|
|
41
64
|
|
|
42
65
|
member_fields = api.model('Member', {
|
|
43
|
-
'user': fields.Nested(
|
|
66
|
+
'user': fields.Nested(member_user_with_email_fields),
|
|
44
67
|
'role': fields.String(
|
|
45
68
|
description='The member role in the organization', required=True,
|
|
46
|
-
enum=list(ORG_ROLES), default=DEFAULT_ROLE)
|
|
69
|
+
enum=list(ORG_ROLES), default=DEFAULT_ROLE),
|
|
70
|
+
'since': fields.ISODateTime(
|
|
71
|
+
description='The date the user joined the organization', readonly=True),
|
|
47
72
|
})
|
|
48
73
|
|
|
49
74
|
org_fields = api.model('Organization', {
|
|
@@ -191,8 +191,7 @@ class MembershipAPITest:
|
|
|
191
191
|
user = api.login()
|
|
192
192
|
data = {'comment': 'a comment'}
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
response = api.post(api_url, data)
|
|
194
|
+
response = api.post(url_for('api.request_membership', org=organization), data)
|
|
196
195
|
assert201(response)
|
|
197
196
|
|
|
198
197
|
organization.reload()
|
|
@@ -209,14 +208,13 @@ class MembershipAPITest:
|
|
|
209
208
|
assert request.handled_by is None
|
|
210
209
|
assert request.refusal_comment is None
|
|
211
210
|
|
|
212
|
-
def
|
|
211
|
+
def test_request_existing_pending_membership_do_not_duplicate_it(self, api):
|
|
213
212
|
user = api.login()
|
|
214
213
|
previous_request = MembershipRequest(user=user, comment='previous')
|
|
215
214
|
organization = OrganizationFactory(requests=[previous_request])
|
|
216
215
|
data = {'comment': 'a comment'}
|
|
217
216
|
|
|
218
|
-
|
|
219
|
-
response = api.post(api_url, data)
|
|
217
|
+
response = api.post(url_for('api.request_membership', org=organization), data)
|
|
220
218
|
assert200(response)
|
|
221
219
|
|
|
222
220
|
organization.reload()
|
|
@@ -233,6 +231,81 @@ class MembershipAPITest:
|
|
|
233
231
|
assert request.handled_by is None
|
|
234
232
|
assert request.refusal_comment is None
|
|
235
233
|
|
|
234
|
+
def test_get_membership_requests(self, api):
|
|
235
|
+
user = api.login()
|
|
236
|
+
applicant = UserFactory(email="thibaud@example.org")
|
|
237
|
+
membership_request = MembershipRequest(user=applicant, comment='test')
|
|
238
|
+
member = Member(user=user, role='admin')
|
|
239
|
+
organization = OrganizationFactory(
|
|
240
|
+
members=[member], requests=[membership_request])
|
|
241
|
+
|
|
242
|
+
response = api.get(url_for('api.request_membership', org=organization))
|
|
243
|
+
assert200(response)
|
|
244
|
+
|
|
245
|
+
assert len(response.json) == 1
|
|
246
|
+
assert response.json[0]['comment'] == 'test'
|
|
247
|
+
assert response.json[0]['user']['email'] == 'thibaud@example.org' # Can see email of applicant
|
|
248
|
+
|
|
249
|
+
def test_only_org_member_can_get_membership_requests(self, api):
|
|
250
|
+
api.login()
|
|
251
|
+
applicant = UserFactory(email="thibaud@example.org")
|
|
252
|
+
membership_request = MembershipRequest(user=applicant, comment='test')
|
|
253
|
+
organization = OrganizationFactory(
|
|
254
|
+
members=[], requests=[membership_request])
|
|
255
|
+
|
|
256
|
+
response = api.get(url_for('api.request_membership', org=organization))
|
|
257
|
+
assert403(response)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def test_get_members_with_or_without_email(self, api):
|
|
261
|
+
admin = Member(user=UserFactory(email="admin@example.org"), role='admin', since="2024-04-14")
|
|
262
|
+
editor = Member(user=UserFactory(email="editor@example.org"), role='editor')
|
|
263
|
+
other = UserFactory(email="other@example.org")
|
|
264
|
+
|
|
265
|
+
organization = OrganizationFactory(members=[admin, editor])
|
|
266
|
+
|
|
267
|
+
# Admin can see emails
|
|
268
|
+
api.login(admin.user)
|
|
269
|
+
response = api.get(url_for('api.organization', org=organization))
|
|
270
|
+
assert200(response)
|
|
271
|
+
|
|
272
|
+
members = response.json['members']
|
|
273
|
+
assert len(members) == 2
|
|
274
|
+
assert members[0]['role'] == 'admin'
|
|
275
|
+
assert members[0]['since'] == '2024-04-14T00:00:00+00:00'
|
|
276
|
+
assert members[0]['user']['email'] == 'admin@example.org'
|
|
277
|
+
|
|
278
|
+
assert members[1]['role'] == 'editor'
|
|
279
|
+
assert members[1]['user']['email'] == 'editor@example.org'
|
|
280
|
+
|
|
281
|
+
# Editor can see emails
|
|
282
|
+
api.login(editor.user)
|
|
283
|
+
response = api.get(url_for('api.organization', org=organization))
|
|
284
|
+
assert200(response)
|
|
285
|
+
|
|
286
|
+
members = response.json['members']
|
|
287
|
+
assert len(members) == 2
|
|
288
|
+
assert members[0]['role'] == 'admin'
|
|
289
|
+
assert members[0]['since'] == '2024-04-14T00:00:00+00:00'
|
|
290
|
+
assert members[0]['user']['email'] == 'admin@example.org'
|
|
291
|
+
|
|
292
|
+
assert members[1]['role'] == 'editor'
|
|
293
|
+
assert members[1]['user']['email'] == 'editor@example.org'
|
|
294
|
+
|
|
295
|
+
# Others cannot see emails
|
|
296
|
+
api.login(other)
|
|
297
|
+
response = api.get(url_for('api.organization', org=organization))
|
|
298
|
+
assert200(response)
|
|
299
|
+
|
|
300
|
+
members = response.json['members']
|
|
301
|
+
assert len(members) == 2
|
|
302
|
+
assert members[0]['role'] == 'admin'
|
|
303
|
+
assert members[0]['since'] == '2024-04-14T00:00:00+00:00'
|
|
304
|
+
assert members[0]['user']['email'] is None
|
|
305
|
+
|
|
306
|
+
assert members[1]['role'] == 'editor'
|
|
307
|
+
assert members[1]['user']['email'] is None
|
|
308
|
+
|
|
236
309
|
def test_accept_membership(self, api):
|
|
237
310
|
user = api.login()
|
|
238
311
|
applicant = UserFactory()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: udata
|
|
3
|
-
Version: 8.0.1.
|
|
3
|
+
Version: 8.0.1.dev29111
|
|
4
4
|
Summary: Open data portal
|
|
5
5
|
Home-page: https://github.com/opendatateam/udata
|
|
6
6
|
Author: Opendata Team
|
|
@@ -143,6 +143,8 @@ It is collectively taken care of by members of the
|
|
|
143
143
|
- Delete a user without sending mail [#3031](https://github.com/opendatateam/udata/pull/3031)
|
|
144
144
|
- Convert known HVD categories used as theme to keywords [#3014](https://github.com/opendatateam/udata/pull/3014)
|
|
145
145
|
- Allow for series in CSW ISO 19139 DCAT backend [#3028](https://github.com/opendatateam/udata/pull/3028)
|
|
146
|
+
- Add `email` to membership request list API response, add `since` to org members API responses, add `email` to members of org on show org endpoint for org's admins and editors [#3038](https://github.com/opendatateam/udata/pull/3038)
|
|
147
|
+
- Add `resources_downloads` to datasets metrics [#3042](https://github.com/opendatateam/udata/pull/3042)
|
|
146
148
|
- Fix do not override resources extras on admin during update [#3043](https://github.com/opendatateam/udata/pull/3043)
|
|
147
149
|
|
|
148
150
|
## 8.0.0 (2024-04-23)
|
|
@@ -86,7 +86,7 @@ udata/core/dataset/actions.py,sha256=3pzBg_qOR-w7fwPpTOKUHXWC9lkjALbOn1UQFmmT-s0
|
|
|
86
86
|
udata/core/dataset/activities.py,sha256=qQnHNL0hOB1IGtQl7JsnVOiUsWT0gm-pts9uDyR3bvU,1536
|
|
87
87
|
udata/core/dataset/api.py,sha256=C6EGhJswCb2hHfKigbxFQbfzpzgvWm8VD3c4O-ZQFso,28789
|
|
88
88
|
udata/core/dataset/api_fields.py,sha256=Cgd_BPlAhP0nTzocOZWWEM-LvKcgCxYE2x00oAiKFYM,15405
|
|
89
|
-
udata/core/dataset/apiv2.py,sha256=
|
|
89
|
+
udata/core/dataset/apiv2.py,sha256=NmfixLd7Q8WNEAKxpJWubD2QzsxgJwJo69z8kNtU__Y,15896
|
|
90
90
|
udata/core/dataset/commands.py,sha256=dbK7gMYH4G6pOPiYtmL3yomzg5MGqTaG97_UM9Smu_k,3712
|
|
91
91
|
udata/core/dataset/constants.py,sha256=Twml-I5mGiIdTkiDV1D4bXqi_TcNhcEc-QFxorUKHM4,3138
|
|
92
92
|
udata/core/dataset/csv.py,sha256=d6JMuvlov_vR7EN10rJa6Q03Il0PfbzMTHQIud5H8qg,3240
|
|
@@ -94,7 +94,7 @@ udata/core/dataset/events.py,sha256=DI71VfRc1eDTtgWQ3TJx5gtUw2MO0O_CVLCKLq0OIF0,
|
|
|
94
94
|
udata/core/dataset/exceptions.py,sha256=uI_NvZRZMr_MtYQBYdLD8tk-BIUeDDfMMcrWwqV7mi8,494
|
|
95
95
|
udata/core/dataset/factories.py,sha256=fHPgEUUpqGw7p7K5wGg-wA6Q0-Pc9eNbzAQK-va8zMM,9120
|
|
96
96
|
udata/core/dataset/forms.py,sha256=VJCsGtgzhQgLW-M-J4ObpQ8o6c_saC3TTc1Js33m3sQ,6188
|
|
97
|
-
udata/core/dataset/models.py,sha256=
|
|
97
|
+
udata/core/dataset/models.py,sha256=q6AknSHYNjeUyVKoFgxEA0r9lSvMa_a4tJ3fLOzL03M,36053
|
|
98
98
|
udata/core/dataset/permissions.py,sha256=3F2J7le3_rEYNhh88o3hSRWHAAt01_yHJM6RPmvCrRo,1090
|
|
99
99
|
udata/core/dataset/preview.py,sha256=puPKT3fBD7ezAcT6owh0JK1_rGNDFZOqgT223qGn3LY,2597
|
|
100
100
|
udata/core/dataset/rdf.py,sha256=y4XBB8nlm_xmqwWGrtiRJj3UZT8DtzCREw4jchOaGsg,23731
|
|
@@ -133,7 +133,7 @@ udata/core/metrics/tasks.py,sha256=Z7La3-zPB5j6qJoPKr_MgjNZhqscZCmNLPa711ZBkdY,7
|
|
|
133
133
|
udata/core/organization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
134
134
|
udata/core/organization/activities.py,sha256=fOBujmduVoTxJph2C6Z4qHeQHOaJT9IsZooEDCWC4BA,1140
|
|
135
135
|
udata/core/organization/api.py,sha256=K9Lnps_gxxt_z1ImLZDBnY1eeh6Zpl7x50YoXcPzJ_k,17479
|
|
136
|
-
udata/core/organization/api_fields.py,sha256=
|
|
136
|
+
udata/core/organization/api_fields.py,sha256=Xotv1Eqd3fnxhlC0cssSEG4mfiRfLKPQK_k07V1hmDc,6370
|
|
137
137
|
udata/core/organization/apiv2.py,sha256=VAU_y9Zz-VhBgS-LWVbGOEZdSt3b44nZd5bzTV2wU8g,3206
|
|
138
138
|
udata/core/organization/commands.py,sha256=FaSYxyWfQDR5tWvrAXmwcF2VMREOC13XTK8DD4vp_sY,1623
|
|
139
139
|
udata/core/organization/constants.py,sha256=XGVnItrJTG0hcVKRK5sPmx44KHC9r_EKtj_y0MmBt0o,563
|
|
@@ -592,7 +592,7 @@ udata/tests/api/test_datasets_api.py,sha256=zqRtC61NvYUNum4kBTjA1W87JAIobA4k564r
|
|
|
592
592
|
udata/tests/api/test_fields.py,sha256=OW85Z5MES5HeWOpapeem8OvR1cIcrqW-xMWpdZO4LZ8,1033
|
|
593
593
|
udata/tests/api/test_follow_api.py,sha256=0h54P_Dfbo07u6tg0Rbai1WWgWb19ZLN2HGv4oLCWfg,3383
|
|
594
594
|
udata/tests/api/test_me_api.py,sha256=8OthqVYQKZrFoGuJ7zAvoLJx1IclPNzPdD5Tnzmh3rM,14163
|
|
595
|
-
udata/tests/api/test_organizations_api.py,sha256=
|
|
595
|
+
udata/tests/api/test_organizations_api.py,sha256=buE1KdGIoJxfsj-ofz5CkMtgnARi38bXWR1jgPRkMzo,35732
|
|
596
596
|
udata/tests/api/test_reuses_api.py,sha256=GSoZ6SBRdMg6o0xKSQWtCSfvzqz_vZxERU567Rq1_GY,17009
|
|
597
597
|
udata/tests/api/test_swagger.py,sha256=tLg452rCD5Q0AgFXOVZKMM6jGiWwC5diX5PxbdYni0o,760
|
|
598
598
|
udata/tests/api/test_tags_api.py,sha256=xSIx_x5gqKz6BJCXKEsTqA_CR4BF1nG5NxEyfp9dy0o,2579
|
|
@@ -681,9 +681,9 @@ udata/translations/pt/LC_MESSAGES/udata.mo,sha256=uttB2K8VsqzkEQG-5HfTtFms_3LtV9
|
|
|
681
681
|
udata/translations/pt/LC_MESSAGES/udata.po,sha256=8Ql1Lp7Z9KLnvp-qRxw-NhFu1p35Xj-q6Jg9JHsYhcw,43733
|
|
682
682
|
udata/translations/sr/LC_MESSAGES/udata.mo,sha256=US8beNIMPxP5h-zD_jfP1TheDDd4DdRVS5UIiY5XVZ8,28553
|
|
683
683
|
udata/translations/sr/LC_MESSAGES/udata.po,sha256=TM0yMDvKRljyOzgZZMlTX6OfpF6OC4Ngf_9Zc8n6ayA,50313
|
|
684
|
-
udata-8.0.1.
|
|
685
|
-
udata-8.0.1.
|
|
686
|
-
udata-8.0.1.
|
|
687
|
-
udata-8.0.1.
|
|
688
|
-
udata-8.0.1.
|
|
689
|
-
udata-8.0.1.
|
|
684
|
+
udata-8.0.1.dev29111.dist-info/LICENSE,sha256=V8j_M8nAz8PvAOZQocyRDX7keai8UJ9skgmnwqETmdY,34520
|
|
685
|
+
udata-8.0.1.dev29111.dist-info/METADATA,sha256=8XbLmQfd-YkSgFDbbzJshQ6nlUUnYZ9btLKZfcCfteI,123154
|
|
686
|
+
udata-8.0.1.dev29111.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
687
|
+
udata-8.0.1.dev29111.dist-info/entry_points.txt,sha256=3SKiqVy4HUqxf6iWspgMqH8d88Htk6KoLbG1BU-UddQ,451
|
|
688
|
+
udata-8.0.1.dev29111.dist-info/top_level.txt,sha256=39OCg-VWFWOq4gCKnjKNu-s3OwFlZIu_dVH8Gl6ndHw,12
|
|
689
|
+
udata-8.0.1.dev29111.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|