c2cgeoportal-admin 2.7.1.156__py3-none-any.whl → 2.8.1.87__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.
Files changed (50) hide show
  1. c2cgeoportal_admin/__init__.py +16 -1
  2. c2cgeoportal_admin/lib/ogcserver_synchronizer.py +4 -4
  3. c2cgeoportal_admin/routes.py +3 -1
  4. c2cgeoportal_admin/schemas/metadata.py +1 -1
  5. c2cgeoportal_admin/templates/404.jinja2 +18 -2
  6. c2cgeoportal_admin/templates/widgets/metadata.pt +1 -1
  7. c2cgeoportal_admin/views/__init__.py +29 -0
  8. c2cgeoportal_admin/views/functionalities.py +4 -3
  9. c2cgeoportal_admin/views/interfaces.py +4 -3
  10. c2cgeoportal_admin/views/layer_groups.py +1 -1
  11. c2cgeoportal_admin/views/layers_wms.py +5 -3
  12. c2cgeoportal_admin/views/layers_wmts.py +5 -3
  13. c2cgeoportal_admin/views/layertree.py +2 -2
  14. c2cgeoportal_admin/views/logged_views.py +80 -0
  15. c2cgeoportal_admin/views/logs.py +90 -0
  16. c2cgeoportal_admin/views/oauth2_clients.py +9 -6
  17. c2cgeoportal_admin/views/ogc_servers.py +66 -12
  18. c2cgeoportal_admin/views/restriction_areas.py +4 -3
  19. c2cgeoportal_admin/views/roles.py +4 -3
  20. c2cgeoportal_admin/views/themes.py +1 -1
  21. c2cgeoportal_admin/views/treeitems.py +4 -3
  22. c2cgeoportal_admin/views/users.py +7 -4
  23. c2cgeoportal_admin/widgets.py +2 -2
  24. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.87.dist-info}/METADATA +13 -7
  25. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.87.dist-info}/RECORD +50 -47
  26. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.87.dist-info}/entry_points.txt +1 -0
  27. tests/__init__.py +2 -3
  28. tests/test_edit_url.py +0 -1
  29. tests/test_functionalities.py +29 -4
  30. tests/test_home.py +0 -1
  31. tests/test_interface.py +27 -4
  32. tests/test_layer_groups.py +45 -11
  33. tests/test_layers_vectortiles.py +33 -8
  34. tests/test_layers_wms.py +43 -10
  35. tests/test_layers_wmts.py +33 -8
  36. tests/test_layertree.py +0 -1
  37. tests/test_left_menu.py +0 -1
  38. tests/test_lingua_extractor_config.py +1 -3
  39. tests/test_logs.py +103 -0
  40. tests/test_metadatas.py +0 -1
  41. tests/test_oauth2_clients.py +35 -7
  42. tests/test_ogc_servers.py +65 -27
  43. tests/test_restriction_areas.py +28 -3
  44. tests/test_role.py +33 -8
  45. tests/test_themes.py +33 -6
  46. tests/test_themes_ordering.py +0 -1
  47. tests/test_user.py +33 -4
  48. tests/themes_ordering.py +0 -1
  49. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.87.dist-info}/WHEEL +0 -0
  50. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.87.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021, Camptocamp SA
1
+ # Copyright (c) 2017-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -26,29 +26,36 @@
26
26
  # either expressed or implied, of the FreeBSD Project.
27
27
 
28
28
 
29
+ import logging
30
+ import threading
29
31
  from functools import partial
30
- from typing import Any, Dict, List, cast
32
+ from typing import Any, Dict, List, Union, cast
31
33
 
34
+ import requests
32
35
  from c2cgeoform.schema import GeoFormSchemaNode
33
36
  from c2cgeoform.views.abstract_views import AbstractViews, ItemAction, ListField, UserMessage
34
37
  from deform.widget import FormWidget
35
- from pyramid.httpexceptions import HTTPNotFound
38
+ from pyramid.httpexceptions import HTTPFound
36
39
  from pyramid.view import view_config, view_defaults
37
40
  from sqlalchemy import inspect
38
41
 
39
42
  from c2cgeoportal_admin import _
40
43
  from c2cgeoportal_admin.lib.ogcserver_synchronizer import OGCServerSynchronizer
44
+ from c2cgeoportal_admin.views.logged_views import LoggedViews
41
45
  from c2cgeoportal_commons.lib.literal import Literal
42
- from c2cgeoportal_commons.models.main import OGCServer
46
+ from c2cgeoportal_commons.models import cache_invalidate_cb
47
+ from c2cgeoportal_commons.models.main import LogAction, OGCServer
43
48
 
44
49
  _list_field = partial(ListField, OGCServer)
45
50
 
46
51
  base_schema = GeoFormSchemaNode(OGCServer, widget=FormWidget(fields_template="ogcserver_fields"))
47
52
  base_schema.add_unique_validator(OGCServer.name, OGCServer.id)
48
53
 
54
+ LOG = logging.getLogger(__name__)
55
+
49
56
 
50
57
  @view_defaults(match_param="table=ogc_servers")
51
- class OGCServerViews(AbstractViews): # type: ignore
58
+ class OGCServerViews(LoggedViews):
52
59
  """The OGC server administration view."""
53
60
 
