udata 9.0.1.dev29716__py2.py3-none-any.whl → 9.0.1.dev29760__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.

Files changed (45) hide show
  1. udata/api/__init__.py +1 -0
  2. udata/api_fields.py +3 -0
  3. udata/core/reports/__init__.py +0 -0
  4. udata/core/reports/api.py +43 -0
  5. udata/core/reports/constants.py +28 -0
  6. udata/core/reports/models.py +57 -0
  7. udata/models/__init__.py +1 -0
  8. udata/static/chunks/{11.7266fef2dddc1db403d9.js → 11.ae54612e36c6d46f85db.js} +3 -3
  9. udata/static/chunks/{11.7266fef2dddc1db403d9.js.map → 11.ae54612e36c6d46f85db.js.map} +1 -1
  10. udata/static/chunks/{13.91b177d7d531fd55cf5d.js → 13.d8ccb992a49875966313.js} +2 -2
  11. udata/static/chunks/{13.91b177d7d531fd55cf5d.js.map → 13.d8ccb992a49875966313.js.map} +1 -1
  12. udata/static/chunks/{16.e866757bab9f6b0a3f1b.js → 16.4565605e68bab129a471.js} +2 -2
  13. udata/static/chunks/{16.e866757bab9f6b0a3f1b.js.map → 16.4565605e68bab129a471.js.map} +1 -1
  14. udata/static/chunks/{19.619b83ac597516dcd03e.js → 19.f993a75d5bfe2382548d.js} +3 -3
  15. udata/static/chunks/{19.619b83ac597516dcd03e.js.map → 19.f993a75d5bfe2382548d.js.map} +1 -1
  16. udata/static/chunks/{5.48417db6b33328fa9d6a.js → 5.cc2e7bf65ef32f9c8604.js} +3 -3
  17. udata/static/chunks/{5.48417db6b33328fa9d6a.js.map → 5.cc2e7bf65ef32f9c8604.js.map} +1 -1
  18. udata/static/chunks/{6.f84539bd4c419b36cc19.js → 6.cad898a38692eda28965.js} +3 -3
  19. udata/static/chunks/{6.f84539bd4c419b36cc19.js.map → 6.cad898a38692eda28965.js.map} +1 -1
  20. udata/static/chunks/{9.07503e7f7ec02919f696.js → 9.d5b992e9ef51921aeb57.js} +2 -2
  21. udata/static/chunks/{9.07503e7f7ec02919f696.js.map → 9.d5b992e9ef51921aeb57.js.map} +1 -1
  22. udata/static/common.js +1 -1
  23. udata/static/common.js.map +1 -1
  24. udata/tests/api/test_reports_api.py +88 -0
  25. udata/translations/ar/LC_MESSAGES/udata.mo +0 -0
  26. udata/translations/ar/LC_MESSAGES/udata.po +32 -12
  27. udata/translations/de/LC_MESSAGES/udata.mo +0 -0
  28. udata/translations/de/LC_MESSAGES/udata.po +32 -12
  29. udata/translations/es/LC_MESSAGES/udata.mo +0 -0
  30. udata/translations/es/LC_MESSAGES/udata.po +31 -11
  31. udata/translations/fr/LC_MESSAGES/udata.mo +0 -0
  32. udata/translations/fr/LC_MESSAGES/udata.po +32 -12
  33. udata/translations/it/LC_MESSAGES/udata.mo +0 -0
  34. udata/translations/it/LC_MESSAGES/udata.po +32 -12
  35. udata/translations/pt/LC_MESSAGES/udata.mo +0 -0
  36. udata/translations/pt/LC_MESSAGES/udata.po +32 -12
  37. udata/translations/sr/LC_MESSAGES/udata.mo +0 -0
  38. udata/translations/sr/LC_MESSAGES/udata.po +32 -12
  39. udata/translations/udata.pot +31 -11
  40. {udata-9.0.1.dev29716.dist-info → udata-9.0.1.dev29760.dist-info}/METADATA +2 -1
  41. {udata-9.0.1.dev29716.dist-info → udata-9.0.1.dev29760.dist-info}/RECORD +45 -40
  42. {udata-9.0.1.dev29716.dist-info → udata-9.0.1.dev29760.dist-info}/LICENSE +0 -0
  43. {udata-9.0.1.dev29716.dist-info → udata-9.0.1.dev29760.dist-info}/WHEEL +0 -0
  44. {udata-9.0.1.dev29716.dist-info → udata-9.0.1.dev29760.dist-info}/entry_points.txt +0 -0
  45. {udata-9.0.1.dev29716.dist-info → udata-9.0.1.dev29760.dist-info}/top_level.txt +0 -0
udata/api/__init__.py CHANGED
@@ -334,6 +334,7 @@ def init_app(app):
334
334
  import udata.core.organization.apiv2 # noqa
335
335
  import udata.core.followers.api # noqa
336
336
  import udata.core.jobs.api # noqa
337
+ import udata.core.reports.api # noqa
337
338
  import udata.core.site.api # noqa
338
339
  import udata.core.tags.api # noqa
339
340
  import udata.core.topic.api # noqa
udata/api_fields.py CHANGED
@@ -38,6 +38,9 @@ def convert_db_to_field(key, field, info = {}):
38
38
  constructor = restx_fields.String
39
39
  params['min_length'] = field.min_length
40
40
  params['max_length'] = field.max_length
41
+ params['enum'] = field.choices
42
+ elif isinstance(field, mongo_fields.ObjectIdField):
43
+ constructor = restx_fields.String
41
44
  elif isinstance(field, mongo_fields.FloatField):
42
45
  constructor = restx_fields.Float
43
46
  params['min'] = field.min # TODO min_value?
