kinto 18.1.0__py3-none-any.whl → 20.4.0__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 kinto might be problematic. Click here for more details.

Files changed (91) hide show
  1. kinto/__init__.py +1 -0
  2. kinto/__main__.py +1 -19
  3. kinto/config/kinto.tpl +5 -15
  4. kinto/contribute.json +27 -0
  5. kinto/core/__init__.py +21 -8
  6. kinto/core/cornice/__init__.py +93 -0
  7. kinto/core/cornice/cors.py +144 -0
  8. kinto/core/cornice/errors.py +40 -0
  9. kinto/core/cornice/pyramidhook.py +373 -0
  10. kinto/core/cornice/renderer.py +89 -0
  11. kinto/core/cornice/resource.py +205 -0
  12. kinto/core/cornice/service.py +641 -0
  13. kinto/core/cornice/util.py +138 -0
  14. kinto/core/cornice/validators/__init__.py +94 -0
  15. kinto/core/cornice/validators/_colander.py +142 -0
  16. kinto/core/cornice/validators/_marshmallow.py +182 -0
  17. kinto/core/cornice_swagger/__init__.py +92 -0
  18. kinto/core/cornice_swagger/converters/__init__.py +21 -0
  19. kinto/core/cornice_swagger/converters/exceptions.py +6 -0
  20. kinto/core/cornice_swagger/converters/parameters.py +90 -0
  21. kinto/core/cornice_swagger/converters/schema.py +249 -0
  22. kinto/core/cornice_swagger/swagger.py +725 -0
  23. kinto/core/cornice_swagger/templates/index.html +73 -0
  24. kinto/core/cornice_swagger/templates/index_script_template.html +21 -0
  25. kinto/core/cornice_swagger/util.py +42 -0
  26. kinto/core/cornice_swagger/views.py +78 -0
  27. kinto/core/errors.py +6 -4
  28. kinto/core/initialization.py +129 -59
  29. kinto/core/metrics.py +93 -0
  30. kinto/core/openapi.py +2 -3
  31. kinto/core/permission/memory.py +3 -2
  32. kinto/core/permission/postgresql/__init__.py +9 -9
  33. kinto/core/permission/testing.py +6 -0
  34. kinto/core/resource/__init__.py +9 -4
  35. kinto/core/resource/schema.py +1 -2
  36. kinto/core/resource/viewset.py +1 -1
  37. kinto/core/statsd.py +1 -63
  38. kinto/core/storage/__init__.py +15 -0
  39. kinto/core/storage/memory.py +20 -3
  40. kinto/core/storage/postgresql/__init__.py +31 -1
  41. kinto/core/storage/postgresql/client.py +2 -2
  42. kinto/core/storage/postgresql/migrations/migration_022_023.sql +5 -0
  43. kinto/core/storage/postgresql/pool.py +1 -1
  44. kinto/core/storage/postgresql/schema.sql +3 -2
  45. kinto/core/storage/testing.py +41 -1
  46. kinto/core/testing.py +6 -2
  47. kinto/core/utils.py +14 -4
  48. kinto/core/views/batch.py +1 -1
  49. kinto/core/views/errors.py +4 -3
  50. kinto/core/views/openapi.py +1 -1
  51. kinto/plugins/accounts/__init__.py +3 -21
  52. kinto/plugins/accounts/authentication.py +8 -54
  53. kinto/plugins/accounts/utils.py +0 -133
  54. kinto/plugins/accounts/{views/__init__.py → views.py} +7 -62
  55. kinto/plugins/admin/VERSION +1 -1
  56. kinto/plugins/admin/build/VERSION +1 -0
  57. kinto/plugins/admin/build/assets/asn1-EdZsLKOL.js +1 -0
  58. kinto/plugins/admin/build/assets/clojure-BMjYHr_A.js +1 -0
  59. kinto/plugins/admin/build/assets/css-BnMrqG3P.js +1 -0
  60. kinto/plugins/admin/build/assets/index-Cs7JVwIg.css +6 -0
  61. kinto/plugins/admin/build/assets/index-CylsivYB.js +165 -0
  62. kinto/plugins/admin/build/assets/javascript-qCveANmP.js +1 -0
  63. kinto/plugins/admin/build/assets/logo-VBRiKSPX.png +0 -0
  64. kinto/plugins/admin/build/assets/mllike-CXdrOF99.js +1 -0
  65. kinto/plugins/admin/build/assets/python-BuPzkPfP.js +1 -0
  66. kinto/plugins/admin/build/assets/rpm-CTu-6PCP.js +1 -0
  67. kinto/plugins/admin/build/assets/sql-D0XecflT.js +1 -0
  68. kinto/plugins/admin/build/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  69. kinto/plugins/admin/build/index.html +18 -0
  70. kinto/plugins/default_bucket/__init__.py +1 -2
  71. kinto/plugins/flush.py +2 -2
  72. kinto/plugins/history/__init__.py +15 -6
  73. kinto/plugins/history/listener.py +68 -5
  74. kinto/plugins/openid/views.py +1 -1
  75. kinto/plugins/prometheus.py +203 -0
  76. kinto/plugins/statsd.py +78 -0
  77. kinto/views/contribute.py +14 -13
  78. {kinto-18.1.0.dist-info → kinto-20.4.0.dist-info}/METADATA +31 -32
  79. kinto-20.4.0.dist-info/RECORD +149 -0
  80. {kinto-18.1.0.dist-info → kinto-20.4.0.dist-info}/WHEEL +1 -1
  81. kinto/plugins/accounts/mails.py +0 -96
  82. kinto/plugins/accounts/views/validation.py +0 -136
  83. kinto/plugins/quotas/__init__.py +0 -22
  84. kinto/plugins/quotas/listener.py +0 -226
  85. kinto/plugins/quotas/scripts.py +0 -80
  86. kinto/plugins/quotas/utils.py +0 -7
  87. kinto/scripts.py +0 -41
  88. kinto-18.1.0.dist-info/RECORD +0 -116
  89. {kinto-18.1.0.dist-info → kinto-20.4.0.dist-info}/entry_points.txt +0 -0
  90. {kinto-18.1.0.dist-info → kinto-20.4.0.dist-info/licenses}/LICENSE +0 -0
  91. {kinto-18.1.0.dist-info → kinto-20.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,78 @@
1
+ import warnings
2
+ from urllib.parse import urlparse
3
+
4
+ from pyramid.exceptions import ConfigurationError
5
+ from zope.interface import implementer
6
+
7
+ from kinto.core import metrics
8
+
9
+
10
+ try:
11
+ import statsd as statsd_module
12
+ except ImportError: # pragma: no cover
13
+ statsd_module = None
14
+
15
+
16
+ def sanitize(value):
17
+ """
18
+ Telegraf does not support ':' in values.
19
+ See https://github.com/influxdata/telegraf/issues/4495
20
+ """
21
+ return value.replace(":", "") if isinstance(value, str) else value
22
+
23
+
24
+ @implementer(metrics.IMetricsService)
25
+ class StatsDService:
26
+ def __init__(self, host, port, prefix):
27
+ self._client = statsd_module.StatsClient(host, port, prefix=prefix)
28
+
29
+ def timer(self, key):
30
+ return self._client.timer(key)
31
+
32
+ def observe(self, key, value, labels=[]):
33
+ return self._client.gauge(key, sanitize(value))
34
+
35
+ def count(self, key, count=1, unique=None):
36
+ if unique is None:
37
+ return self._client.incr(key, count=count)
38
+ if isinstance(unique, list):
39
+ # [("method", "get")] -> "method.get"
40
+ # [("endpoint", "/"), ("method", "get")] -> "endpoint./.method.get"
41
+ unique = ".".join(f"{label[0]}.{sanitize(label[1])}" for label in unique)
42
+ else:
43
+ warnings.warn(
44
+ "`unique` parameter should be of type ``list[tuple[str, str]]``",
45
+ DeprecationWarning,
46
+ )
47
+ return self._client.set(key, unique)
48
+
49
+
50
+ def load_from_config(config):
51
+ # If this is called, it means that a ``statsd_url`` was specified in settings.
52
+ # (see ``kinto.core.initialization``)
53
+ # Raise a proper error if the ``statsd`` module is not installed.
54
+ if statsd_module is None:
55
+ error_msg = "Please install Kinto with monitoring dependencies (e.g. statsd package)"
56
+ raise ConfigurationError(error_msg)
57
+
58
+ settings = config.get_settings()
59
+ uri = settings["statsd_url"]
60
+ uri = urlparse(uri)
61
+
62
+ if settings["project_name"] != "":
63
+ prefix = settings["project_name"]
64
+ else:
65
+ prefix = settings["statsd_prefix"]
66
+
67
+ return StatsDService(uri.hostname, uri.port, prefix)
68
+
69
+
70
+ def includeme(config):
71
+ settings = config.get_settings()
72
+
73
+ # TODO: this backend abstraction may not be required anymore.
74
+ statsd_mod = settings["statsd_backend"]
75
+ statsd_mod = config.maybe_dotted(statsd_mod)
76
+ client = statsd_mod.load_from_config(config)
77
+
78
+ config.registry.registerUtility(client, metrics.IMetricsService)
kinto/views/contribute.py CHANGED
@@ -1,7 +1,15 @@
1
+ import json
2
+ import os
3
+
1
4
  import colander
2
- from cornice import Service
3
5
  from pyramid.security import NO_PERMISSION_REQUIRED
4
6
 
7
+ from kinto.core import Service
8
+
9
+
10
+ HERE = os.path.dirname(__file__)
11
+ ORIGIN = os.path.dirname(HERE) # package root.
12
+ _CONTRIBUTE_INFO = None
5
13
 
6
14
  contribute = Service(
7
15
  name="contribute.json", description="Open-source information", path="/contribute.json"
@@ -24,15 +32,8 @@ contribute_responses = {
24
32
  response_schemas=contribute_responses,
25
33
  )
26
34
  def contribute_get(request):
27
- return {
28
- "name": "kinto",
29
- "description": "A minimalist JSON storage service.",
30
- "repository": {"url": "https://github.com/Kinto/kinto", "license": "Apache License (2.0)"},
31
- "participate": {
32
- "docs": "https://kinto.readthedocs.io/",
33
- "mailing-list": "kinto@mozilla.org",
34
- "irc": "irc://irc.freenode.net/#kinto",
35
- },
36
- "keywords": ["JSON", "Python", "Offline", "Sync", "Storage"],
37
- "urls": {"dev": "https://demo.kinto-storage.org/v1/"},
38
- }
35
+ global _CONTRIBUTE_INFO
36
+ if _CONTRIBUTE_INFO is None:
37
+ with open(os.path.join(ORIGIN, "contribute.json")) as f:
38
+ _CONTRIBUTE_INFO = json.load(f)
39
+ return _CONTRIBUTE_INFO
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: kinto
3
- Version: 18.1.0
3
+ Version: 20.4.0
4
4
  Summary: Kinto Web Service - Store, Sync, Share, and Self-Host.
5
5
  Author-email: Mozilla Services <developers@kinto-storage.org>
6
6
  License: Copyright 2012 - Mozilla Foundation
@@ -21,10 +21,10 @@ Project-URL: Repository, https://github.com/Kinto/kinto
21
21
  Keywords: web,sync,json,storage,services
22
22
  Classifier: Programming Language :: Python
23
23
  Classifier: Programming Language :: Python :: 3
24
- Classifier: Programming Language :: Python :: 3.8
25
24
  Classifier: Programming Language :: Python :: 3.9
26
25
  Classifier: Programming Language :: Python :: 3.10
27
26
  Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
28
28
  Classifier: Programming Language :: Python :: Implementation :: CPython
29
29
  Classifier: Topic :: Internet :: WWW/HTTP
30
30
  Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
@@ -33,45 +33,44 @@ Description-Content-Type: text/x-rst
33
33
  License-File: LICENSE
34
34
  Requires-Dist: bcrypt
35
35
  Requires-Dist: colander
36
- Requires-Dist: cornice
37
- Requires-Dist: cornice-swagger
38
36
  Requires-Dist: dockerflow
39
37
  Requires-Dist: jsonschema
40
38
  Requires-Dist: jsonpatch
41
39
  Requires-Dist: logging-color-formatter
42
40
  Requires-Dist: python-dateutil
43
41
  Requires-Dist: pyramid
44
- Requires-Dist: pyramid-mailer
45
- Requires-Dist: pyramid-multiauth
42
+ Requires-Dist: pyramid_multiauth
46
43
  Requires-Dist: transaction
47
- Requires-Dist: pyramid-tm
44
+ Requires-Dist: pyramid_tm
48
45
  Requires-Dist: requests
49
46
  Requires-Dist: waitress
50
47
  Requires-Dist: python-rapidjson
51
- Provides-Extra: dev
52
- Requires-Dist: build ; extra == 'dev'
53
- Requires-Dist: ruff ; extra == 'dev'
54
- Requires-Dist: twine ; extra == 'dev'
48
+ Provides-Extra: redis
49
+ Requires-Dist: kinto_redis; extra == "redis"
55
50
  Provides-Extra: memcached
56
- Requires-Dist: python-memcached ; extra == 'memcached'
57
- Provides-Extra: monitoring
58
- Requires-Dist: newrelic ; extra == 'monitoring'
59
- Requires-Dist: sentry-sdk[sqlalchemy] ; extra == 'monitoring'
60
- Requires-Dist: statsd ; extra == 'monitoring'
61
- Requires-Dist: werkzeug ; extra == 'monitoring'
51
+ Requires-Dist: python-memcached; extra == "memcached"
62
52
  Provides-Extra: postgresql
63
- Requires-Dist: SQLAlchemy <3 ; extra == 'postgresql'
64
- Requires-Dist: psycopg2 ; extra == 'postgresql'
65
- Requires-Dist: zope.sqlalchemy ; extra == 'postgresql'
66
- Provides-Extra: redis
67
- Requires-Dist: kinto-redis ; extra == 'redis'
53
+ Requires-Dist: SQLAlchemy<3; extra == "postgresql"
54
+ Requires-Dist: psycopg2-binary; extra == "postgresql"
55
+ Requires-Dist: zope.sqlalchemy; extra == "postgresql"
56
+ Provides-Extra: monitoring
57
+ Requires-Dist: newrelic; extra == "monitoring"
58
+ Requires-Dist: sentry-sdk[sqlalchemy]; extra == "monitoring"
59
+ Requires-Dist: statsd; extra == "monitoring"
60
+ Requires-Dist: werkzeug; extra == "monitoring"
61
+ Requires-Dist: prometheus-client; extra == "monitoring"
68
62
  Provides-Extra: test
69
- Requires-Dist: bravado ; extra == 'test'
70
- Requires-Dist: pytest ; extra == 'test'
71
- Requires-Dist: pytest-cache ; extra == 'test'
72
- Requires-Dist: pytest-cov ; extra == 'test'
73
- Requires-Dist: playwright ; extra == 'test'
74
- Requires-Dist: webtest ; extra == 'test'
63
+ Requires-Dist: bravado; extra == "test"
64
+ Requires-Dist: pytest; extra == "test"
65
+ Requires-Dist: pytest-cache; extra == "test"
66
+ Requires-Dist: pytest-cov; extra == "test"
67
+ Requires-Dist: playwright; extra == "test"
68
+ Requires-Dist: webtest; extra == "test"
69
+ Provides-Extra: dev
70
+ Requires-Dist: build; extra == "dev"
71
+ Requires-Dist: ruff; extra == "dev"
72
+ Requires-Dist: twine; extra == "dev"
73
+ Dynamic: license-file
75
74
 
76
75
  Kinto
77
76
  =====
@@ -79,7 +78,7 @@ Kinto
79
78
  |coc| |gitter| |readthedocs| |pypi| |ci| |main-coverage|
80
79
 
81
80
  .. |coc| image:: https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-blue.svg
82
- :target: https://github.com/Kinto/kinto/blob/main/CODE_OF_CONDUCT.md
81
+ :target: https://github.com/Kinto/kinto/blob/main/.github/CODE_OF_CONDUCT.md
83
82
  :alt: Code of conduct
84
83
 
85
84
  .. |gitter| image:: https://badges.gitter.im/Kinto/kinto.svg
@@ -107,13 +106,12 @@ Kinto is a minimalist JSON storage service with synchronisation and sharing abil
107
106
  * `Tutorial <https://kinto.readthedocs.io/en/latest/tutorials/first-steps.html>`_
108
107
  * `Issue tracker <https://github.com/Kinto/kinto/issues>`_
109
108
  * `Contributing <https://kinto.readthedocs.io/en/latest/community.html#how-to-contribute>`_
110
- * `Try our daily flushed instance at: https://demo.kinto-storage.org/v1/ <https://demo.kinto-storage.org/v1/>`_
111
109
  * `Docker Hub <https://hub.docker.com/r/kinto/kinto-server>`_
112
110
 
113
111
  Requirements
114
112
  ------------
115
113
 
116
- * **Python**: 3.8+
114
+ * **Python**: 3.9+
117
115
  * **Backends**: In-memory (development), PostgreSQL 9.5+ (production)
118
116
 
119
117
  Contributors
@@ -135,6 +133,7 @@ Contributors
135
133
  * Balthazar Rouberol <br@imap.cc>
136
134
  * Boris Feld <lothiraldan@gmail.com>
137
135
  * Brady Dufresne <dufresnebrady@gmail.com>
136
+ * Can Berk Güder <cbguder@mozilla.com>
138
137
  * Castro
139
138
  * Chirag B. Jadwani <chirag.jadwani@gmail.com>
140
139
  * Christophe Gragnic <cgragnic@protonmail.com>
@@ -0,0 +1,149 @@
1
+ kinto/__init__.py,sha256=XG7cOyHN0ipQeOSPMW-XFax7uFgAjnCd3Slq0jSFGC4,3299
2
+ kinto/__main__.py,sha256=0vBSUT2pAMg78HyRpfGbk3R6Z_fpg12pcGi3pi1XJ1c,7181
3
+ kinto/authorization.py,sha256=i3ttdPTFGzE9CqUQmfC4rR_6dDZJu0jWJMLGl_jFzIE,4919
4
+ kinto/contribute.json,sha256=HT9QVB8rA8jWIREQoqWfMibfJXMAzbRsixW8F6O6cQY,792
5
+ kinto/events.py,sha256=NMPvKUdbi25aYHhu9svzQsrEZMa9nyO4mtuMZC5871Q,85
6
+ kinto/schema_validation.py,sha256=mtAmnl5HwiUsjS2gU8MKH4lkZ1380A5wZht-w9s5X7M,5306
7
+ kinto/config/__init__.py,sha256=av8W0utmjheueFqrjTYEDk_vbpm3XYdHcqv5lppNR4k,2131
8
+ kinto/config/kinto.tpl,sha256=Pm9p_oRsBlVoEXPVA2X6Wvv49jMOVv-27jw4rahVlwE,8201
9
+ kinto/core/__init__.py,sha256=s7PshdeKmpiqI5sW-zdC7p3Ig-e60w4kiUwlKi-impY,8655
10
+ kinto/core/authentication.py,sha256=HLA0kREC3GMEsrIsHsQYjVNztYfAF01kb8-pLboByFs,1527
11
+ kinto/core/authorization.py,sha256=GywY25KEzuSSAI709dFHDfdLnKxy3SLEYGwW5FkQ7Qc,13212
12
+ kinto/core/decorators.py,sha256=3SAPWXlyPNUSICZ9mz04bcN-UdbnDuFOtU0bQHHzLis,2178
13
+ kinto/core/errors.py,sha256=JXZjkPYjjC0I6x02d2VJRGeaQ2yZYS2zm5o7_ljfyes,8946
14
+ kinto/core/events.py,sha256=SYpXgKMtVjiD9fwYJA2Omdom9yA3nBqi9btdvU1I_nc,10345
15
+ kinto/core/initialization.py,sha256=ZjmCKc8MYZXv63W2mv--fY8rXSLAnJa7RtCYdfK4jsg,26225
16
+ kinto/core/metrics.py,sha256=Y6Mt4PUzy2-oudeGr_oCmtX8nIR4SZkzUlPxr58jr-g,2619
17
+ kinto/core/openapi.py,sha256=92sZviff4NCxN0jMnu5lPUnF5iQbrKMGy7Cegf-VAME,3876
18
+ kinto/core/schema.py,sha256=d5L5TQynRYJPkZ8Mu2X7F72xEh6SKDbrHK1CNTdOf2E,3646
19
+ kinto/core/scripts.py,sha256=5HSq5QAuin7HuU6icNYkPisny-4JpcdBvjf8X4JImrE,978
20
+ kinto/core/statsd.py,sha256=2f4s2opiHVdrA02ZlBa5pxIHaEjPuG8tdVLsmdII27s,64
21
+ kinto/core/testing.py,sha256=kZ-75EiiZwTNDBpHZyKBBHute6jEmUwXd7nRMK9kwr4,5908
22
+ kinto/core/utils.py,sha256=EDlZfHsgcaUvxg-AG_dn9IcQCq7j7RxpBjnFrx8b11E,17069
23
+ kinto/core/cache/__init__.py,sha256=NJT_39WFTuUd-OHuVqgoQTQUYv5zS9PIc3W_Kq9tabc,2726
24
+ kinto/core/cache/memcached.py,sha256=WuYyq6-QykRNryLA_bKdeGAY_Hvwq0c1ejS_8G94cY4,2914
25
+ kinto/core/cache/memory.py,sha256=603vuyV5nKxsmUlkVxZFZWKPAbxMSTQKqkpqK4ttFas,2748
26
+ kinto/core/cache/testing.py,sha256=KVNz1tVYv_A33HF66SObM1WTgOx1UY47MuwPsaaQRag,6980
27
+ kinto/core/cache/postgresql/__init__.py,sha256=04OetGaxI89XAHUhtrNtRyipsZTe0bn_ZjoUQms_3VA,6026
28
+ kinto/core/cache/postgresql/schema.sql,sha256=a-6lbhqzlNMcig7DCGQ_ULP-Z5nzhNWrZWCpaHTiJPw,503
29
+ kinto/core/cornice/__init__.py,sha256=P07QaR_5qIXuFxAXciJZYlUlQSH5bYD2LNsv5v9E_tY,3685
30
+ kinto/core/cornice/cors.py,sha256=nA61VsAamFovkpk5aYVoSWASLnXWVl6XJdMw17IDIKA,5159
31
+ kinto/core/cornice/errors.py,sha256=_8Jxhm7ic2obRSMkEKqRtJEK2tg9Fp75DhJ0kJ5OxLI,1433
32
+ kinto/core/cornice/pyramidhook.py,sha256=iy5I8nFTg29aIjPKrwmak5_hy_GjGK1nLwPkmvB7mYM,13936
33
+ kinto/core/cornice/renderer.py,sha256=Rk1BNrPnpFxIZVE1jdQmgqcpsOVf37378Ge1Fm4gidc,3341
34
+ kinto/core/cornice/resource.py,sha256=jpjZdvOfJNe9XMDvetBhVIcoJsQot5D6K3gcrH2DQGE,6181
35
+ kinto/core/cornice/service.py,sha256=3qZteBmR9aVjL9ZQDylnWCZeac51IE9iBtUVnFqv3so,23261
36
+ kinto/core/cornice/util.py,sha256=N6KbypHKkz5YmCARilY_xatGUePwreH3ThhiafrgCh8,4106
37
+ kinto/core/cornice/validators/__init__.py,sha256=tJAewtgSYL2Fpye0pQ-jsbA3vLJ3A6d3hhm9yXUO2Yc,3325
38
+ kinto/core/cornice/validators/_colander.py,sha256=qlh1jR3xEOkRvMgS-F-CxtyKohzJFPjaaOYPi5Lb2Ns,4752
39
+ kinto/core/cornice/validators/_marshmallow.py,sha256=auiqi9chYk2H1y47Xd0UDi5FMO-umis20pNqOTx9-oU,6278
40
+ kinto/core/cornice_swagger/__init__.py,sha256=ls4uB23VcamRxoBo2IDVA4cadBlzbp5x99jbTY_pmK4,2815
41
+ kinto/core/cornice_swagger/swagger.py,sha256=a4QProdgZ7XUDFNUWsC0zLwmroxwtWbALm0Jjd00stQ,26001
42
+ kinto/core/cornice_swagger/util.py,sha256=xNKQ9kY8gkIJdVoWIDqEzrK0v8o-vfdAxxKvbXMeTwE,1210
43
+ kinto/core/cornice_swagger/views.py,sha256=h3Ehwidak0CeCr3oTy5Eh4_rLTDEAYm2Ubxb_opqaUc,2572
44
+ kinto/core/cornice_swagger/converters/__init__.py,sha256=DaSaL-e2TKtqrhWk91dZolPOk_e-oPbzgctjZNXjnj0,640
45
+ kinto/core/cornice_swagger/converters/exceptions.py,sha256=YDtm7yDay_PRxCZWOKgdWZc549JTMCi_n8Z5-PtKvCA,94
46
+ kinto/core/cornice_swagger/converters/parameters.py,sha256=VWx3NzKqaC12U2BrflYCuLJHt0W3_UJqcXiTNfeQ414,2757
47
+ kinto/core/cornice_swagger/converters/schema.py,sha256=Ga9qJMso90U0a43JHFyQ1NVKjnAGOYd0jRWmCgFqbCA,6922
48
+ kinto/core/cornice_swagger/templates/index.html,sha256=rgDT8vx6Pu4amI2vym2BC0utGPbDM8kJ2KCQWJwtgBY,2957
49
+ kinto/core/cornice_swagger/templates/index_script_template.html,sha256=vq92R0oZE5kSJ0c0NuvUq_RCSC1_325ht_cu7aCrD2s,518
50
+ kinto/core/listeners/__init__.py,sha256=mBBo0LxNOjL8h8IqRweG1sY_G142FAakhimzKcgQBDQ,203
51
+ kinto/core/permission/__init__.py,sha256=RoI8UJYl3X8ZmuUfVGC8QH1g4EGNrRknUao97D3jKRE,7331
52
+ kinto/core/permission/memory.py,sha256=ymageLrGfgYxa0j8erOvVq2WPDBgtTo75R0wcL3Wx3Y,6171
53
+ kinto/core/permission/testing.py,sha256=o94YzVhrokh9xHO7s9hxkeoxIjKP_HSRFNj1K2dGaVU,22348
54
+ kinto/core/permission/postgresql/__init__.py,sha256=LRKo4yhrfn9tRm3cLaAVK4ALAn-8Gxb0hI2-QoUevBg,18251
55
+ kinto/core/permission/postgresql/schema.sql,sha256=BlKJNC-omDVF9REaWCTsfKgXupFrmCBX8ZvN4sqTWUU,1344
56
+ kinto/core/permission/postgresql/migrations/migration_001_002.sql,sha256=ey5rDVQfStVStWpyTJn2fmQP5WSA34HhO99PapcgH1k,681
57
+ kinto/core/resource/__init__.py,sha256=B-1X3nPzIZOiN8Dc_tSersAP-Wn4jXf3GcrctN2Ck1k,50746
58
+ kinto/core/resource/model.py,sha256=xjZ6shnhelXCdWvgw6yeOWXodxiKMm9iyDqLTk0i8Bs,15626
59
+ kinto/core/resource/schema.py,sha256=EhPKDMlBjx60hXztMvywfo4IrRfwaZ3V-7sY_sl-BYk,16126
60
+ kinto/core/resource/viewset.py,sha256=Wo7mQwmI08IGnSetaqGF66fCqYPB1pDUdZa3U92NIic,7613
61
+ kinto/core/storage/__init__.py,sha256=Bo9q5PCDQ7KkBuBAHt7UoZFr5WfVWwEbFJjGsuq4Oo4,13704
62
+ kinto/core/storage/exceptions.py,sha256=o10f7LohwyCHOTlR-dOdnB4us_MdCGOJUxZO8HZ3Akc,1304
63
+ kinto/core/storage/generators.py,sha256=rxWN9hOfOsB-PLeryhPGO-aE670sivr3LFRIExImpxc,1829
64
+ kinto/core/storage/memory.py,sha256=DR6gpqSYh4oGPBX9x4-dGLNITZi33T0VODsNWsPtgho,19875
65
+ kinto/core/storage/testing.py,sha256=4hGR6xc54M6H81IQb8XP7NP_iBP-X8m8PqKqixDs5nU,78411
66
+ kinto/core/storage/utils.py,sha256=BHpohIKVOCtURjRbUT7O5AEhIKfSEFv-pfgRzq8Q5zs,1082
67
+ kinto/core/storage/postgresql/__init__.py,sha256=HMlUfTBsnsUQkLEhuhItU-9fgSOf9wTH6J09-1HW1fA,40157
68
+ kinto/core/storage/postgresql/client.py,sha256=JTRxHK-8ipTXgs0E4PyiFiun-32yuzqFGsWTi-OuFfA,4270
69
+ kinto/core/storage/postgresql/migrator.py,sha256=MQ_5aSrDi9-s2wlyyFyfhYP6HreCXjtlJzBI4b85u1I,3524
70
+ kinto/core/storage/postgresql/pool.py,sha256=lOtclVagFqzzWbVxrGoWeKylpHlKdFgGz3Ef6cgGNJU,2219
71
+ kinto/core/storage/postgresql/schema.sql,sha256=qRmx8NSwqedwozOi-Nn-pnipubxUWLCcYTRDMkt2B80,4216
72
+ kinto/core/storage/postgresql/migrations/migration_001_002.sql,sha256=GVJIs8MGmZEyp1i0KjsmGKv1pLlBRckn0EWX6Kl6uQE,428
73
+ kinto/core/storage/postgresql/migrations/migration_002_003.sql,sha256=zlSZpG_2L-wd8KXh3szmbYtoGjAOOwy2gH7RFMUd61w,1203
74
+ kinto/core/storage/postgresql/migrations/migration_003_004.sql,sha256=OZSbH6Yt1PA2zba8iQWIguaTsnn3v7bFF-rbg2_teXY,530
75
+ kinto/core/storage/postgresql/migrations/migration_004_005.sql,sha256=3VzFzj5y7quywYN-j6OE8xwYvB84O33YeeTF7QYXFOA,603
76
+ kinto/core/storage/postgresql/migrations/migration_005_006.sql,sha256=NE1fdI1grEqnXZOiO714vME-TQo2UKVuxeUvplEKCUg,354
77
+ kinto/core/storage/postgresql/migrations/migration_006_007.sql,sha256=anpEkjSCJ6uXaDr_krei1ZY_1TIbxBW9iF5JsPDT4sw,2352
78
+ kinto/core/storage/postgresql/migrations/migration_007_008.sql,sha256=7SQpJRjD-44tuBYbXL0mGg3ugUhh7tlRpQiv98JeY-k,2011
79
+ kinto/core/storage/postgresql/migrations/migration_008_009.sql,sha256=UnMmGLf3mYNmfYMfStzWS4oeHWRTCEpqvMD9a60aHTg,1224
80
+ kinto/core/storage/postgresql/migrations/migration_009_010.sql,sha256=Wzczz3J2sjPUfcG7iP2nEuASU9Qrx97IYHiCfrTvYeA,2843
81
+ kinto/core/storage/postgresql/migrations/migration_010_011.sql,sha256=zQS3GMgZNJEmHtaW1uH8hVP5IVQ9lU9Gpk6tzfYb_cs,484
82
+ kinto/core/storage/postgresql/migrations/migration_011_012.sql,sha256=YcpZcO68d4wPF3b5e-PWljV3F9LACe1o2uEKmDOnxHo,304
83
+ kinto/core/storage/postgresql/migrations/migration_012_013.sql,sha256=MOnGjfQVIucs3A3eOBRZ0mdgS9NY-KZDdQ8Eu2FjPdI,2389
84
+ kinto/core/storage/postgresql/migrations/migration_013_014.sql,sha256=cyDg2EpAwvbfaOXJbuxiJz_ofwl2pN6lix8Yrd3pbys,482
85
+ kinto/core/storage/postgresql/migrations/migration_014_015.sql,sha256=U2LtXV-oo8aozeeUIm2D62ujPHj29KuQ0JSYbJ3t1Iw,2992
86
+ kinto/core/storage/postgresql/migrations/migration_015_016.sql,sha256=gacFTc1zpmbkkbSCqpn12lySeMyYT-4_g4L6bSqHOFw,176
87
+ kinto/core/storage/postgresql/migrations/migration_016_017.sql,sha256=B0QFDuvcp8hKXY5xjOVy58vl0OO9LLnZdJQxBuyrLus,2476
88
+ kinto/core/storage/postgresql/migrations/migration_017_018.sql,sha256=n_BGQ-btSoTjmznHd0yypxoGcSJ7wWkORrLqlhUuVPI,993
89
+ kinto/core/storage/postgresql/migrations/migration_018_019.sql,sha256=XK6ex2jwQQLXgxjhy5bXF4H2Zt9nV_K4dehmvePd30k,346
90
+ kinto/core/storage/postgresql/migrations/migration_019_020.sql,sha256=yDQDdzU65cgctKIeo1YqMrFi7aU2VGdBhVUpVQAQOgM,306
91
+ kinto/core/storage/postgresql/migrations/migration_020_021.sql,sha256=cEgfGNDLH3RyLswxy9YZazZtOvidxNsi57z7SGR8VsQ,2369
92
+ kinto/core/storage/postgresql/migrations/migration_021_022.sql,sha256=MUIAfgbBDQLy8JfklEs6ekK93nr1buVRtmBAHaaMXug,1993
93
+ kinto/core/storage/postgresql/migrations/migration_022_023.sql,sha256=c1Fw10sxtaDqYJpxk1P9eZCtXP3uSmBY7-3IjZZLwjU,231
94
+ kinto/core/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
+ kinto/core/views/batch.py,sha256=sWNn67YqfTbiqwpbwbm1QyumcVGi8aNhlT5AtLToElI,5657
96
+ kinto/core/views/errors.py,sha256=2uTy85UBQL1EDIMotzFBhVl14RmWwb3rupbsB0mycbs,6099
97
+ kinto/core/views/heartbeat.py,sha256=qidZ7fTvuPoJMo7miDnclAm_WsbgqubzsARrv9aCo5U,3336
98
+ kinto/core/views/hello.py,sha256=tTjJ2PHKPnmLL41cwF6e0AzPhm4WmojIc0VWHcZNOgI,1961
99
+ kinto/core/views/openapi.py,sha256=PgxplQX1D0zqzlvRxBvd5SzrNMJmsaLfDta_fh-Pr-A,958
100
+ kinto/core/views/version.py,sha256=-m5G_o0oHTpCgrtfFrHFve6Zqw_gs_szT0Bd8jnNmD4,1419
101
+ kinto/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
102
+ kinto/plugins/flush.py,sha256=poiBOLGXjml0xXHjqDMRdbXJSd6N3SL0mfeGK2vxeHY,812
103
+ kinto/plugins/prometheus.py,sha256=oGpm1H4-CTVK4kd_GWDyn4nKBCSVq1fypdBoewDMRPk,6209
104
+ kinto/plugins/statsd.py,sha256=-VasJZM1xkhTfFa6_0GgWwfPqKnYS2722bSMDLzZ3pI,2469
105
+ kinto/plugins/accounts/__init__.py,sha256=2DeIaXJmMqRca3xVHeJ6xBWmeXAfrCdyg3EvK5jzIak,3670
106
+ kinto/plugins/accounts/authentication.py,sha256=pCb269FquKGFd6DH8AVTjFnBFlfxcDEYVyxhQp5Y08o,2117
107
+ kinto/plugins/accounts/scripts.py,sha256=_LNkSpFprOMGHFKkRmmOqK31uoQW28yttPQztmfUt5Q,2001
108
+ kinto/plugins/accounts/utils.py,sha256=xGtWwBPKVEwkbJbtJ_SUFgTJpwQzreoJG9XY86HPj7M,358
109
+ kinto/plugins/accounts/views.py,sha256=NO2nZCS1v0dN390Hxhe55Bsi4IM-NH9jEStkiKH2AEU,5221
110
+ kinto/plugins/admin/README.md,sha256=3a9inoO2IHH5aST3xZp_km3ddupHZqadWrQjOQifBRk,105
111
+ kinto/plugins/admin/VERSION,sha256=Tpnn6sIcK3GpcTnKzKaV2YyT-9fdJlBfBPUnGAmsS5Q,6
112
+ kinto/plugins/admin/__init__.py,sha256=057R3q_S4CFiUuqwMIFkyu4prMBnUVc1eo8OUAPeJBs,1327
113
+ kinto/plugins/admin/views.py,sha256=NHQncNB-32ytP03o-ZqisbYEoK7L2QcaK7RBuh0akwg,1338
114
+ kinto/plugins/admin/build/VERSION,sha256=Tpnn6sIcK3GpcTnKzKaV2YyT-9fdJlBfBPUnGAmsS5Q,6
115
+ kinto/plugins/admin/build/index.html,sha256=cfQ_QjlmMyviojnRWQFxC6J5nWbyo8WIFvWtmcyzbeo,467
116
+ kinto/plugins/admin/build/assets/asn1-EdZsLKOL.js,sha256=rgO6M_APbSRME0yY3rddue8niU7UJmG2uWz4l1YeG6s,3981
117
+ kinto/plugins/admin/build/assets/clojure-BMjYHr_A.js,sha256=SYpgEG0C5dkSQgMtAejALIQFzA3S0InWn1XquOeNGiA,10815
118
+ kinto/plugins/admin/build/assets/css-BnMrqG3P.js,sha256=qj5HvX1-byua7Xs0K31qoFn_bncMhtZMsOr5e0A-yYo,27132
119
+ kinto/plugins/admin/build/assets/index-Cs7JVwIg.css,sha256=dtEppIrcuaKwSBl-bfgIKrBnbrr7qFL7PST9yLyPfc0,171774
120
+ kinto/plugins/admin/build/assets/index-CylsivYB.js,sha256=4GW6MPa0FgDsBjUF2bjYB-8jjU5hjUXykaQMxjChFsM,2754443
121
+ kinto/plugins/admin/build/assets/javascript-qCveANmP.js,sha256=ol336oG7yGQxC9YIvojoE-dqx7wd3lLp0Ikn2rV4F5g,17080
122
+ kinto/plugins/admin/build/assets/logo-VBRiKSPX.png,sha256=4LXIgVZbcdbMun8bTlCFgnBik7uIkIRILVPFYrTUGgg,5578
123
+ kinto/plugins/admin/build/assets/mllike-CXdrOF99.js,sha256=C_YMaIP-ED2BN1nxtpuqRq-LXcC1AqrkksJHg4pdh4Q,4788
124
+ kinto/plugins/admin/build/assets/python-BuPzkPfP.js,sha256=rDHPcNHr9ezekY0ihOc2YV-rU0QsKzwjC_qD-F-AbXg,6475
125
+ kinto/plugins/admin/build/assets/rpm-CTu-6PCP.js,sha256=YPjyUyP0eZbB5aKZ-H9C3kK9bBOlhHM8T-PXHsSLplo,1622
126
+ kinto/plugins/admin/build/assets/sql-D0XecflT.js,sha256=3hecsZJ0WlDxeFA_1lrl_ySI80tNQh3oWWGhIHkwoSU,37052
127
+ kinto/plugins/admin/build/assets/ttcn-cfg-B9xdYoR4.js,sha256=jTZ_XHKOChJZEt-FzJbGHhvSYW42F1NccHg0lOY2FlM,4050
128
+ kinto/plugins/admin/public/help.html,sha256=1hol7z5Sv0Xn3mYyEfPQWFOsrR24htlKhmnGA3rH8fs,958
129
+ kinto/plugins/default_bucket/__init__.py,sha256=7TmBzFgW0gmYsetXr6Kqt9317XZ3PiB9gyCr-IBfmGg,7276
130
+ kinto/plugins/history/__init__.py,sha256=ZuGoj9giDEefv2BNuaakgGEV87e85wvrkNgsmVAotIU,1443
131
+ kinto/plugins/history/listener.py,sha256=ABPRduTnkwH6oMzRyrQlF3AZoVt7brqwKVpA8ynY0Sw,7962
132
+ kinto/plugins/history/views.py,sha256=NoBP-S7epeH5TLZZbIqfBmwMA2KaWmxP7lqPAS11BTU,2293
133
+ kinto/plugins/openid/__init__.py,sha256=1Iv5SCa6vwEvoJkmGd45-TYm_mxz2okFj6u2VTNuVrk,4863
134
+ kinto/plugins/openid/utils.py,sha256=n3KGS-ogXR2sg6j4QtdPe_DtEsqD7AGVT2K7vhl8yE8,273
135
+ kinto/plugins/openid/views.py,sha256=RRLBH6uipqafPSyQG5bi8nQOGGO6kT4fGLW4H3blU3E,6519
136
+ kinto/views/__init__.py,sha256=mItMqadROvEieXtxm0AoDReH3PwxOlM4rzECPCQfK_s,1187
137
+ kinto/views/admin.py,sha256=m4JKApzUUQNmmbHOfoc2n0CK01OrNiho21nYW_f5zlo,7439
138
+ kinto/views/buckets.py,sha256=3dc5cURZEP4vPKfk3f9W3BDbloG3QZ2lefhIoo-BiSQ,1868
139
+ kinto/views/collections.py,sha256=KrqJuje88er1VS2mtspMnXU6eYeZQTqUw0zB1ova9Bo,2206
140
+ kinto/views/contribute.py,sha256=PJoIMLj9_IszSjgZkaCd_TUjekDgNqjpmVTmRN9ztaA,983
141
+ kinto/views/groups.py,sha256=jOq5fX0-4lwZE8k1q5HME2tU7x9052rtBPF7YqcJ-Qg,3181
142
+ kinto/views/permissions.py,sha256=F0_eKx201WyLonXJ5vLdGKa9RcFKjvAihrEEhU1JuLw,9069
143
+ kinto/views/records.py,sha256=lYfACW2L8qcQoyYBD5IX-fTPjFWmGp7GjHq_U4InlyE,5037
144
+ kinto-20.4.0.dist-info/licenses/LICENSE,sha256=oNEIMTuTJzppR5ZEyi86yvvtSagveMYXTYFn56zF0Uk,561
145
+ kinto-20.4.0.dist-info/METADATA,sha256=FJkC9Vuz90F7WOrCHXR68mhO8z59xIu5bkLBCe1Os2k,8731
146
+ kinto-20.4.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
147
+ kinto-20.4.0.dist-info/entry_points.txt,sha256=3KlqBWPKY81mrCe_oX0I5s1cRO7Q53nCLbnVr5P9LH4,85
148
+ kinto-20.4.0.dist-info/top_level.txt,sha256=EG_YmbZL6FAug9VwopG7JtF9SvH_r0DEnFp-3twPPys,6
149
+ kinto-20.4.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,96 +0,0 @@
1
- import string
2
-
3
- from pyramid_mailer import get_mailer
4
- from pyramid_mailer.message import Message
5
-
6
-
7
- DEFAULT_EMAIL_SENDER = "admin@example.com"
8
- DEFAULT_SUBJECT_TEMPLATE = "activate your account"
9
- DEFAULT_BODY_TEMPLATE = "{activation-key}"
10
- DEFAULT_CONFIRMATION_SUBJECT_TEMPLATE = "Account active"
11
- DEFAULT_CONFIRMATION_BODY_TEMPLATE = "The account {id} is now active"
12
- DEFAULT_RESET_SUBJECT_TEMPLATE = "Reset password"
13
- DEFAULT_RESET_BODY_TEMPLATE = "{reset-password}"
14
-
15
-
16
- class EmailFormatter(string.Formatter):
17
- """Formatter class that will not fail if there's a missing key."""
18
-
19
- def __init__(self, default="{{{0}}}"):
20
- self.default = default
21
-
22
- def get_value(self, key, args, kwargs):
23
- return kwargs.get(key, self.default.format(key))
24
-
25
-
26
- class Emailer:
27
- def __init__(self, request, user):
28
- self.request = request
29
- self.settings = request.registry.settings
30
- self.user = user
31
- self.user_email = user["id"]
32
- self.email_sender = self.settings.get(
33
- "account_validation.email_sender", DEFAULT_EMAIL_SENDER
34
- )
35
- self.mailer = get_mailer(request)
36
-
37
- def send_mail(self, subject_template, body_template, extra_data=None):
38
- formatter = EmailFormatter()
39
- if extra_data is None:
40
- extra_data = {}
41
- user_email_context = self.user.get("email-context", {})
42
- # We might have some previous email context.
43
- try:
44
- data = self.request.json.get("data", {})
45
- email_context = data.get("email-context", user_email_context)
46
- except ValueError:
47
- email_context = user_email_context
48
-
49
- formatted_subject = formatter.format(
50
- subject_template, **self.user, **extra_data, **email_context
51
- )
52
- formatted_body = formatter.format(
53
- body_template, **self.user, **extra_data, **email_context
54
- )
55
- message = Message(
56
- subject=formatted_subject,
57
- sender=self.email_sender,
58
- recipients=[self.user_email],
59
- body=formatted_body,
60
- )
61
- self.mailer.send(message)
62
-
63
- def send_activation(self, activation_key):
64
- extra_data = {"activation-key": activation_key}
65
-
66
- subject_template = self.settings.get(
67
- "account_validation.email_subject_template", DEFAULT_SUBJECT_TEMPLATE
68
- )
69
- body_template = self.settings.get(
70
- "account_validation.email_body_template", DEFAULT_BODY_TEMPLATE
71
- )
72
- self.send_mail(subject_template, body_template, extra_data)
73
-
74
- def send_confirmation(self):
75
- subject_template = self.settings.get(
76
- "account_validation.email_confirmation_subject_template",
77
- DEFAULT_CONFIRMATION_SUBJECT_TEMPLATE,
78
- )
79
- body_template = self.settings.get(
80
- "account_validation.email_confirmation_body_template",
81
- DEFAULT_CONFIRMATION_BODY_TEMPLATE,
82
- )
83
-
84
- self.send_mail(subject_template, body_template)
85
-
86
- def send_temporary_reset_password(self, reset_password):
87
- extra_data = {"reset-password": reset_password}
88
- subject_template = self.settings.get(
89
- "account_validation.email_reset_password_subject_template",
90
- DEFAULT_RESET_SUBJECT_TEMPLATE,
91
- )
92
- body_template = self.settings.get(
93
- "account_validation.email_reset_password_body_template", DEFAULT_RESET_BODY_TEMPLATE
94
- )
95
-
96
- self.send_mail(subject_template, body_template, extra_data)
@@ -1,136 +0,0 @@
1
- import re
2
- import uuid
3
-
4
- from pyramid import httpexceptions
5
- from pyramid.events import subscriber
6
-
7
- from kinto.core import Service
8
- from kinto.core.errors import http_error, raise_invalid
9
- from kinto.core.events import ACTIONS, ResourceChanged
10
- from kinto.core.storage import exceptions as storage_exceptions
11
-
12
- from ..mails import Emailer
13
- from ..utils import (
14
- cache_reset_password,
15
- delete_cached_validation_key,
16
- get_cached_validation_key,
17
- hash_password,
18
- )
19
- from . import DEFAULT_EMAIL_REGEXP
20
-
21
-
22
- # Account validation (enable in the settings).
23
- validation = Service(
24
- name="account-validation",
25
- path="/accounts/{user_id}/validate/{activation_key}",
26
- description="Validate an account",
27
- )
28
-
29
-
30
- def check_validation_key(activation_key, username, registry):
31
- """Given a username, compare the activation-key provided with the one from the cache."""
32
- cache_result = get_cached_validation_key(username, registry)
33
-
34
- if cache_result == activation_key:
35
- delete_cached_validation_key(username, registry) # We're done with the activation key.
36
- return True
37
- return False
38
-
39
-
40
- @validation.post()
41
- def post_validation(request):
42
- user_id = request.matchdict["user_id"]
43
- activation_key = request.matchdict["activation_key"]
44
-
45
- parent_id = user_id
46
- try:
47
- user = request.registry.storage.get(
48
- parent_id=parent_id, resource_name="account", object_id=user_id
49
- )
50
- except storage_exceptions.ObjectNotFoundError:
51
- # Don't give information on the existence of a user id: return a generic error message.
52
- error_details = {"message": "Account ID and activation key do not match"}
53
- raise http_error(httpexceptions.HTTPForbidden(), **error_details)
54
-
55
- if not check_validation_key(activation_key, user_id, request.registry):
56
- error_details = {"message": "Account ID and activation key do not match"}
57
- raise http_error(httpexceptions.HTTPForbidden(), **error_details)
58
-
59
- # User is now validated.
60
- new = user.copy()
61
- new["validated"] = True
62
-
63
- result = request.registry.storage.update(
64
- parent_id=parent_id, resource_name="account", object_id=user_id, obj=new
65
- )
66
- request.notify_resource_event(
67
- parent_id=parent_id,
68
- timestamp=result["last_modified"],
69
- data=result,
70
- action=ACTIONS.UPDATE,
71
- old=user,
72
- resource_name="account",
73
- )
74
- return new
75
-
76
-
77
- # Password reset.
78
- reset_password = Service(
79
- name="reset-password",
80
- path="/accounts/{user_id}/reset-password",
81
- description="Send a temporary reset password by mail for an account",
82
- )
83
-
84
-
85
- @reset_password.post()
86
- def post_reset_password(request):
87
- user_id = request.matchdict["user_id"]
88
-
89
- parent_id = user_id
90
- try:
91
- user = request.registry.storage.get(
92
- parent_id=parent_id, resource_name="account", object_id=user_id
93
- )
94
- except storage_exceptions.ObjectNotFoundError:
95
- # Don't give information on the existence of a user id: return a generic message.
96
- return {"message": "A temporary reset password has been sent by mail"}
97
-
98
- settings = request.registry.settings
99
-
100
- user_email = user["id"]
101
- email_regexp = settings.get("account_validation.email_regexp", DEFAULT_EMAIL_REGEXP)
102
- compiled_email_regexp = re.compile(email_regexp)
103
- if not compiled_email_regexp.match(user_email):
104
- error_details = {
105
- "name": "data.id",
106
- "description": f"The user id should match {email_regexp}.",
107
- }
108
- raise_invalid(request, **error_details)
109
-
110
- reset_password = str(uuid.uuid4())
111
- hashed_reset_password = hash_password(reset_password)
112
- cache_reset_password(hashed_reset_password, user_id, request.registry)
113
-
114
- # Send a temporary reset password by mail.
115
- Emailer(request, user).send_temporary_reset_password(reset_password)
116
-
117
- return {"message": "A temporary reset password has been sent by mail"}
118
-
119
-
120
- # Send confirmation email on account activation if account validation is enabled.
121
- @subscriber(ResourceChanged, for_resources=("account",), for_actions=(ACTIONS.UPDATE,))
122
- def on_account_activated(event):
123
- request = event.request
124
- settings = request.registry.settings
125
- if not settings.get("account_validation", False):
126
- return
127
-
128
- for impacted_object in event.impacted_objects:
129
- old_account = impacted_object["old"]
130
- account = impacted_object["new"]
131
- if old_account.get("validated", True) or not account.get("validated", False):
132
- # It's not an account activation, bail.
133
- continue
134
-
135
- # Send a confirmation email.
136
- Emailer(request, account).send_confirmation()
@@ -1,22 +0,0 @@
1
- from kinto.core.events import ResourceChanged
2
-
3
- from .listener import on_resource_changed
4
-
5
-
6
- def includeme(config):
7
- config.add_api_capability(
8
- "quotas",
9
- description="Quotas Management on buckets " "and collections.",
10
- url="https://kinto.readthedocs.io",
11
- )
12
-
13
- # If StatsD is enabled, monitor execution time of listener.
14
- listener = on_resource_changed
15
- if config.registry.statsd:
16
- key = "plugins.quotas"
17
- listener = config.registry.statsd.timer(key)(on_resource_changed)
18
-
19
- # Listen to every resources (except history)
20
- config.add_subscriber(
21
- listener, ResourceChanged, for_resources=("bucket", "group", "collection", "record")
22
- )