udata 9.1.2.dev30355__py2.py3-none-any.whl → 9.1.2.dev30454__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.
- tasks/__init__.py +109 -107
- tasks/helpers.py +18 -18
- udata/__init__.py +4 -4
- udata/admin/views.py +5 -5
- udata/api/__init__.py +111 -134
- udata/api/commands.py +45 -37
- udata/api/errors.py +5 -4
- udata/api/fields.py +23 -21
- udata/api/oauth2.py +55 -74
- udata/api/parsers.py +15 -15
- udata/api/signals.py +1 -1
- udata/api_fields.py +137 -89
- udata/app.py +58 -55
- udata/assets.py +5 -5
- udata/auth/__init__.py +37 -26
- udata/auth/forms.py +23 -15
- udata/auth/helpers.py +1 -1
- udata/auth/mails.py +3 -3
- udata/auth/password_validation.py +19 -15
- udata/auth/views.py +94 -68
- udata/commands/__init__.py +71 -69
- udata/commands/cache.py +7 -7
- udata/commands/db.py +201 -140
- udata/commands/dcat.py +36 -30
- udata/commands/fixtures.py +100 -84
- udata/commands/images.py +21 -20
- udata/commands/info.py +17 -20
- udata/commands/init.py +10 -10
- udata/commands/purge.py +12 -13
- udata/commands/serve.py +41 -29
- udata/commands/static.py +16 -18
- udata/commands/test.py +20 -20
- udata/commands/tests/fixtures.py +26 -24
- udata/commands/worker.py +31 -33
- udata/core/__init__.py +12 -12
- udata/core/activity/__init__.py +0 -1
- udata/core/activity/api.py +59 -49
- udata/core/activity/models.py +28 -26
- udata/core/activity/signals.py +1 -1
- udata/core/activity/tasks.py +16 -10
- udata/core/badges/api.py +6 -6
- udata/core/badges/commands.py +14 -13
- udata/core/badges/fields.py +8 -5
- udata/core/badges/forms.py +7 -4
- udata/core/badges/models.py +16 -31
- udata/core/badges/permissions.py +1 -3
- udata/core/badges/signals.py +2 -2
- udata/core/badges/tasks.py +3 -2
- udata/core/badges/tests/test_commands.py +10 -10
- udata/core/badges/tests/test_model.py +24 -31
- udata/core/contact_point/api.py +19 -18
- udata/core/contact_point/api_fields.py +21 -14
- udata/core/contact_point/factories.py +2 -2
- udata/core/contact_point/forms.py +7 -6
- udata/core/contact_point/models.py +3 -5
- udata/core/dataservices/api.py +26 -21
- udata/core/dataservices/factories.py +13 -11
- udata/core/dataservices/models.py +35 -40
- udata/core/dataservices/permissions.py +4 -4
- udata/core/dataservices/rdf.py +40 -17
- udata/core/dataservices/tasks.py +4 -3
- udata/core/dataset/actions.py +10 -10
- udata/core/dataset/activities.py +21 -23
- udata/core/dataset/api.py +321 -298
- udata/core/dataset/api_fields.py +443 -271
- udata/core/dataset/apiv2.py +305 -229
- udata/core/dataset/commands.py +38 -36
- udata/core/dataset/constants.py +61 -54
- udata/core/dataset/csv.py +70 -74
- udata/core/dataset/events.py +39 -32
- udata/core/dataset/exceptions.py +8 -4
- udata/core/dataset/factories.py +57 -65
- udata/core/dataset/forms.py +87 -63
- udata/core/dataset/models.py +336 -280
- udata/core/dataset/permissions.py +9 -6
- udata/core/dataset/preview.py +15 -17
- udata/core/dataset/rdf.py +156 -122
- udata/core/dataset/search.py +92 -77
- udata/core/dataset/signals.py +1 -1
- udata/core/dataset/tasks.py +63 -54
- udata/core/discussions/actions.py +5 -5
- udata/core/discussions/api.py +124 -120
- udata/core/discussions/factories.py +2 -2
- udata/core/discussions/forms.py +9 -7
- udata/core/discussions/metrics.py +1 -3
- udata/core/discussions/models.py +25 -24
- udata/core/discussions/notifications.py +18 -14
- udata/core/discussions/permissions.py +3 -3
- udata/core/discussions/signals.py +4 -4
- udata/core/discussions/tasks.py +24 -28
- udata/core/followers/api.py +32 -33
- udata/core/followers/models.py +9 -9
- udata/core/followers/signals.py +3 -3
- udata/core/jobs/actions.py +7 -7
- udata/core/jobs/api.py +99 -92
- udata/core/jobs/commands.py +48 -49
- udata/core/jobs/forms.py +11 -11
- udata/core/jobs/models.py +6 -6
- udata/core/metrics/__init__.py +2 -2
- udata/core/metrics/commands.py +34 -30
- udata/core/metrics/models.py +2 -4
- udata/core/metrics/signals.py +1 -1
- udata/core/metrics/tasks.py +3 -3
- udata/core/organization/activities.py +12 -15
- udata/core/organization/api.py +167 -174
- udata/core/organization/api_fields.py +183 -124
- udata/core/organization/apiv2.py +32 -32
- udata/core/organization/commands.py +20 -22
- udata/core/organization/constants.py +11 -11
- udata/core/organization/csv.py +17 -15
- udata/core/organization/factories.py +8 -11
- udata/core/organization/forms.py +32 -26
- udata/core/organization/metrics.py +2 -1
- udata/core/organization/models.py +87 -67
- udata/core/organization/notifications.py +18 -14
- udata/core/organization/permissions.py +10 -11
- udata/core/organization/rdf.py +14 -14
- udata/core/organization/search.py +30 -28
- udata/core/organization/signals.py +7 -7
- udata/core/organization/tasks.py +42 -61
- udata/core/owned.py +38 -27
- udata/core/post/api.py +82 -81
- udata/core/post/constants.py +8 -5
- udata/core/post/factories.py +4 -4
- udata/core/post/forms.py +13 -14
- udata/core/post/models.py +20 -22
- udata/core/post/tests/test_api.py +30 -32
- udata/core/reports/api.py +8 -7
- udata/core/reports/constants.py +1 -3
- udata/core/reports/models.py +10 -10
- udata/core/reuse/activities.py +15 -19
- udata/core/reuse/api.py +123 -126
- udata/core/reuse/api_fields.py +120 -85
- udata/core/reuse/apiv2.py +11 -10
- udata/core/reuse/constants.py +23 -23
- udata/core/reuse/csv.py +18 -18
- udata/core/reuse/factories.py +5 -9
- udata/core/reuse/forms.py +24 -21
- udata/core/reuse/models.py +55 -51
- udata/core/reuse/permissions.py +2 -2
- udata/core/reuse/search.py +49 -46
- udata/core/reuse/signals.py +1 -1
- udata/core/reuse/tasks.py +4 -5
- udata/core/site/api.py +47 -50
- udata/core/site/factories.py +2 -2
- udata/core/site/forms.py +4 -5
- udata/core/site/models.py +94 -63
- udata/core/site/rdf.py +14 -14
- udata/core/spam/api.py +16 -9
- udata/core/spam/constants.py +4 -4
- udata/core/spam/fields.py +13 -7
- udata/core/spam/models.py +27 -20
- udata/core/spam/signals.py +1 -1
- udata/core/spam/tests/test_spam.py +6 -5
- udata/core/spatial/api.py +72 -80
- udata/core/spatial/api_fields.py +73 -58
- udata/core/spatial/commands.py +67 -64
- udata/core/spatial/constants.py +3 -3
- udata/core/spatial/factories.py +37 -54
- udata/core/spatial/forms.py +27 -26
- udata/core/spatial/geoids.py +17 -17
- udata/core/spatial/models.py +43 -47
- udata/core/spatial/tasks.py +2 -1
- udata/core/spatial/tests/test_api.py +115 -130
- udata/core/spatial/tests/test_fields.py +74 -77
- udata/core/spatial/tests/test_geoid.py +22 -22
- udata/core/spatial/tests/test_models.py +5 -7
- udata/core/spatial/translations.py +16 -16
- udata/core/storages/__init__.py +16 -18
- udata/core/storages/api.py +66 -64
- udata/core/storages/tasks.py +7 -7
- udata/core/storages/utils.py +15 -15
- udata/core/storages/views.py +5 -6
- udata/core/tags/api.py +17 -14
- udata/core/tags/csv.py +4 -4
- udata/core/tags/models.py +8 -5
- udata/core/tags/tasks.py +11 -13
- udata/core/tags/views.py +4 -4
- udata/core/topic/api.py +84 -73
- udata/core/topic/apiv2.py +157 -127
- udata/core/topic/factories.py +3 -4
- udata/core/topic/forms.py +12 -14
- udata/core/topic/models.py +14 -19
- udata/core/topic/parsers.py +26 -26
- udata/core/user/activities.py +30 -29
- udata/core/user/api.py +151 -152
- udata/core/user/api_fields.py +132 -100
- udata/core/user/apiv2.py +7 -7
- udata/core/user/commands.py +38 -38
- udata/core/user/factories.py +8 -9
- udata/core/user/forms.py +14 -11
- udata/core/user/metrics.py +2 -2
- udata/core/user/models.py +68 -69
- udata/core/user/permissions.py +4 -5
- udata/core/user/rdf.py +7 -8
- udata/core/user/tasks.py +2 -2
- udata/core/user/tests/test_user_model.py +24 -16
- udata/cors.py +99 -0
- udata/db/tasks.py +2 -1
- udata/entrypoints.py +35 -31
- udata/errors.py +2 -1
- udata/event/values.py +6 -6
- udata/factories.py +2 -2
- udata/features/identicon/api.py +5 -6
- udata/features/identicon/backends.py +48 -55
- udata/features/identicon/tests/test_backends.py +4 -5
- udata/features/notifications/__init__.py +0 -1
- udata/features/notifications/actions.py +9 -9
- udata/features/notifications/api.py +17 -13
- udata/features/territories/__init__.py +12 -10
- udata/features/territories/api.py +14 -15
- udata/features/territories/models.py +23 -28
- udata/features/transfer/actions.py +8 -11
- udata/features/transfer/api.py +84 -77
- udata/features/transfer/factories.py +2 -1
- udata/features/transfer/models.py +11 -12
- udata/features/transfer/notifications.py +19 -15
- udata/features/transfer/permissions.py +5 -5
- udata/forms/__init__.py +5 -2
- udata/forms/fields.py +164 -172
- udata/forms/validators.py +19 -22
- udata/forms/widgets.py +9 -13
- udata/frontend/__init__.py +31 -26
- udata/frontend/csv.py +68 -58
- udata/frontend/markdown.py +40 -44
- udata/harvest/actions.py +89 -77
- udata/harvest/api.py +294 -238
- udata/harvest/backends/__init__.py +4 -4
- udata/harvest/backends/base.py +128 -111
- udata/harvest/backends/dcat.py +80 -66
- udata/harvest/commands.py +56 -60
- udata/harvest/csv.py +8 -8
- udata/harvest/exceptions.py +6 -3
- udata/harvest/filters.py +24 -23
- udata/harvest/forms.py +27 -28
- udata/harvest/models.py +88 -80
- udata/harvest/notifications.py +15 -10
- udata/harvest/signals.py +13 -13
- udata/harvest/tasks.py +11 -10
- udata/harvest/tests/factories.py +23 -24
- udata/harvest/tests/test_actions.py +136 -166
- udata/harvest/tests/test_api.py +220 -214
- udata/harvest/tests/test_base_backend.py +117 -112
- udata/harvest/tests/test_dcat_backend.py +380 -308
- udata/harvest/tests/test_filters.py +33 -22
- udata/harvest/tests/test_models.py +11 -14
- udata/harvest/tests/test_notifications.py +6 -7
- udata/harvest/tests/test_tasks.py +7 -6
- udata/i18n.py +237 -78
- udata/linkchecker/backends.py +5 -11
- udata/linkchecker/checker.py +23 -22
- udata/linkchecker/commands.py +4 -6
- udata/linkchecker/models.py +6 -6
- udata/linkchecker/tasks.py +18 -20
- udata/mail.py +21 -21
- udata/migrations/2020-07-24-remove-s-from-scope-oauth.py +9 -8
- udata/migrations/2020-08-24-add-fs-filename.py +9 -8
- udata/migrations/2020-09-28-update-reuses-datasets-metrics.py +5 -4
- udata/migrations/2020-10-16-migrate-ods-resources.py +9 -10
- udata/migrations/2021-04-08-update-schema-with-new-structure.py +8 -7
- udata/migrations/2021-05-27-fix-default-schema-name.py +7 -6
- udata/migrations/2021-07-05-remove-unused-badges.py +17 -15
- udata/migrations/2021-07-07-update-schema-for-community-resources.py +7 -6
- udata/migrations/2021-08-17-follow-integrity.py +5 -4
- udata/migrations/2021-08-17-harvest-integrity.py +13 -12
- udata/migrations/2021-08-17-oauth2client-integrity.py +5 -4
- udata/migrations/2021-08-17-transfer-integrity.py +5 -4
- udata/migrations/2021-08-17-users-integrity.py +9 -8
- udata/migrations/2021-12-14-reuse-topics.py +7 -6
- udata/migrations/2022-04-21-improve-extension-detection.py +8 -7
- udata/migrations/2022-09-22-clean-inactive-harvest-datasets.py +16 -14
- udata/migrations/2022-10-10-add-fs_uniquifier-to-user-model.py +6 -6
- udata/migrations/2022-10-10-migrate-harvest-extras.py +36 -26
- udata/migrations/2023-02-08-rename-internal-dates.py +46 -28
- udata/migrations/2024-01-29-fix-reuse-and-dataset-with-private-None.py +10 -8
- udata/migrations/2024-03-22-migrate-activity-kwargs-to-extras.py +6 -4
- udata/migrations/2024-06-11-fix-reuse-datasets-references.py +7 -6
- udata/migrations/__init__.py +123 -105
- udata/models/__init__.py +4 -4
- udata/mongo/__init__.py +13 -11
- udata/mongo/badges_field.py +3 -2
- udata/mongo/datetime_fields.py +13 -12
- udata/mongo/document.py +17 -16
- udata/mongo/engine.py +15 -16
- udata/mongo/errors.py +2 -1
- udata/mongo/extras_fields.py +30 -20
- udata/mongo/queryset.py +12 -12
- udata/mongo/slug_fields.py +38 -28
- udata/mongo/taglist_field.py +1 -2
- udata/mongo/url_field.py +5 -5
- udata/mongo/uuid_fields.py +4 -3
- udata/notifications/__init__.py +1 -1
- udata/notifications/mattermost.py +10 -9
- udata/rdf.py +167 -188
- udata/routing.py +40 -45
- udata/search/__init__.py +18 -19
- udata/search/adapter.py +17 -16
- udata/search/commands.py +44 -51
- udata/search/fields.py +13 -20
- udata/search/query.py +23 -18
- udata/search/result.py +9 -10
- udata/sentry.py +21 -19
- udata/settings.py +262 -198
- udata/sitemap.py +8 -6
- udata/storage/s3.py +20 -13
- udata/tags.py +4 -5
- udata/tasks.py +43 -42
- udata/tests/__init__.py +9 -6
- udata/tests/api/__init__.py +8 -6
- udata/tests/api/test_auth_api.py +395 -321
- udata/tests/api/test_base_api.py +33 -35
- udata/tests/api/test_contact_points.py +7 -9
- udata/tests/api/test_dataservices_api.py +211 -158
- udata/tests/api/test_datasets_api.py +823 -812
- udata/tests/api/test_follow_api.py +13 -15
- udata/tests/api/test_me_api.py +95 -112
- udata/tests/api/test_organizations_api.py +301 -339
- udata/tests/api/test_reports_api.py +35 -25
- udata/tests/api/test_reuses_api.py +134 -139
- udata/tests/api/test_swagger.py +5 -5
- udata/tests/api/test_tags_api.py +18 -25
- udata/tests/api/test_topics_api.py +94 -94
- udata/tests/api/test_transfer_api.py +53 -48
- udata/tests/api/test_user_api.py +128 -141
- udata/tests/apiv2/test_datasets.py +290 -198
- udata/tests/apiv2/test_me_api.py +10 -11
- udata/tests/apiv2/test_organizations.py +56 -74
- udata/tests/apiv2/test_swagger.py +5 -5
- udata/tests/apiv2/test_topics.py +69 -87
- udata/tests/cli/test_cli_base.py +8 -8
- udata/tests/cli/test_db_cli.py +21 -19
- udata/tests/dataservice/test_dataservice_tasks.py +8 -12
- udata/tests/dataset/test_csv_adapter.py +44 -35
- udata/tests/dataset/test_dataset_actions.py +2 -3
- udata/tests/dataset/test_dataset_commands.py +7 -8
- udata/tests/dataset/test_dataset_events.py +36 -29
- udata/tests/dataset/test_dataset_model.py +224 -217
- udata/tests/dataset/test_dataset_rdf.py +142 -131
- udata/tests/dataset/test_dataset_tasks.py +15 -15
- udata/tests/dataset/test_resource_preview.py +10 -13
- udata/tests/features/territories/__init__.py +9 -13
- udata/tests/features/territories/test_territories_api.py +71 -91
- udata/tests/forms/test_basic_fields.py +7 -7
- udata/tests/forms/test_current_user_field.py +39 -66
- udata/tests/forms/test_daterange_field.py +31 -39
- udata/tests/forms/test_dict_field.py +28 -26
- udata/tests/forms/test_extras_fields.py +102 -76
- udata/tests/forms/test_form_field.py +8 -8
- udata/tests/forms/test_image_field.py +33 -26
- udata/tests/forms/test_model_field.py +134 -123
- udata/tests/forms/test_model_list_field.py +7 -7
- udata/tests/forms/test_nested_model_list_field.py +117 -79
- udata/tests/forms/test_publish_as_field.py +36 -65
- udata/tests/forms/test_reference_field.py +34 -53
- udata/tests/forms/test_user_forms.py +23 -21
- udata/tests/forms/test_uuid_field.py +6 -10
- udata/tests/frontend/__init__.py +9 -6
- udata/tests/frontend/test_auth.py +7 -6
- udata/tests/frontend/test_csv.py +81 -96
- udata/tests/frontend/test_hooks.py +43 -43
- udata/tests/frontend/test_markdown.py +211 -191
- udata/tests/helpers.py +32 -37
- udata/tests/models.py +2 -2
- udata/tests/organization/test_csv_adapter.py +21 -16
- udata/tests/organization/test_notifications.py +11 -18
- udata/tests/organization/test_organization_model.py +13 -13
- udata/tests/organization/test_organization_rdf.py +29 -22
- udata/tests/organization/test_organization_tasks.py +16 -17
- udata/tests/plugin.py +79 -73
- udata/tests/reuse/test_reuse_model.py +21 -21
- udata/tests/reuse/test_reuse_task.py +11 -13
- udata/tests/search/__init__.py +11 -12
- udata/tests/search/test_adapter.py +60 -70
- udata/tests/search/test_query.py +16 -16
- udata/tests/search/test_results.py +10 -7
- udata/tests/site/test_site_api.py +11 -16
- udata/tests/site/test_site_metrics.py +20 -30
- udata/tests/site/test_site_model.py +4 -5
- udata/tests/site/test_site_rdf.py +94 -78
- udata/tests/test_activity.py +17 -17
- udata/tests/test_cors.py +62 -0
- udata/tests/test_discussions.py +292 -299
- udata/tests/test_i18n.py +37 -40
- udata/tests/test_linkchecker.py +91 -85
- udata/tests/test_mail.py +13 -17
- udata/tests/test_migrations.py +219 -180
- udata/tests/test_model.py +164 -157
- udata/tests/test_notifications.py +17 -17
- udata/tests/test_owned.py +14 -14
- udata/tests/test_rdf.py +25 -23
- udata/tests/test_routing.py +89 -93
- udata/tests/test_storages.py +137 -128
- udata/tests/test_tags.py +44 -46
- udata/tests/test_topics.py +7 -7
- udata/tests/test_transfer.py +42 -49
- udata/tests/test_uris.py +160 -161
- udata/tests/test_utils.py +79 -71
- udata/tests/user/test_user_rdf.py +5 -9
- udata/tests/workers/test_jobs_commands.py +57 -58
- udata/tests/workers/test_tasks_routing.py +23 -29
- udata/tests/workers/test_workers_api.py +125 -131
- udata/tests/workers/test_workers_helpers.py +6 -6
- udata/tracking.py +4 -6
- udata/uris.py +45 -46
- udata/utils.py +68 -66
- udata/wsgi.py +1 -1
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/METADATA +7 -3
- udata-9.1.2.dev30454.dist-info/RECORD +706 -0
- udata-9.1.2.dev30355.dist-info/RECORD +0 -704
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/LICENSE +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/WHEEL +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/entry_points.txt +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/top_level.txt +0 -0
|
@@ -2,16 +2,16 @@ from blinker import Namespace
|
|
|
2
2
|
|
|
3
3
|
namespace = Namespace()
|
|
4
4
|
|
|
5
|
-
organization_created = namespace.signal(
|
|
5
|
+
organization_created = namespace.signal("organization-created")
|
|
6
6
|
|
|
7
|
-
organization_updated = namespace.signal(
|
|
7
|
+
organization_updated = namespace.signal("organization-updated")
|
|
8
8
|
|
|
9
|
-
organization_deleted = namespace.signal(
|
|
9
|
+
organization_deleted = namespace.signal("organization-deleted")
|
|
10
10
|
|
|
11
|
-
new_member = namespace.signal(
|
|
11
|
+
new_member = namespace.signal("new-member")
|
|
12
12
|
|
|
13
|
-
new_membership_request = namespace.signal(
|
|
13
|
+
new_membership_request = namespace.signal("new-membership-request")
|
|
14
14
|
|
|
15
|
-
membership_accepted = namespace.signal(
|
|
15
|
+
membership_accepted = namespace.signal("membership-accepted")
|
|
16
16
|
|
|
17
|
-
membership_refused = namespace.signal(
|
|
17
|
+
membership_refused = namespace.signal("membership-refused")
|
udata/core/organization/tasks.py
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
from udata import mail
|
|
2
|
-
from udata.i18n import lazy_gettext as _
|
|
3
2
|
from udata.core import storages
|
|
4
|
-
from udata.models import Follow, Activity, Dataset, Transfer, ContactPoint
|
|
5
|
-
from udata.search import reindex
|
|
6
|
-
from udata.tasks import job, task, get_logger
|
|
7
|
-
|
|
8
3
|
from udata.core.badges.tasks import notify_new_badge
|
|
4
|
+
from udata.i18n import lazy_gettext as _
|
|
5
|
+
from udata.models import Activity, ContactPoint, Dataset, Follow, Transfer
|
|
6
|
+
from udata.search import reindex
|
|
7
|
+
from udata.tasks import get_logger, job, task
|
|
9
8
|
|
|
9
|
+
from .constants import ASSOCIATION, CERTIFIED, COMPANY, LOCAL_AUTHORITY, PUBLIC_SERVICE
|
|
10
10
|
from .models import Organization
|
|
11
|
-
from .constants import CERTIFIED, PUBLIC_SERVICE, COMPANY, ASSOCIATION, LOCAL_AUTHORITY
|
|
12
11
|
|
|
13
12
|
log = get_logger(__name__)
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
@job(
|
|
15
|
+
@job("purge-organizations")
|
|
17
16
|
def purge_organizations(self):
|
|
18
17
|
for organization in Organization.objects(deleted__ne=None):
|
|
19
|
-
log.info(f
|
|
18
|
+
log.info(f"Purging organization {organization}")
|
|
20
19
|
# Remove followers
|
|
21
20
|
Follow.objects(following=organization).delete()
|
|
22
21
|
# Remove activity
|
|
@@ -43,28 +42,27 @@ def purge_organizations(self):
|
|
|
43
42
|
reindex(Dataset.__name__, str(id))
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
@task(route=
|
|
45
|
+
@task(route="high.mail")
|
|
47
46
|
def notify_membership_request(org_id, request_id):
|
|
48
47
|
org = Organization.objects.get(pk=org_id)
|
|
49
48
|
request = next((r for r in org.requests if str(r.id) == request_id), None)
|
|
50
49
|
|
|
51
|
-
recipients = [m.user for m in org.by_role(
|
|
50
|
+
recipients = [m.user for m in org.by_role("admin")]
|
|
52
51
|
mail.send(
|
|
53
|
-
_(
|
|
54
|
-
|
|
52
|
+
_("New membership request"), recipients, "membership_request", org=org, request=request
|
|
53
|
+
)
|
|
55
54
|
|
|
56
55
|
|
|
57
|
-
@task(route=
|
|
56
|
+
@task(route="high.mail")
|
|
58
57
|
def notify_membership_response(org_id, request_id):
|
|
59
58
|
org = Organization.objects.get(pk=org_id)
|
|
60
59
|
request = next((r for r in org.requests if str(r.id) == request_id), None)
|
|
61
60
|
|
|
62
|
-
if request.status ==
|
|
63
|
-
subject = _('You are now a member of the organization "%(org)s"',
|
|
64
|
-
|
|
65
|
-
template = 'new_member'
|
|
61
|
+
if request.status == "accepted":
|
|
62
|
+
subject = _('You are now a member of the organization "%(org)s"', org=org)
|
|
63
|
+
template = "new_member"
|
|
66
64
|
else:
|
|
67
|
-
subject, template = _(
|
|
65
|
+
subject, template = _("Membership refused"), "membership_refused"
|
|
68
66
|
mail.send(subject, request.user, template, org=org, request=request)
|
|
69
67
|
|
|
70
68
|
|
|
@@ -74,104 +72,87 @@ def notify_new_member(org_id, email):
|
|
|
74
72
|
member = next((m for m in org.members if m.user.email == email), None)
|
|
75
73
|
|
|
76
74
|
subject = _('You are now a member of the organization "%(org)s"', org=org)
|
|
77
|
-
mail.send(subject, member.user,
|
|
75
|
+
mail.send(subject, member.user, "new_member", org=org)
|
|
78
76
|
|
|
79
77
|
|
|
80
78
|
@notify_new_badge(Organization, CERTIFIED)
|
|
81
79
|
def notify_badge_certified(org_id):
|
|
82
|
-
|
|
80
|
+
"""
|
|
83
81
|
Send an email when a `CERTIFIED` badge is added to an `Organization`
|
|
84
|
-
|
|
82
|
+
"""
|
|
85
83
|
org = Organization.objects.get(pk=org_id)
|
|
86
84
|
recipients = [member.user for member in org.members]
|
|
87
|
-
subject = _(
|
|
88
|
-
'Your organization "%(name)s" has been certified',
|
|
89
|
-
name=org.name
|
|
90
|
-
)
|
|
85
|
+
subject = _('Your organization "%(name)s" has been certified', name=org.name)
|
|
91
86
|
mail.send(
|
|
92
87
|
subject,
|
|
93
88
|
recipients,
|
|
94
|
-
|
|
89
|
+
"badge_added_certified",
|
|
95
90
|
organization=org,
|
|
96
|
-
badge=org.get_badge(CERTIFIED)
|
|
91
|
+
badge=org.get_badge(CERTIFIED),
|
|
97
92
|
)
|
|
98
93
|
|
|
99
94
|
|
|
100
95
|
@notify_new_badge(Organization, PUBLIC_SERVICE)
|
|
101
96
|
def notify_badge_public_service(org_id):
|
|
102
|
-
|
|
97
|
+
"""
|
|
103
98
|
Send an email when a `PUBLIC_SERVICE` badge is added to an `Organization`
|
|
104
|
-
|
|
99
|
+
"""
|
|
105
100
|
org = Organization.objects.get(pk=org_id)
|
|
106
101
|
recipients = [member.user for member in org.members]
|
|
107
|
-
subject = _(
|
|
108
|
-
'Your organization "%(name)s" has been identified as public service',
|
|
109
|
-
name=org.name
|
|
110
|
-
)
|
|
102
|
+
subject = _('Your organization "%(name)s" has been identified as public service', name=org.name)
|
|
111
103
|
mail.send(
|
|
112
104
|
subject,
|
|
113
105
|
recipients,
|
|
114
|
-
|
|
106
|
+
"badge_added_public_service",
|
|
115
107
|
organization=org,
|
|
116
|
-
badge=org.get_badge(PUBLIC_SERVICE)
|
|
108
|
+
badge=org.get_badge(PUBLIC_SERVICE),
|
|
117
109
|
)
|
|
118
110
|
|
|
119
111
|
|
|
120
112
|
@notify_new_badge(Organization, COMPANY)
|
|
121
113
|
def notify_badge_company(org_id):
|
|
122
|
-
|
|
114
|
+
"""
|
|
123
115
|
Send an email when a `COMPANY` badge is added to an `Organization`
|
|
124
|
-
|
|
116
|
+
"""
|
|
125
117
|
org = Organization.objects.get(pk=org_id)
|
|
126
118
|
recipients = [member.user for member in org.members]
|
|
127
|
-
subject = _(
|
|
128
|
-
'Your organization "%(name)s" has been identified as a company',
|
|
129
|
-
name=org.name
|
|
130
|
-
)
|
|
119
|
+
subject = _('Your organization "%(name)s" has been identified as a company', name=org.name)
|
|
131
120
|
mail.send(
|
|
132
|
-
subject,
|
|
133
|
-
recipients,
|
|
134
|
-
'badge_added_company',
|
|
135
|
-
organization=org,
|
|
136
|
-
badge=org.get_badge(COMPANY)
|
|
121
|
+
subject, recipients, "badge_added_company", organization=org, badge=org.get_badge(COMPANY)
|
|
137
122
|
)
|
|
138
123
|
|
|
139
124
|
|
|
140
125
|
@notify_new_badge(Organization, ASSOCIATION)
|
|
141
126
|
def notify_badge_association(org_id):
|
|
142
|
-
|
|
127
|
+
"""
|
|
143
128
|
Send an email when a `ASSOCIATION` badge is added to an `Organization`
|
|
144
|
-
|
|
129
|
+
"""
|
|
145
130
|
org = Organization.objects.get(pk=org_id)
|
|
146
131
|
recipients = [member.user for member in org.members]
|
|
147
|
-
subject = _(
|
|
148
|
-
'Your organization "%(name)s" has been identified as an association',
|
|
149
|
-
name=org.name
|
|
150
|
-
)
|
|
132
|
+
subject = _('Your organization "%(name)s" has been identified as an association', name=org.name)
|
|
151
133
|
mail.send(
|
|
152
134
|
subject,
|
|
153
135
|
recipients,
|
|
154
|
-
|
|
136
|
+
"badge_added_association",
|
|
155
137
|
organization=org,
|
|
156
|
-
badge=org.get_badge(ASSOCIATION)
|
|
138
|
+
badge=org.get_badge(ASSOCIATION),
|
|
157
139
|
)
|
|
158
140
|
|
|
159
141
|
|
|
160
142
|
@notify_new_badge(Organization, LOCAL_AUTHORITY)
|
|
161
143
|
def notify_badge_local_authority(org_id):
|
|
162
|
-
|
|
144
|
+
"""
|
|
163
145
|
Send an email when a `LOCAL_AUTHORITY` badge is added to an `Organization`
|
|
164
|
-
|
|
146
|
+
"""
|
|
165
147
|
org = Organization.objects.get(pk=org_id)
|
|
166
148
|
recipients = [member.user for member in org.members]
|
|
167
149
|
subject = _(
|
|
168
|
-
'Your organization "%(name)s" has been identified as a local authority',
|
|
169
|
-
name=org.name
|
|
150
|
+
'Your organization "%(name)s" has been identified as a local authority', name=org.name
|
|
170
151
|
)
|
|
171
152
|
mail.send(
|
|
172
153
|
subject,
|
|
173
154
|
recipients,
|
|
174
|
-
|
|
155
|
+
"badge_added_local_authority",
|
|
175
156
|
organization=org,
|
|
176
|
-
badge=org.get_badge(LOCAL_AUTHORITY)
|
|
177
|
-
)
|
|
157
|
+
badge=org.get_badge(LOCAL_AUTHORITY),
|
|
158
|
+
)
|
udata/core/owned.py
CHANGED
|
@@ -5,14 +5,14 @@ from mongoengine import NULLIFY, Q, post_save
|
|
|
5
5
|
from mongoengine.fields import ReferenceField
|
|
6
6
|
|
|
7
7
|
from udata.api_fields import field
|
|
8
|
-
from udata.core.organization.models import Organization
|
|
9
|
-
from udata.core.user.models import User
|
|
10
|
-
from udata.mongo.queryset import UDataQuerySet
|
|
11
|
-
from udata.core.user.api_fields import user_ref_fields
|
|
12
8
|
from udata.core.organization.api_fields import org_ref_fields
|
|
9
|
+
from udata.core.organization.models import Organization
|
|
13
10
|
from udata.core.organization.permissions import OrganizationPrivatePermission
|
|
14
|
-
from udata.
|
|
11
|
+
from udata.core.user.api_fields import user_ref_fields
|
|
12
|
+
from udata.core.user.models import User
|
|
15
13
|
from udata.i18n import lazy_gettext as _
|
|
14
|
+
from udata.mongo.errors import FieldValidationError
|
|
15
|
+
from udata.mongo.queryset import UDataQuerySet
|
|
16
16
|
|
|
17
17
|
log = logging.getLogger(__name__)
|
|
18
18
|
|
|
@@ -23,11 +23,19 @@ class OwnedQuerySet(UDataQuerySet):
|
|
|
23
23
|
for owner in owners:
|
|
24
24
|
qs |= Q(owner=owner) | Q(organization=owner)
|
|
25
25
|
return self(qs)
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
|
|
27
28
|
def check_owner_is_current_user(owner):
|
|
28
|
-
from udata.auth import
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
from udata.auth import admin_permission, current_user
|
|
30
|
+
|
|
31
|
+
if (
|
|
32
|
+
current_user.is_authenticated
|
|
33
|
+
and owner
|
|
34
|
+
and not admin_permission
|
|
35
|
+
and current_user.id != owner
|
|
36
|
+
):
|
|
37
|
+
raise FieldValidationError(_("You can only set yourself as owner"), field="owner")
|
|
38
|
+
|
|
31
39
|
|
|
32
40
|
def check_organization_is_valid_for_current_user(organization):
|
|
33
41
|
from udata.auth import current_user
|
|
@@ -38,13 +46,16 @@ def check_organization_is_valid_for_current_user(organization):
|
|
|
38
46
|
raise FieldValidationError(_("Unknown organization"), field="organization")
|
|
39
47
|
|
|
40
48
|
if current_user.is_authenticated and org and not OrganizationPrivatePermission(org).can():
|
|
41
|
-
raise FieldValidationError(
|
|
49
|
+
raise FieldValidationError(
|
|
50
|
+
_("Permission denied for this organization"), field="organization"
|
|
51
|
+
)
|
|
42
52
|
|
|
43
53
|
|
|
44
54
|
class Owned(object):
|
|
45
|
-
|
|
55
|
+
"""
|
|
46
56
|
A mixin to factorize owning behvaior between users and organizations.
|
|
47
|
-
|
|
57
|
+
"""
|
|
58
|
+
|
|
48
59
|
owner = field(
|
|
49
60
|
ReferenceField(User, reverse_delete_rule=NULLIFY),
|
|
50
61
|
nested_fields=user_ref_fields,
|
|
@@ -60,26 +71,26 @@ class Owned(object):
|
|
|
60
71
|
allow_null=True,
|
|
61
72
|
)
|
|
62
73
|
|
|
63
|
-
on_owner_change = signal(
|
|
74
|
+
on_owner_change = signal("Owned.on_owner_change")
|
|
64
75
|
|
|
65
76
|
meta = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
"indexes": [
|
|
78
|
+
"owner",
|
|
79
|
+
"organization",
|
|
69
80
|
],
|
|
70
|
-
|
|
81
|
+
"queryset_class": OwnedQuerySet,
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
def clean(self):
|
|
74
|
-
|
|
85
|
+
"""
|
|
75
86
|
Verify owner consistency and fetch original owner before the new one erase it.
|
|
76
|
-
|
|
87
|
+
"""
|
|
77
88
|
|
|
78
89
|
changed_fields = self._get_changed_fields()
|
|
79
|
-
if
|
|
90
|
+
if "organization" in changed_fields and "owner" in changed_fields:
|
|
80
91
|
# Ownership changes (org to owner or the other way around) have already been made
|
|
81
92
|
return
|
|
82
|
-
if
|
|
93
|
+
if "organization" in changed_fields:
|
|
83
94
|
if self.owner:
|
|
84
95
|
# Change from owner to organization
|
|
85
96
|
self._previous_owner = self.owner
|
|
@@ -87,9 +98,9 @@ class Owned(object):
|
|
|
87
98
|
else:
|
|
88
99
|
# Change from org to another
|
|
89
100
|
# Need to fetch previous value in base
|
|
90
|
-
original = self.__class__.objects.only(
|
|
101
|
+
original = self.__class__.objects.only("organization").get(pk=self.pk)
|
|
91
102
|
self._previous_owner = original.organization
|
|
92
|
-
elif
|
|
103
|
+
elif "owner" in changed_fields:
|
|
93
104
|
if self.organization:
|
|
94
105
|
# Change from organization to owner
|
|
95
106
|
self._previous_owner = self.organization
|
|
@@ -97,20 +108,20 @@ class Owned(object):
|
|
|
97
108
|
else:
|
|
98
109
|
# Change from owner to another
|
|
99
110
|
# Need to fetch previous value in base
|
|
100
|
-
original = self.__class__.objects.only(
|
|
111
|
+
original = self.__class__.objects.only("owner").get(pk=self.pk)
|
|
101
112
|
self._previous_owner = original.owner
|
|
102
113
|
|
|
103
114
|
|
|
104
115
|
def owned_post_save(sender, document, **kwargs):
|
|
105
|
-
|
|
116
|
+
"""
|
|
106
117
|
Owned mongoengine.post_save signal handler
|
|
107
118
|
Dispatch the `Owned.on_owner_change` signal
|
|
108
119
|
once the document has been saved including the previous owner.
|
|
109
120
|
|
|
110
121
|
The signal handler should have the following signature:
|
|
111
122
|
``def handler(document, previous)``
|
|
112
|
-
|
|
113
|
-
if isinstance(document, Owned) and hasattr(document,
|
|
123
|
+
"""
|
|
124
|
+
if isinstance(document, Owned) and hasattr(document, "_previous_owner"):
|
|
114
125
|
Owned.on_owner_change.send(document, previous=document._previous_owner)
|
|
115
126
|
|
|
116
127
|
|
udata/core/post/api.py
CHANGED
|
@@ -1,156 +1,157 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
|
|
3
|
-
from udata.api import api, fields
|
|
3
|
+
from udata.api import API, api, fields
|
|
4
4
|
from udata.auth import admin_permission
|
|
5
|
-
|
|
6
5
|
from udata.core.dataset.api_fields import dataset_fields
|
|
7
6
|
from udata.core.reuse.api_fields import reuse_fields
|
|
8
|
-
from udata.core.user.api_fields import user_ref_fields
|
|
9
7
|
from udata.core.storages.api import (
|
|
10
|
-
|
|
8
|
+
image_parser,
|
|
9
|
+
parse_uploaded_image,
|
|
10
|
+
uploaded_image_fields,
|
|
11
11
|
)
|
|
12
|
+
from udata.core.user.api_fields import user_ref_fields
|
|
12
13
|
|
|
13
|
-
from .models import Post
|
|
14
14
|
from .forms import PostForm
|
|
15
|
+
from .models import Post
|
|
15
16
|
|
|
16
|
-
ns = api.namespace(
|
|
17
|
-
|
|
18
|
-
post_fields = api.model(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
description=
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
description=
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
description=
|
|
30
|
-
|
|
31
|
-
description=
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
fields.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}, mask='*,datasets{id,title,acronym,uri,page},reuses{id,title,image,image_thumbnail,uri,page}')
|
|
57
|
-
|
|
58
|
-
post_page_fields = api.model('PostPage', fields.pager(post_fields))
|
|
17
|
+
ns = api.namespace("posts", "Posts related operations")
|
|
18
|
+
|
|
19
|
+
post_fields = api.model(
|
|
20
|
+
"Post",
|
|
21
|
+
{
|
|
22
|
+
"id": fields.String(description="The post identifier"),
|
|
23
|
+
"name": fields.String(description="The post name", required=True),
|
|
24
|
+
"slug": fields.String(description="The post permalink string", readonly=True),
|
|
25
|
+
"headline": fields.String(description="The post headline", required=True),
|
|
26
|
+
"content": fields.Markdown(description="The post content in Markdown", required=True),
|
|
27
|
+
"image": fields.ImageField(description="The post image", readonly=True),
|
|
28
|
+
"credit_to": fields.String(description="An optional credit line (associated to the image)"),
|
|
29
|
+
"credit_url": fields.String(description="An optional link associated to the credits"),
|
|
30
|
+
"tags": fields.List(fields.String, description="Some keywords to help in search"),
|
|
31
|
+
"datasets": fields.List(fields.Nested(dataset_fields), description="The post datasets"),
|
|
32
|
+
"reuses": fields.List(fields.Nested(reuse_fields), description="The post reuses"),
|
|
33
|
+
"owner": fields.Nested(
|
|
34
|
+
user_ref_fields, description="The owner user", readonly=True, allow_null=True
|
|
35
|
+
),
|
|
36
|
+
"created_at": fields.ISODateTime(description="The post creation date", readonly=True),
|
|
37
|
+
"last_modified": fields.ISODateTime(
|
|
38
|
+
description="The post last modification date", readonly=True
|
|
39
|
+
),
|
|
40
|
+
"published": fields.ISODateTime(description="The post publication date", readonly=True),
|
|
41
|
+
"body_type": fields.String(description="HTML or markdown body type", default="markdown"),
|
|
42
|
+
"uri": fields.UrlFor(
|
|
43
|
+
"api.post", lambda o: {"post": o}, description="The post API URI", readonly=True
|
|
44
|
+
),
|
|
45
|
+
"page": fields.UrlFor(
|
|
46
|
+
"posts.show",
|
|
47
|
+
lambda o: {"post": o},
|
|
48
|
+
description="The post page URL",
|
|
49
|
+
readonly=True,
|
|
50
|
+
fallback_endpoint="api.post",
|
|
51
|
+
),
|
|
52
|
+
},
|
|
53
|
+
mask="*,datasets{id,title,acronym,uri,page},reuses{id,title,image,image_thumbnail,uri,page}",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
post_page_fields = api.model("PostPage", fields.pager(post_fields))
|
|
59
57
|
|
|
60
58
|
parser = api.page_parser()
|
|
61
59
|
|
|
62
|
-
parser.add_argument(
|
|
63
|
-
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"sort", type=str, default="-created_at", location="args", help="The sorting attribute"
|
|
62
|
+
)
|
|
64
63
|
|
|
65
64
|
|
|
66
|
-
@ns.route(
|
|
65
|
+
@ns.route("/", endpoint="posts")
|
|
67
66
|
class PostsAPI(API):
|
|
68
|
-
|
|
69
|
-
@api.doc('list_posts')
|
|
67
|
+
@api.doc("list_posts")
|
|
70
68
|
@api.expect(parser)
|
|
71
69
|
@api.marshal_with(post_page_fields)
|
|
72
70
|
def get(self):
|
|
73
|
-
|
|
71
|
+
"""List all posts"""
|
|
74
72
|
args = parser.parse_args()
|
|
75
|
-
return (
|
|
76
|
-
|
|
73
|
+
return (
|
|
74
|
+
Post.objects.published()
|
|
75
|
+
.order_by(args["sort"])
|
|
76
|
+
.paginate(args["page"], args["page_size"])
|
|
77
|
+
)
|
|
77
78
|
|
|
78
|
-
@api.doc(
|
|
79
|
+
@api.doc("create_post")
|
|
79
80
|
@api.secure(admin_permission)
|
|
80
81
|
@api.expect(post_fields)
|
|
81
82
|
@api.marshal_with(post_fields)
|
|
82
|
-
@api.response(400,
|
|
83
|
+
@api.response(400, "Validation error")
|
|
83
84
|
def post(self):
|
|
84
|
-
|
|
85
|
+
"""Create a post"""
|
|
85
86
|
form = api.validate(PostForm)
|
|
86
87
|
return form.save(), 201
|
|
87
88
|
|
|
88
89
|
|
|
89
|
-
@ns.route(
|
|
90
|
-
@api.response(404,
|
|
91
|
-
@api.param(
|
|
90
|
+
@ns.route("/<post:post>/", endpoint="post")
|
|
91
|
+
@api.response(404, "Object not found")
|
|
92
|
+
@api.param("post", "The post ID or slug")
|
|
92
93
|
class PostAPI(API):
|
|
93
|
-
@api.doc(
|
|
94
|
+
@api.doc("get_post")
|
|
94
95
|
@api.marshal_with(post_fields)
|
|
95
96
|
def get(self, post):
|
|
96
|
-
|
|
97
|
+
"""Get a given post"""
|
|
97
98
|
return post
|
|
98
99
|
|
|
99
|
-
@api.doc(
|
|
100
|
+
@api.doc("update_post")
|
|
100
101
|
@api.secure(admin_permission)
|
|
101
102
|
@api.expect(post_fields)
|
|
102
103
|
@api.marshal_with(post_fields)
|
|
103
|
-
@api.response(400,
|
|
104
|
+
@api.response(400, "Validation error")
|
|
104
105
|
def put(self, post):
|
|
105
|
-
|
|
106
|
+
"""Update a given post"""
|
|
106
107
|
form = api.validate(PostForm, post)
|
|
107
108
|
return form.save()
|
|
108
109
|
|
|
109
110
|
@api.secure(admin_permission)
|
|
110
|
-
@api.doc(
|
|
111
|
-
@api.response(204,
|
|
111
|
+
@api.doc("delete_post")
|
|
112
|
+
@api.response(204, "Object deleted")
|
|
112
113
|
def delete(self, post):
|
|
113
|
-
|
|
114
|
+
"""Delete a given post"""
|
|
114
115
|
post.delete()
|
|
115
|
-
return
|
|
116
|
+
return "", 204
|
|
116
117
|
|
|
117
118
|
|
|
118
|
-
@ns.route(
|
|
119
|
+
@ns.route("/<post:post>/publish", endpoint="publish_post")
|
|
119
120
|
class PublishPostAPI(API):
|
|
120
121
|
@api.secure(admin_permission)
|
|
121
|
-
@api.doc(
|
|
122
|
+
@api.doc("publish_post")
|
|
122
123
|
@api.marshal_with(post_fields)
|
|
123
124
|
def post(self, post):
|
|
124
|
-
|
|
125
|
+
"""Publish an existing post"""
|
|
125
126
|
post.modify(published=datetime.utcnow())
|
|
126
127
|
return post
|
|
127
128
|
|
|
128
129
|
@api.secure(admin_permission)
|
|
129
|
-
@api.doc(
|
|
130
|
+
@api.doc("unpublish_post")
|
|
130
131
|
@api.marshal_with(post_fields)
|
|
131
132
|
def delete(self, post):
|
|
132
|
-
|
|
133
|
+
"""Publish an existing post"""
|
|
133
134
|
post.modify(published=None)
|
|
134
135
|
return post
|
|
135
136
|
|
|
136
137
|
|
|
137
|
-
@ns.route(
|
|
138
|
+
@ns.route("/<post:post>/image", endpoint="post_image")
|
|
138
139
|
class PostImageAPI(API):
|
|
139
140
|
@api.secure(admin_permission)
|
|
140
|
-
@api.doc(
|
|
141
|
+
@api.doc("post_image")
|
|
141
142
|
@api.expect(image_parser) # Swagger 2.0 does not support formData at path level
|
|
142
143
|
@api.marshal_with(uploaded_image_fields)
|
|
143
144
|
def post(self, post):
|
|
144
|
-
|
|
145
|
+
"""Upload a new image"""
|
|
145
146
|
parse_uploaded_image(post.image)
|
|
146
147
|
post.save()
|
|
147
148
|
return post
|
|
148
149
|
|
|
149
150
|
@api.secure(admin_permission)
|
|
150
|
-
@api.doc(
|
|
151
|
+
@api.doc("resize_post_image")
|
|
151
152
|
@api.expect(image_parser) # Swagger 2.0 does not support formData at path level
|
|
152
153
|
@api.marshal_with(uploaded_image_fields)
|
|
153
154
|
def put(self, post):
|
|
154
|
-
|
|
155
|
+
"""Set the image BBox"""
|
|
155
156
|
parse_uploaded_image(post.image)
|
|
156
157
|
return post
|
udata/core/post/constants.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
from udata.i18n import lazy_gettext as _
|
|
2
1
|
from collections import OrderedDict
|
|
3
2
|
|
|
3
|
+
from udata.i18n import lazy_gettext as _
|
|
4
|
+
|
|
4
5
|
IMAGE_SIZES = [400, 100, 50]
|
|
5
6
|
|
|
6
|
-
BODY_TYPES = OrderedDict(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
BODY_TYPES = OrderedDict(
|
|
8
|
+
[
|
|
9
|
+
("markdown", _("Markdown")),
|
|
10
|
+
("html", _("HTML")),
|
|
11
|
+
]
|
|
12
|
+
)
|
udata/core/post/factories.py
CHANGED
|
@@ -11,10 +11,10 @@ class PostFactory(ModelFactory):
|
|
|
11
11
|
class Meta:
|
|
12
12
|
model = Post
|
|
13
13
|
|
|
14
|
-
name = factory.Faker(
|
|
15
|
-
headline = factory.Faker(
|
|
16
|
-
content = factory.Faker(
|
|
17
|
-
published = factory.Faker(
|
|
14
|
+
name = factory.Faker("sentence")
|
|
15
|
+
headline = factory.Faker("sentence")
|
|
16
|
+
content = factory.Faker("text")
|
|
17
|
+
published = factory.Faker("past_datetime")
|
|
18
18
|
|
|
19
19
|
@factory.lazy_attribute
|
|
20
20
|
def datasets(self):
|