54
61
  _list_fields = [
@@ -84,10 +91,7 @@ class OGCServerViews(AbstractViews): # type: ignore
84
91
  return super().grid() # type: ignore
85
92
 
86
93
  def schema(self) -> GeoFormSchemaNode:
87
- try:
88
- obj = self._get_object()
89
- except HTTPNotFound:
90
- obj = None
94
+ obj = self._get_object()
91
95
 
92
96
  schema = self._base_schema.clone()
93
97
  schema["url"].description = Literal(
@@ -107,6 +111,22 @@ class OGCServerViews(AbstractViews): # type: ignore
107
111
  def _item_actions(self, item: OGCServer, readonly: bool = False) -> List[Any]:
108
112
  actions = cast(List[Any], super()._item_actions(item, readonly))
109
113
  if inspect(item).persistent:
114
+ actions.insert(
115
+ next((i for i, v in enumerate(actions) if v.name() == "delete")),
116
+ ItemAction(
117
+ name="clear-cache",
118
+ label=_("Clear the cache"),
119
+ icon="glyphicon glyphicon-hdd",
120
+ url=self._request.route_url(
121
+ "ogc_server_clear_cache",
122
+ id=getattr(item, self._id_field),
123
+ _query={
124
+ "came_from": self._request.current_route_url(),
125
+ },
126
+ ),
127
+ confirmation=_("The current changes will be lost."),
128
+ ),
129
+ )
110
130
  actions.insert(
111
131
  next((i for i, v in enumerate(actions) if v.name() == "delete")),
112
132
  ItemAction(
@@ -127,8 +147,11 @@ class OGCServerViews(AbstractViews): # type: ignore
127
147
  @view_config( # type: ignore
128
148
  route_name="c2cgeoform_item", request_method="POST", renderer="../templates/edit.jinja2"
129
149
  )
130
- def save(self) -> Dict[str, Any]:
131
- return super().save() # type: ignore
150
+ def save(self) -> Union[HTTPFound, Dict[str, Any]]:
151
+ result: Union[HTTPFound, Dict[str, Any]] = super().save()
152
+ if isinstance(result, HTTPFound):
153
+ self._update_cache(self._obj)
154
+ return result
132
155
 
133
156
  @view_config(route_name="c2cgeoform_item", request_method="DELETE", renderer="fast_json") # type: ignore
134
157
  def delete(self) -> Dict[str, Any]:
@@ -143,7 +166,9 @@ class OGCServerViews(AbstractViews): # type: ignore
143
166
  _query=[("msg_col", "cannot_delete")],
144
167
  ),
145
168
  }
146
- return super().delete() # type: ignore
169
+ result: Dict[str, Any] = super().delete()
170
+ cache_invalidate_cb()
171
+ return result
147
172
 
148
173
  @view_config( # type: ignore
149
174
  route_name="c2cgeoform_item_duplicate", request_method="GET", renderer="../templates/edit.jinja2"
@@ -176,16 +201,45 @@ class OGCServerViews(AbstractViews): # type: ignore
176
201
  force_ordering=force_ordering,
177
202
  clean=clean,
178
203
  )
204
+
179
205
  if "check" in self._request.params:
180
206
  synchronizer.check_layers()
207
+
181
208
  elif "dry-run" in self._request.params:
182
209
  synchronizer.synchronize(dry_run=True)
210
+
183
211
  elif "synchronize" in self._request.params:
184
212
  synchronizer.synchronize()
213
+
214
+ self._create_log(LogAction.SYNCHRONIZE, obj)
215
+
185
216
  return {
186
217
  "ogcserver": obj,
187
218
  "success": True,
188
219
  "report": synchronizer.report(),
189
220
  }
190
221
 
222
+ self._update_cache(obj)
223
+
191
224
  return {}
225
+
226
+ def _update_cache(self, ogc_server: OGCServer) -> None:
227
+ try:
228
+ ogc_server_id = ogc_server.id
229
+
230
+ def update_cache() -> None:
231
+ response = requests.get(
232
+ self._request.route_url(
233
+ "ogc_server_clear_cache",
234
+ id=ogc_server_id,
235
+ _query={
236
+ "came_from": self._request.current_route_url(),
237
+ },
238
+ )
239
+ )
240
+ if not response.ok:
241
+ LOG.error("Error while cleaning the OGC server cache:\n%s", response.text)
242
+
243
+ threading.Thread(target=update_cache).start()
244
+ except Exception:
245
+ LOG.error("Error on cleaning the OGC server cache", exc_info=True)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021, Camptocamp SA
1
+ # Copyright (c) 2017-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -30,13 +30,14 @@ from functools import partial
30
30
 
31
31
  import colander
32
32
  from c2cgeoform.schema import GeoFormManyToManySchemaNode, GeoFormSchemaNode
33
- from c2cgeoform.views.abstract_views import AbstractViews, ListField
33
+ from c2cgeoform.views.abstract_views import ListField
34
34
  from deform.widget import FormWidget
35
35
  from pyramid.view import view_config, view_defaults
36
36
  from sqlalchemy.orm import subqueryload
37
37
 
38
38
  from c2cgeoportal_admin.schemas.roles import roles_schema_node
39
39
  from c2cgeoportal_admin.schemas.treegroup import treeitem_edit_url
40
+ from c2cgeoportal_admin.views.logged_views import LoggedViews
40
41
  from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
41
42
  from c2cgeoportal_commons.models.main import Layer, RestrictionArea
42
43
 
@@ -87,7 +88,7 @@ base_schema.add(
87
88
 
88
89
 
89
90
  @view_defaults(match_param="table=restriction_areas")
90
- class RestrictionAreaViews(AbstractViews): # type: ignore
91
+ class RestrictionAreaViews(LoggedViews):
91
92
  """The restriction area administration view."""
92
93
 
93
94
  _list_fields = [
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021, Camptocamp SA
1
+ # Copyright (c) 2017-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -30,13 +30,14 @@ from functools import partial
30
30
 
31
31
  import colander
32
32
  from c2cgeoform.schema import GeoFormManyToManySchemaNode, GeoFormSchemaNode
33
- from c2cgeoform.views.abstract_views import AbstractViews, ListField
33
+ from c2cgeoform.views.abstract_views import ListField
34
34
  from deform.widget import FormWidget
35
35
  from pyramid.view import view_config, view_defaults
36
36
  from sqlalchemy.orm import subqueryload
37
37
 
38
38
  from c2cgeoportal_admin.schemas.functionalities import functionalities_schema_node
39
39
  from c2cgeoportal_admin.schemas.restriction_areas import restrictionareas_schema_node
40
+ from c2cgeoportal_admin.views.logged_views import LoggedViews
40
41
  from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
41
42
  from c2cgeoportal_commons.models.main import Role
42
43
  from c2cgeoportal_commons.models.static import User
@@ -99,7 +100,7 @@ base_schema["users"].children[0].description = ""
99
100
 
100
101
 
101
102
  @view_defaults(match_param="table=roles")
102
- class RoleViews(AbstractViews): # type: ignore
103
+ class RoleViews(LoggedViews):
103
104
  """The roles administration view."""
104
105
 
105
106
  _list_fields = [
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021, Camptocamp SA
1
+ # Copyright (c) 2017-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021, Camptocamp SA
1
+ # Copyright (c) 2017-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,18 @@
29
29
  from functools import partial
30
30
 
31
31
  import sqlalchemy
32
- from c2cgeoform.views.abstract_views import AbstractViews, ListField
32
+ from c2cgeoform.views.abstract_views import ListField
33
33
  from pyramid.view import view_config
34
34
  from sqlalchemy.orm import subqueryload
35
35
  from sqlalchemy.sql.functions import concat
36
36
 
37
+ from c2cgeoportal_admin.views.logged_views import LoggedViews
37
38
  from c2cgeoportal_commons.models.main import LayergroupTreeitem, Metadata, TreeGroup, TreeItem
38
39
 
39
40
  _list_field = partial(ListField, TreeItem)
40
41
 
41
42
 
42
- class TreeItemViews(AbstractViews): # type: ignore
43
+ class TreeItemViews(LoggedViews):
43
44
  """The admin tree item view."""
44
45
 
45
46
  _list_fields = [
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2022, Camptocamp SA
1
+ # Copyright (c) 2017-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
29
29
  from functools import partial
30
30
 
31
31
  from c2cgeoform.schema import GeoFormSchemaNode
32
- from c2cgeoform.views.abstract_views import AbstractViews, ListField
32
+ from c2cgeoform.views.abstract_views import ListField
33
33
  from deform.widget import FormWidget
34
34
  from passwordgenerator import pwgenerator
35
35
  from pyramid.httpexceptions import HTTPFound
@@ -37,9 +37,10 @@ from pyramid.view import view_config, view_defaults
37
37
  from sqlalchemy.orm import aliased, subqueryload
38
38
 
39
39
  from c2cgeoportal_admin.schemas.roles import roles_schema_node
40
+ from c2cgeoportal_admin.views.logged_views import LoggedViews
40
41
  from c2cgeoportal_commons.lib.email_ import send_email_config
41
42
  from c2cgeoportal_commons.models.main import Role
42
- from c2cgeoportal_commons.models.static import User
43
+ from c2cgeoportal_commons.models.static import Log, User
43
44
 
44
45
  _list_field = partial(ListField, User)
45
46
 
@@ -51,7 +52,7 @@ settings_role = aliased(Role)
51
52
 
52
53
 
53
54
  @view_defaults(match_param="table=users")
54
- class UserViews(AbstractViews): # type: ignore
55
+ class UserViews(LoggedViews):
55
56
  """The admin user view."""
56
57
 
57
58
  _list_fields = [
@@ -76,6 +77,8 @@ class UserViews(AbstractViews): # type: ignore
76
77
  _id_field = "id"
77
78
  _model = User
78
79
  _base_schema = base_schema
80
+ _log_model = Log
81
+ _name_field = "username"
79
82
 
80
83
  def _base_query(self):
81
84
  return (
@@ -90,11 +90,11 @@ class ChildWidget(MappingWidget): # type: ignore
90
90
  model = TreeItem
91
91
  label_field = "name"
92
92
 
93
- def icon_class(self, child: Any) -> Optional[str]: # pylint: disable=no-self-use,useless-return
93
+ def icon_class(self, child: Any) -> Optional[str]: # pylint: disable=useless-return
94
94
  del child
95
95
  return None
96
96
 
97
- def edit_url( # pylint: disable=no-self-use,useless-return
97
+ def edit_url( # pylint: disable=useless-return
98
98
  self, request: pyramid.request.Request, child: Any
99
99
  ) -> Optional[str]:
100
100
  del request
@@ -1,11 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: c2cgeoportal-admin
3
- Version: 2.7.1.156
3
+ Version: 2.8.1.87
4
4
  Summary: c2cgeoportal admin
5
5
  Home-page: https://github.com/camptocamp/c2cgeoportal/
6
6
  Author: Camptocamp
7
7
  Author-email: info@camptocamp.com
8
+ License: UNKNOWN
8
9
  Keywords: web gis geoportail c2cgeoportal geocommune pyramid
10
+ Platform: UNKNOWN
9
11
  Classifier: Development Status :: 6 - Mature
10
12
  Classifier: Environment :: Web Environment
11
13
  Classifier: Framework :: Pyramid
@@ -18,23 +20,25 @@ Classifier: Programming Language :: Python :: 3.8
18
20
  Classifier: Topic :: Scientific/Engineering :: GIS
19
21
  Classifier: Typing :: Typed
20
22
  Description-Content-Type: text/markdown
23
+ Requires-Dist: babel (>=2.9.1)
21
24
  Requires-Dist: c2cgeoform
22
25
  Requires-Dist: c2cwsgiutils
26
+ Requires-Dist: certifi (>=2022.12.7)
23
27
  Requires-Dist: colander
24
28
  Requires-Dist: deform
29
+ Requires-Dist: idna (>=3.7)
25
30
  Requires-Dist: passwordgenerator
31
+ Requires-Dist: pygments (>=2.15.0)
26
32
  Requires-Dist: pyproj
27
33
  Requires-Dist: pyramid
28
34
  Requires-Dist: pyramid-debugtoolbar
29
35
  Requires-Dist: pyramid-jinja2
30
36
  Requires-Dist: pyramid-tm
37
+ Requires-Dist: requests (>=2.31.0)
31
38
  Requires-Dist: sqlalchemy
32
- Requires-Dist: zope.event
33
39
  Requires-Dist: translationstring
34
- Requires-Dist: jinja2 (>=2.11.3)
35
- Requires-Dist: pygments (>=2.7.4)
36
- Requires-Dist: setuptools (>=65.5.1)
37
- Requires-Dist: requests (>=2.31.0)
40
+ Requires-Dist: urllib3 (>=1.26.17)
41
+ Requires-Dist: zope.event
38
42
 
39
43
  # c2cgeoportal admin interface
40
44
 
@@ -47,4 +51,6 @@ make preparedev
47
51
  make serve
48
52
  ```
49
53
 
50
- Now open http://localhost:8888/ in your favorite browser.
54
+ Now open http://localhost:8888/admin/ in your favorite browser.
55
+
56
+
@@ -1,16 +1,16 @@
1
- c2cgeoportal_admin/__init__.py,sha256=4UYLGCcfxd8mfHojIalTFmaYNgD67WFbgVhw2sl5yok,4959
1
+ c2cgeoportal_admin/__init__.py,sha256=uuW2AC81qIXn7bH7MLHzf9fhEK4liGg3Zi-TosyzKNs,5478
2
2
  c2cgeoportal_admin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- c2cgeoportal_admin/routes.py,sha256=So17Lj2v8UigkxVwfYJrK_piDejRkvekPiFibyr3qiw,4676
3
+ c2cgeoportal_admin/routes.py,sha256=tgLP5uKhgX80a2gLCpu6C92UtmqwVkOkmJ-tPxEP3QE,4712
4
4
  c2cgeoportal_admin/subscribers.py,sha256=P1CaccDTpuxrWak_gMN2qBurz3OrAZ6aZ1LA7P3avu8,2430
5
- c2cgeoportal_admin/widgets.py,sha256=tW6brDW-95LuRnSsRd_8xVRKNAkwkYtdi8zQ44TBj18,6132
5
+ c2cgeoportal_admin/widgets.py,sha256=bjMlC4mqx_bAjzIzzu-zqdQ7bc6tVo7mKOMbpmbeN38,6108
6
6
  c2cgeoportal_admin/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  c2cgeoportal_admin/lib/lingua_extractor.py,sha256=Dw4vo46TcUnJ7vvxgFezPYidfEdL2pHJUM0qxAaJ1KE,3380
8
- c2cgeoportal_admin/lib/ogcserver_synchronizer.py,sha256=NuCV8EpUso01to2PYbh6NpXPcD702pQOSslah__Bzus,15421
8
+ c2cgeoportal_admin/lib/ogcserver_synchronizer.py,sha256=Px9SzBAv5qDTtF1xu6IRzr1u77TA8eAC3cjgI0Rxgks,15515
9
9
  c2cgeoportal_admin/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  c2cgeoportal_admin/schemas/dimensions.py,sha256=rPMEuIdGiVGS5e0xqXUu-COVKlrWg9rpp-xe-8aHbOQ,2290
11
11
  c2cgeoportal_admin/schemas/functionalities.py,sha256=AptqKn2oyy74qivzihNfeNvmaDILsl36bSoJdSNXh9Y,3941
12
12
  c2cgeoportal_admin/schemas/interfaces.py,sha256=0NCRDZOqbw7Bwj-l3GNsVwYDHck4F0q1fCSo1kTYoOY,2578
13
- c2cgeoportal_admin/schemas/metadata.py,sha256=px0Teh0vtyimQfzL7zXHXIEkWtBbD00OsadfDDeqSkY,8991
13
+ c2cgeoportal_admin/schemas/metadata.py,sha256=EOr9hWYBPBJ3iaUmPFgtWnBaNWadX0g9UQ0eeJ6N84E,8991
14
14
  c2cgeoportal_admin/schemas/restriction_areas.py,sha256=48hFUgFznl_1bYsl490YSXLbXfjCY_f6gURQtB_7eIk,2598
15
15
  c2cgeoportal_admin/schemas/roles.py,sha256=4JJrgZNKsj_wru_YGOWxZTEXGVm0hahbAkYf2aePGzI,2507
16
16
  c2cgeoportal_admin/schemas/treegroup.py,sha256=-s_aKAzwYwS9zVsuqQAp_7M_-c00LVq-R6dC8BiUWk0,7039
@@ -18,7 +18,7 @@ c2cgeoportal_admin/schemas/treeitem.py,sha256=qnjrLd2LD7NCBjXqzw7aRn83cw_hYZbepJ
18
18
  c2cgeoportal_admin/static/layertree.css,sha256=tk54KGW0yRRmdrY35gOCZG3qTsqWtGNEwvBYPQKhaVs,3177
19
19
  c2cgeoportal_admin/static/navbar.css,sha256=QIaAQsb4n17OfwdKEQdmNDVPCP23Yu-oGW4xsSaHyW0,2307
20
20
  c2cgeoportal_admin/static/theme.css,sha256=eHtBEJcBtDhyZJvCKNxE5hgril0VpLtcDKfNFdgCSVw,2025
21
- c2cgeoportal_admin/templates/404.jinja2,sha256=F05OZUzJljcieoCFMP7Oz1F6Jb-VZ06hTOSc9mrb87g,1420
21
+ c2cgeoportal_admin/templates/404.jinja2,sha256=KSpqCNFwv37rKSmX6kL_VvCnn5egcT1eRD6kIKwWx34,1807
22
22
  c2cgeoportal_admin/templates/edit.jinja2,sha256=rkBQiz0JZdL7VDq8XrhRLTv6JaiFt_QB8CwP3NMHWQY,1302
23
23
  c2cgeoportal_admin/templates/home.jinja2,sha256=WDQwmBGMZxsiOLw9YeYPLuca_mjjntjrTh529euzd1o,1516
24
24
  c2cgeoportal_admin/templates/index.jinja2,sha256=HPgilbqh5dv-yc_T_bc1hV2DEtV2wD617_aAERC2VSk,2005
@@ -34,59 +34,62 @@ c2cgeoportal_admin/templates/widgets/functionality_fields.pt,sha256=8TvwXCmQOtYF
34
34
  c2cgeoportal_admin/templates/widgets/layer_fields.pt,sha256=RJBYt8ji6YQp9ZaNZJD-caLgy856a6rzlKSMnuZWphw,3223
35
35
  c2cgeoportal_admin/templates/widgets/layer_group_fields.pt,sha256=xnqIqFjPPan81OqLwKeDnvNtlhEvYss6h2J9txH5neE,2459
36
36
  c2cgeoportal_admin/templates/widgets/layer_v1_fields.pt,sha256=w-MujUevHWmnOkOTbbvES6alDoL_UO1eiMj8SCxcQEY,3956
37
- c2cgeoportal_admin/templates/widgets/metadata.pt,sha256=jWiLmS0J-cwFkqUxxZwKnkPNX9ShTG2zj0tUCq4TMjQ,3735
37
+ c2cgeoportal_admin/templates/widgets/metadata.pt,sha256=P8noHX8YAv3m6EGh0IDUJCFsyeZDX88HtlqOWab8DAU,3735
38
38
  c2cgeoportal_admin/templates/widgets/metadatas.pt,sha256=ErgAH0DA94MO7gqEJ2iZdQ9LRptP2YKH78yze-jdl2Q,1476
39
39
  c2cgeoportal_admin/templates/widgets/ogcserver_fields.pt,sha256=x0bDmgrnj9SA6RCVpg3k2lTkkXPkuBFPKMScDgDeyGU,1724
40
40
  c2cgeoportal_admin/templates/widgets/restriction_area_fields.pt,sha256=pZVE0KcitAF7HXc3ZlniLr0QwSD05TOhlgieLUR1i7Q,1731
41
41
  c2cgeoportal_admin/templates/widgets/role_fields.pt,sha256=gVd9eRYaqw8fGmZauqEUS_Igmyxaa71qcmdC1KUx5nY,2623
42
42
  c2cgeoportal_admin/templates/widgets/theme_fields.pt,sha256=68G1Ya8-Dc6pCeP-taQ0ofCIpnY_v0rouazkFhfQflU,3083
43
43
  c2cgeoportal_admin/templates/widgets/user_fields.pt,sha256=twmajhUYL1xa47Eu-iATKifNPA5lu3SGpqdKajH6gL8,1753
44
- c2cgeoportal_admin/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ c2cgeoportal_admin/views/__init__.py,sha256=jtI6CdoXJwizznjwb8ClYySgq4kbwhTIJYutSw89PAw,683
45
45
  c2cgeoportal_admin/views/dimension_layers.py,sha256=jupwqX_kO37ukcWE-SsO290JdKENEmfoYxk4sRWb25Y,2598
46
- c2cgeoportal_admin/views/functionalities.py,sha256=U51DvRd6Jg40VQm66kyVy363cDGGEol0WwaQC8b2ZKM,4002
46
+ c2cgeoportal_admin/views/functionalities.py,sha256=4oZYgs2_M0Usb3GBi40gCP6XvTbR-1PhCDZXiBnhsuk,4031
47
47
  c2cgeoportal_admin/views/home.py,sha256=h_hJWIKpzJeSmXl58J0nvZdEg7avSYOOVUEEnlV-r0k,1943
48
- c2cgeoportal_admin/views/interfaces.py,sha256=3Sl-57PchMlUw_RrvL7F4KTpa57ifpNjOxk-nWqMXpk,3465
49
- c2cgeoportal_admin/views/layer_groups.py,sha256=CbuURDXMcRXnWbW9aEhXP9nSiSiFq4m3JdtgQS6agxs,3956
48
+ c2cgeoportal_admin/views/interfaces.py,sha256=gzIRrd4D64iSH7NVaR-9oQh8-iMzjZOW5QfTfpQeYU4,3494
49
+ c2cgeoportal_admin/views/layer_groups.py,sha256=Zcdr26jyo4ZZw7sr6hYOjo6PuI9-StQ5KQ7OlIxSEtY,3956
50
50
  c2cgeoportal_admin/views/layers.py,sha256=xjvcRvKVpeD-LRuVwE8PGkDT-Kih9ADX0beEDcOP1bE,3039
51
51
  c2cgeoportal_admin/views/layers_vectortiles.py,sha256=lREdMc7bo2TVqdf-s6MzNXZoauReqFS_K-Hng49NUT4,4932
52
- c2cgeoportal_admin/views/layers_wms.py,sha256=p3g2zc2waMBBrlFQjgTUn9YTg3WcXQofx5Yw1b3ozAg,7954
53
- c2cgeoportal_admin/views/layers_wmts.py,sha256=IxvF_knk3HYsa8gKhIaZsyi5Uhmv_Qrmd50gU8BPla8,7731
54
- c2cgeoportal_admin/views/layertree.py,sha256=x1nTVwyf-ZK7M0gIDpsDdySMZm3XmE6yGEE9j8VYQ4Y,8589
55
- c2cgeoportal_admin/views/oauth2_clients.py,sha256=hovhxGKK3et_Lny7UuXsterP_OUSZ1HW7YqhawEXrOw,3740
56
- c2cgeoportal_admin/views/ogc_servers.py,sha256=rK0dIS2XLTc5EDeGrnDf_mpHlNXJsCEyUpci_lIexR8,7476
57
- c2cgeoportal_admin/views/restriction_areas.py,sha256=0Zpo8p5Zsw3JdPCH8kqWr020boBpNiKMhARKcgCsOVU,5549
58
- c2cgeoportal_admin/views/roles.py,sha256=7BjQ0zLcsf6JW8OgBKJukaMRksUB-VKTeILfhP9bLG0,5858
59
- c2cgeoportal_admin/views/themes.py,sha256=Qv6sZ7op90JEd7ASGuTU68rjTdsRrGlf0clYqqumuFI,5710
52
+ c2cgeoportal_admin/views/layers_wms.py,sha256=Kpgr-eWME9zxahkf-re1w6wkToKBqyInmqd_DHhj9Kc,8040
53
+ c2cgeoportal_admin/views/layers_wmts.py,sha256=HNZalKLLhPF7aXLxuFP07yr9-MGnJTg-CVD-GeokvMM,7815
54
+ c2cgeoportal_admin/views/layertree.py,sha256=plb5fL9vTaSe9EFp8VmUWl5iD9FuiQ-3TuStKAGjIKo,8587
55
+ c2cgeoportal_admin/views/logged_views.py,sha256=_XHoIl7Lw3SV_1T0c0JUeIhkluzNnjNrSUgimfk993E,3169
56
+ c2cgeoportal_admin/views/logs.py,sha256=I4ZnfNtBZmriDLIzLpLiX5HPm3Y1UvIQehemPbC2rL0,3616
57
+ c2cgeoportal_admin/views/oauth2_clients.py,sha256=lfMSwZW7pybQx3PR1btRY7XFLfx1TOx7ooVgllOqK-s,3798
58
+ c2cgeoportal_admin/views/ogc_servers.py,sha256=nGTs_pDr2knS_NAakqvxmjZE2ulrWxn2puWA_uNqgaY,9412
59
+ c2cgeoportal_admin/views/restriction_areas.py,sha256=uzfQQVRFCP-OCg1sdGzQCTkO35C1H8DZNMWIquFQqRw,5578
60
+ c2cgeoportal_admin/views/roles.py,sha256=VP0OEsW2_l99YnxGO5mdOkvPBs4Hs3nyRSbetIKtx14,5887
61
+ c2cgeoportal_admin/views/themes.py,sha256=mxpf56KXwCKG5tCYgV7xgPtQqlCU67iOBOLB7cHD-Hc,5710
60
62
  c2cgeoportal_admin/views/themes_ordering.py,sha256=NYN3I2tDwLW5E4G-695DwV0dCbHUAObWVFYZ8Bir1-o,5590
61
- c2cgeoportal_admin/views/treeitems.py,sha256=p-Ba_v3UFtUZEmlct4MZmkwv7jzMoxNKnCVa_FX2hxg,3860
62
- c2cgeoportal_admin/views/users.py,sha256=YzyKYDDTVn69NQPkrlkmbpgrtsIkK_cxqlcWa6utAVA,5355
63
- tests/__init__.py,sha256=JbVMbOZgS0u5_MhWBnyzT1gdv3cXwhkXyLQgDqpZAik,9525
63
+ c2cgeoportal_admin/views/treeitems.py,sha256=C-vjScmb_HI5QOowx3MGZBJqAHDkGTG90vshPG7FvgA,3889
64
+ c2cgeoportal_admin/views/users.py,sha256=sXCgVluLLnbbQTG8Q7tmaVfnEcHj5fBiHFCG7owVp1w,5439
65
+ tests/__init__.py,sha256=oo8kqGfoSh8AV0HhTqQfC0izcIQ8ZQPkNmONSEUUby4,9556
64
66
  tests/conftest.py,sha256=ah7JmR2epDZul2rmMH5wuUzkSpXIjm8dd-cgGjK6_k0,2119
65
- tests/test_edit_url.py,sha256=00Q9E3QOtsEEB0YJQehllFr1ztQCU3wc9OyayXCHYI4,4495
66
- tests/test_functionalities.py,sha256=CPHxBueoCt8W76VJN2sCouxQyc7LD7ccusRah5UK2ys,4126
67
- tests/test_home.py,sha256=oA4i-V9jJQQgHD9Gz79mgIEMUCRw3tmIQVqdhM9Q2Fo,426
68
- tests/test_interface.py,sha256=ml1yM4t1o6jIQEHZRwMywjt7mjkUhP-34VKBgHOmWes,4704
69
- tests/test_layer_groups.py,sha256=Bb1Rsy8QkzGee6edY4UQY8hcxvp54PE7gXUcHoi__JA,11062
70
- tests/test_layers_vectortiles.py,sha256=DjOLkm3o8nPJJbd010Xi_pwHTK5roiHoQBYAuNaZW5c,9395
71
- tests/test_layers_wms.py,sha256=MISvkAjEZ4oSD1xg7Zah_GKiBHNu60D8kT03f241wuc,18175
72
- tests/test_layers_wmts.py,sha256=jjO3AbOQgHgC2yXdYke339W11Ygz1b8DpuAn4OXLnxE,11185
73
- tests/test_layertree.py,sha256=uu-2AzVtqr87eqq9w_5EWPR_KIXFFjEipEA0_ImnkCU,11336
67
+ tests/test_edit_url.py,sha256=Mo_Vo5xvdpPasfjvhQUif5F3nKVpJ6GQJ_x_Hj5VNY8,4494
68
+ tests/test_functionalities.py,sha256=tGQbEsQWjr_oExI3vWhLIioxylDaoUaOfEas42YPw50,5191
69
+ tests/test_home.py,sha256=oWsKaWqRicNpUdaca54YvLIBRaGYnsXlv_Tjqv7guEQ,425
70
+ tests/test_interface.py,sha256=z1jpRzW0R2e9BJWWurE-j-YkG5yhorn7h1XRIauUQ7A,5669
71
+ tests/test_layer_groups.py,sha256=bisbaDY0SiyBc0rexYajbcvfdDt8Kux6VqXIEBLSULM,12191
72
+ tests/test_layers_vectortiles.py,sha256=PpnR8wJyRcsByPTOrrtltQUYzzQ0qRzQM2no1z1rLgU,10404
73
+ tests/test_layers_wms.py,sha256=ynqO1cnXk2ZbSXR3l9hp0IyG8PMXbmR4eyubnwRvRfU,19494
74
+ tests/test_layers_wmts.py,sha256=7zye_pZ_e0RyJdoT8oeHKPoYJMKWfTg0K8lEgMIu77Q,12181
75
+ tests/test_layertree.py,sha256=Dxe10OwuilQ-AEgVIDU4Ns9U6PQ4kPWTxwItdBE7nSg,11335
74
76
  tests/test_learn.py,sha256=gQwe-Bim0eihZH0rbBWDn6_rIBxvQD_lyu9MlOljupM,2307
75
- tests/test_left_menu.py,sha256=-K_429ZcW5Hsz317StIRVz8VtU7GDMH7UCTzZDfckUo,920
76
- tests/test_lingua_extractor_config.py,sha256=3dqgIdCB1M3YPzXrgDCFQ74t0t4QRXwdQZSy6AMqKp8,2515
77
+ tests/test_left_menu.py,sha256=xnlv5sD0k3wpCChKCnbpYRN0TA895pg8k6wVvjf99-4,919
78
+ tests/test_lingua_extractor_config.py,sha256=vAfunJ4tVuqTJg4xinPwlB0EvA4sYhjY_iDBfMq8EW4,2495
79
+ tests/test_logs.py,sha256=sUBC61rCSIfg9HBavhT6c0QPmPYUnEfDm91bUaUF4Q8,3147
77
80
  tests/test_main.py,sha256=_gUdMrMMAEzvGIf1QwkoHQkd0eBACz05ycTidCHP5Ao,365
78
- tests/test_metadatas.py,sha256=dawAKLxyWy4Ok3TWAR5zsB_IN_Ci_VJdjNE9fU5NVjE,12089
79
- tests/test_oauth2_clients.py,sha256=UaTz7jE0-V2JJ4VkjA3W0FlzgkfacI1jchiynXNNYbc,5782
80
- tests/test_ogc_servers.py,sha256=qPrbLFw8zaPOpk-fbydJUtfgLl9nxA81jOUNd1l8EUI,6436
81
- tests/test_restriction_areas.py,sha256=S97lbxHghyhz9h8Sv78jYt2EOQEgwlUp8zCfOtmV-OU,7925
82
- tests/test_role.py,sha256=99Rk4PCTtoVzbiTP3cR3cVkuIArdLywBl2Hx8Pk5lnE,11820
83
- tests/test_themes.py,sha256=e-OGon6beHfY4q8xOGsYjW-_pm0-wTA18DPBOz6F9iM,15181
84
- tests/test_themes_ordering.py,sha256=qIEgLgIjSYpWqMVXBAhOk6BKBUAPXkiXsxWB_A1Dy4s,2244
81
+ tests/test_metadatas.py,sha256=bVNxvZRKNRMmjQGr7Al1d4H85EjEaoesRpxytyld4Fw,12088
82
+ tests/test_oauth2_clients.py,sha256=-aowsa2Dw77lxzuBb9ULW4iEJSB9yut-eYGP7YptT0M,7000
83
+ tests/test_ogc_servers.py,sha256=DGSMVIzYnw3bJT53VFGuPYIPMPCyHJDb5ZPJj1VM3Bo,8204
84
+ tests/test_restriction_areas.py,sha256=5VhO9ZvtFQPy1kVFm96Mh_vf1LCI5oeIdl0dfvS6JD8,9003
85
+ tests/test_role.py,sha256=eD7dXwP7RjCg14T9ncTfJuMUU4caY9yW3l5ka-gtCd4,12776
86
+ tests/test_themes.py,sha256=uhzHe2TbuNoLnL4VdYATPnOqtnZWWPKsvUTq6GUxwiU,16207
87
+ tests/test_themes_ordering.py,sha256=T4Esr0C3EN5UdeEyYLa4ePvEn-bx3RNPkGBK3lDFoBo,2243
85
88
  tests/test_treegroup.py,sha256=Plv119G4TWlurWLE7Z1mWGeHHPScK_fWKcDmDzMUlIU,576
86
- tests/test_user.py,sha256=pW2Fsbw8wIP2H3BxAMUojSonhMMyr63jsWFmEteaogk,11659
87
- tests/themes_ordering.py,sha256=mbjTJHl63UVdv5SsfgDrjOx-1z6C5L4wDSCzIh7LPAE,1343
88
- c2cgeoportal_admin-2.7.1.156.dist-info/METADATA,sha256=cRegyrlS02-K1HNMG99ohp7l0WSyWQpqnPMJC7zInU4,1492
89
- c2cgeoportal_admin-2.7.1.156.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
90
- c2cgeoportal_admin-2.7.1.156.dist-info/entry_points.txt,sha256=ZF-xnP-Q_zr7y6yRmVqjIGVZ1L2iKi5uaOxjxJQBuG4,164
91
- c2cgeoportal_admin-2.7.1.156.dist-info/top_level.txt,sha256=DgcTJgTvpJUB8HqwYB14PdLBPAOAFk0B8oqnSTFoAU4,25
92
- c2cgeoportal_admin-2.7.1.156.dist-info/RECORD,,
89
+ tests/test_user.py,sha256=xD0yoJa_babVK69hHQzDkTs6wRWBMXFGD8k0-DfOd-4,12814
90
+ tests/themes_ordering.py,sha256=UdydcRIzWC6RRnTMfl2JM_250DHuAhGC7rijHqfy7lk,1342
91
+ c2cgeoportal_admin-2.8.1.87.dist-info/METADATA,sha256=0P1ADIuP41MRtydXCS-ldsnsw6lk4Yz_zmGTBaNO3QA,1596
92
+ c2cgeoportal_admin-2.8.1.87.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
93
+ c2cgeoportal_admin-2.8.1.87.dist-info/entry_points.txt,sha256=kz-7AnYsbtK04jTpGUtcOeu2NbQiXW3CQV3AjyC32tw,165
94
+ c2cgeoportal_admin-2.8.1.87.dist-info/top_level.txt,sha256=DgcTJgTvpJUB8HqwYB14PdLBPAOAFk0B8oqnSTFoAU4,25
95
+ c2cgeoportal_admin-2.8.1.87.dist-info/RECORD,,
@@ -3,3 +3,4 @@ geomapfish-admin-config = c2cgeoportal_admin.lib.lingua_extractor:GeomapfishConf
3
3
 
4
4
  [paste.app_factory]
5
5
  main = c2cgeoportal_admin:main
6
+
tests/__init__.py CHANGED
@@ -54,7 +54,6 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
54
54
 
55
55
  layers = []
56
56
  for i in range(0, 25):
57
-
58
57
  layer = layer_builder(i)
59
58
 
60
59
  if add_dimension:
@@ -90,7 +89,6 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
90
89
 
91
90
 
92
91
  class AbstractViewsTests:
93
-
94
92
  _prefix = None # url prefix (index view url). Example: /users
95
93
 
96
94
  def get(self, test_app, path="", locale="en", status=200, **kwargs):
@@ -120,7 +118,8 @@ class AbstractViewsTests:
120
118
  )
121
119
  actions = resp.html.select_one('th[data-field="actions"]')
122
120
  assert "false" == actions.attrs["data-sortable"]
123
- assert 1 == len(list(filter(lambda x: next(x.stripped_strings) == new, resp.html.findAll("a"))))
121
+ if new is not False:
122
+ assert 1 == len(list(filter(lambda x: next(x.stripped_strings) == new, resp.html.findAll("a"))))
124
123
 
125
124
  def check_search(self, test_app, search="", offset=0, limit=10, sort="", order="", total=None):
126
125
  json = test_app.post(
tests/test_edit_url.py CHANGED
@@ -92,7 +92,6 @@ def edit_url_test_data(dbsession, transact):
92
92
 
93
93
  @pytest.mark.usefixtures("edit_url_test_data", "test_app")
94
94
  class TestUrlEdit(AbstractViewsTests):
95
-
96
95
  _prefix = "/admin/"
97
96
 
98
97
  def _get(self, test_app, tablename, pk):
@@ -31,7 +31,6 @@ def functionality_test_data(dbsession, transact, settings):
31
31
 
32
32
  @pytest.mark.usefixtures("functionality_test_data", "test_app")
33
33
  class TestFunctionality(AbstractViewsTests):
34
-
35
34
  _prefix = "/admin/functionalities"
36
35
 
37
36
  def test_index_rendering(self, test_app):
@@ -53,7 +52,7 @@ class TestFunctionality(AbstractViewsTests):
53
52
  self.check_search(test_app, "default_basemap", total=1)
54
53
 
55
54
  def test_submit_new(self, dbsession, test_app):
56
- from c2cgeoportal_commons.models.main import Functionality
55
+ from c2cgeoportal_commons.models.main import Functionality, Log, LogAction
57
56
 
58
57
  resp = test_app.post(
59
58
  "/admin/functionalities/new",
@@ -66,7 +65,17 @@ class TestFunctionality(AbstractViewsTests):
66
65
  ).group(1)
67
66
  assert functionality.name == "new_name"
68
67
 
69
- def test_edit(self, test_app, functionality_test_data):
68
+ log = dbsession.query(Log).one()
69
+ assert log.date != None
70
+ assert log.action == LogAction.INSERT
71
+ assert log.element_type == "functionality"
72
+ assert log.element_id == functionality.id
73
+ assert log.element_name == functionality.name
74
+ assert log.username == "test_user"
75
+
76
+ def test_edit(self, test_app, functionality_test_data, dbsession):
77
+ from c2cgeoportal_commons.models.main import Log, LogAction
78
+
70
79
  functionality = functionality_test_data["functionalities"][0]
71
80
  resp = test_app.get(f"/admin/functionalities/{functionality.id}", status=200)
72
81
  form = resp.form
@@ -77,14 +86,30 @@ class TestFunctionality(AbstractViewsTests):
77
86
  assert form.submit().status_int == 302
78
87
  assert functionality.description == "new_description"
79
88
 
89
+ log = dbsession.query(Log).one()
90
+ assert log.date != None
91
+ assert log.action == LogAction.UPDATE
92
+ assert log.element_type == "functionality"
93
+ assert log.element_id == functionality.id
94
+ assert log.element_name == functionality.name
95
+ assert log.username == "test_user"
96
+
80
97
  def test_delete(self, test_app, functionality_test_data, dbsession):
81
- from c2cgeoportal_commons.models.main import Functionality
98
+ from c2cgeoportal_commons.models.main import Functionality, Log, LogAction
82
99
 
83
100
  functionality = functionality_test_data["functionalities"][0]
84
101
  deleted_id = functionality.id
85
102
  test_app.delete(f"/admin/functionalities/{deleted_id}", status=200)
86
103
  assert dbsession.query(Functionality).get(deleted_id) is None
87
104
 
105
+ log = dbsession.query(Log).one()
106
+ assert log.date != None
107
+ assert log.action == LogAction.DELETE
108
+ assert log.element_type == "functionality"
109
+ assert log.element_id == functionality.id
110
+ assert log.element_name == functionality.name
111
+ assert log.username == "test_user"
112
+
88
113
  def test_duplicate(self, functionality_test_data, test_app, dbsession):
89
114
  from c2cgeoportal_commons.models.main import Functionality
90
115
 
tests/test_home.py CHANGED
@@ -5,7 +5,6 @@ from . import AbstractViewsTests
5
5
 
6
6
  @pytest.mark.usefixtures("test_app")
7
7
  class TestHome(AbstractViewsTests):
8
-
9
8
  _prefix = "/admin/"
10
9
 
11
10
  def test_index_rendering(self, test_app):