File without changes
@@ -0,0 +1,43 @@
1
+ from flask import request
2
+ from flask_login import current_user
3
+ import mongoengine
4
+
5
+ from udata.api import api, API, fields
6
+ from udata.api_fields import patch
7
+ from .models import Report
8
+ from .constants import reports_reasons_translations
9
+
10
+ ns = api.namespace('reports', 'User reported objects related operations (beta)')
11
+
12
+ @ns.route('/', endpoint='reports')
13
+ class ReportsAPI(API):
14
+ @api.doc('list_reports')
15
+ @api.expect(Report.__index_parser__)
16
+ @api.marshal_with(Report.__page_fields__)
17
+ def get(self):
18
+ query = Report.objects
19
+
20
+ return Report.apply_sort_filters_and_pagination(query)
21
+
22
+ @api.secure
23
+ @api.doc('create_report', responses={400: 'Validation error'})
24
+ @api.expect(Report.__write_fields__)
25
+ @api.marshal_with(Report.__read_fields__, code=201)
26
+ def post(self):
27
+ report = patch(Report(), request)
28
+ report.by = current_user._get_current_object()
29
+
30
+ try:
31
+ report.save()
32
+ except mongoengine.errors.ValidationError as e:
33
+ api.abort(400, e.message)
34
+
35
+ return report, 201
36
+
37
+
38
+ @ns.route('/reasons/', endpoint='reports_reasons')
39
+ class ReportsReasonsAPI(API):
40
+ @api.doc('list_reports_reasons')
41
+ @ns.response(200, "dictionnary of available reasons associated with their labels", fields.Raw)
42
+ def get(self):
43
+ return reports_reasons_translations()
@@ -0,0 +1,28 @@
1
+
2
+ from udata.core.dataset.models import Dataset
3
+ from udata.i18n import lazy_gettext as _
4
+
5
+
6
+ REASON_SPAM = 'spam'
7
+ REASON_PERSONAL_DATA = 'personal_data'
8
+ REASON_EXPLICIT_CONTENT = 'explicit_content'
9
+ REASON_ILLEGAL_CONTENT = 'illegal_content'
10
+ REASON_SECURITY = 'security'
11
+ REASON_OTHERS = 'others'
12
+
13
+ def reports_reasons_translations():
14
+ '''
15
+ This is a function to avoid creating the dict with a wrong lang
16
+ at the start of the app.
17
+ '''
18
+ return {
19
+ REASON_SPAM: _('Spam'),
20
+ REASON_PERSONAL_DATA: _('Personal data'),
21
+ REASON_EXPLICIT_CONTENT: _('Explicit content'),
22
+ REASON_ILLEGAL_CONTENT: _('Illegal content'),
23
+ REASON_SECURITY: _('Security'),
24
+ REASON_OTHERS: _('Others'),
25
+ }
26
+
27
+ REPORT_REASONS_CHOICES = [key for key, _ in reports_reasons_translations().items()]
28
+ REPORTABLE_MODELS = [Dataset]
@@ -0,0 +1,57 @@
1
+ from datetime import datetime
2
+ from mongoengine import signals, NULLIFY
3
+
4
+ from udata.api_fields import field, generate_fields
5
+ from udata.core.dataset.models import Dataset
6
+ from udata.core.user.models import User
7
+ from udata.mongo import db
8
+ from udata.core.user.api_fields import user_ref_fields
9
+
10
+ from .constants import REPORT_REASONS_CHOICES, REPORTABLE_MODELS
11
+
12
+ @generate_fields()
13
+ class Report(db.Document):
14
+ by = field(
15
+ db.ReferenceField(User, reverse_delete_rule=NULLIFY),
16
+ nested_fields=user_ref_fields,
17
+ description="Only set if a user was connected when reporting an element.",
18
+ readonly=True,
19
+ allow_null=True,
20
+ )
21
+
22
+ object_type = field(
23
+ db.StringField(choices=[m.__name__ for m in REPORTABLE_MODELS])
24
+ )
25
+ object_id = field(
26
+ db.ObjectIdField()
27
+ )
28
+ object_deleted_at = field(
29
+ db.DateTimeField(),
30
+ allow_null=True,
31
+ readonly=True,
32
+ )
33
+
34
+ reason = field(
35
+ db.StringField(choices=REPORT_REASONS_CHOICES, required=True),
36
+ )
37
+ message = field(
38
+ db.StringField(),
39
+ )
40
+
41
+ reported_at = field(
42
+ db.DateTimeField(default=datetime.utcnow, required=True),
43
+ readonly=True,
44
+ )
45
+
46
+ @classmethod
47
+ def mark_as_deleted_soft_delete(cls, sender, document, **kwargs):
48
+ if document.deleted:
49
+ Report.objects(object_type=sender.__name__, object_id=document.id, object_deleted_at=None).update(object_deleted_at=datetime.utcnow)
50
+
51
+ def mark_as_deleted_hard_delete(cls, document, **kwargs):
52
+ Report.objects(object_type=document.__class__.__name__, object_id=document.id, object_deleted_at=None).update(object_deleted_at=datetime.utcnow)
53
+
54
+
55
+ for model in REPORTABLE_MODELS:
56
+ signals.post_save.connect(Report.mark_as_deleted_soft_delete, sender=model)
57
+ signals.post_delete.connect(Report.mark_as_deleted_hard_delete, sender=model)
udata/models/__init__.py CHANGED
@@ -21,6 +21,7 @@ from udata.core.post.models import * # noqa
21
21
  from udata.core.jobs.models import * # noqa
22
22
  from udata.core.tags.models import * # noqa
23
23
  from udata.core.spam.models import * # noqa
24
+ from udata.core.reports.models import * # noqa
24
25
 
25
26
  from udata.features.transfer.models import * # noqa
26
27
  from udata.features.territories.models import * # noqa