c2cgeoportal-admin 2.7.1.156__py3-none-any.whl → 2.8.1.180__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 (52) 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/schemas/treegroup.py +2 -2
  6. c2cgeoportal_admin/templates/404.jinja2 +18 -2
  7. c2cgeoportal_admin/templates/widgets/metadata.pt +1 -1
  8. c2cgeoportal_admin/views/__init__.py +29 -0
  9. c2cgeoportal_admin/views/functionalities.py +4 -3
  10. c2cgeoportal_admin/views/interfaces.py +4 -3
  11. c2cgeoportal_admin/views/layer_groups.py +1 -1
  12. c2cgeoportal_admin/views/layers_wms.py +5 -3
  13. c2cgeoportal_admin/views/layers_wmts.py +5 -3
  14. c2cgeoportal_admin/views/layertree.py +2 -2
  15. c2cgeoportal_admin/views/logged_views.py +80 -0
  16. c2cgeoportal_admin/views/logs.py +90 -0
  17. c2cgeoportal_admin/views/oauth2_clients.py +9 -6
  18. c2cgeoportal_admin/views/ogc_servers.py +66 -12
  19. c2cgeoportal_admin/views/restriction_areas.py +4 -3
  20. c2cgeoportal_admin/views/roles.py +4 -3
  21. c2cgeoportal_admin/views/themes.py +1 -1
  22. c2cgeoportal_admin/views/treeitems.py +4 -3
  23. c2cgeoportal_admin/views/users.py +7 -4
  24. c2cgeoportal_admin/widgets.py +2 -2
  25. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/METADATA +13 -7
  26. c2cgeoportal_admin-2.8.1.180.dist-info/RECORD +95 -0
  27. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/entry_points.txt +1 -0
  28. tests/__init__.py +2 -3
  29. tests/test_edit_url.py +0 -1
  30. tests/test_functionalities.py +29 -4
  31. tests/test_home.py +0 -1
  32. tests/test_interface.py +27 -4
  33. tests/test_layer_groups.py +45 -11
  34. tests/test_layers_vectortiles.py +33 -8
  35. tests/test_layers_wms.py +43 -10
  36. tests/test_layers_wmts.py +33 -8
  37. tests/test_layertree.py +0 -1
  38. tests/test_left_menu.py +0 -1
  39. tests/test_lingua_extractor_config.py +1 -3
  40. tests/test_logs.py +103 -0
  41. tests/test_metadatas.py +0 -1
  42. tests/test_oauth2_clients.py +35 -7
  43. tests/test_ogc_servers.py +65 -27
  44. tests/test_restriction_areas.py +28 -3
  45. tests/test_role.py +33 -8
  46. tests/test_themes.py +33 -6
  47. tests/test_themes_ordering.py +0 -1
  48. tests/test_user.py +33 -4
  49. tests/themes_ordering.py +0 -1
  50. c2cgeoportal_admin-2.7.1.156.dist-info/RECORD +0 -92
  51. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/WHEEL +0 -0
  52. {c2cgeoportal_admin-2.7.1.156.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/top_level.txt +0 -0
@@ -60,7 +60,6 @@ def layer_groups_test_data(dbsession, transact):
60
60
 
61
61
  @pytest.mark.usefixtures("layer_groups_test_data", "test_app")
62
62
  class TestLayersGroups(TestTreeGroup):
63
-
64
63
  _prefix = "/admin/layer_groups"
65
64
 
66
65
  def test_index_rendering(self, test_app):
@@ -94,6 +93,8 @@ class TestLayersGroups(TestTreeGroup):
94
93
  self.check_search(test_app, "copyable", total=8)
95
94
 
96
95
  def test_edit(self, test_app, layer_groups_test_data, dbsession):
96
+ from c2cgeoportal_commons.models.main import Log, LogAction
97
+
97
98
  group = layer_groups_test_data["groups"][1]
98
99
 
99
100
  form = self.get_item(test_app, group.id).form
@@ -134,6 +135,14 @@ class TestLayersGroups(TestTreeGroup):
134
135
  else:
135
136
  assert str(value or "") == str(getattr(group, key) or "")
136
137
 
138
+ log = dbsession.query(Log).one()
139
+ assert log.date != None
140
+ assert log.action == LogAction.UPDATE
141
+ assert log.element_type == "layergroup"
142
+ assert log.element_id == group.id
143
+ assert log.element_name == group.name
144
+ assert log.username == "test_user"
145
+
137
146
  def test_post_new_with_children_invalid(self, test_app, layer_groups_test_data):
138
147
  """
139
148
  Check there is no rendering error when validation fails.
@@ -159,6 +168,8 @@ class TestLayersGroups(TestTreeGroup):
159
168
  assert "Required" == resp.html.select_one(".item-name .help-block").getText().strip()
160
169
 
161
170
  def test_post_new_with_children_success(self, test_app, dbsession, layer_groups_test_data):
171
+ from c2cgeoportal_commons.models.main import Log, LogAction
172
+
162
173
  groups = layer_groups_test_data["groups"]
163
174
  resp = test_app.post(
164
175
  f"{self._prefix}/new",
@@ -202,6 +213,14 @@ class TestLayersGroups(TestTreeGroup):
202
213
  rel.treeitem_id for rel in group.children_relation
203
214
  ]
204
215
 
216
+ log = dbsession.query(Log).one()
217
+ assert log.date != None
218
+ assert log.action == LogAction.INSERT
219
+ assert log.element_type == "layergroup"
220
+ assert log.element_id == group.id
221
+ assert log.element_name == group.name
222
+ assert log.username == "test_user"
223
+
205
224
  def test_post_with_ancestor(self, layer_groups_test_data, test_app):
206
225
  """
207
226
  Check that ancestors are refused to avoid cycles.
@@ -274,34 +293,49 @@ class TestLayersGroups(TestTreeGroup):
274
293
  self._check_submission_problem(resp, f"{group.name} is already used.")
275
294
 
276
295
  def test_delete(self, test_app, dbsession, layer_groups_test_data):
277
- from c2cgeoportal_commons.models.main import LayerGroup, LayergroupTreeitem, TreeGroup, TreeItem
296
+ from c2cgeoportal_commons.models.main import (
297
+ LayerGroup,
298
+ LayergroupTreeitem,
299
+ Log,
300
+ LogAction,
301
+ TreeGroup,
302
+ TreeItem,
303
+ )
278
304
 
279
- group_id = layer_groups_test_data["groups"][9].id
305
+ group = layer_groups_test_data["groups"][9]
280
306
 
281
307
  assert (
282
308
  3
283
- == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group_id).count()
309
+ == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group.id).count()
284
310
  )
285
311
 
286
312
  assert (
287
313
  1
288
- == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group_id).count()
314
+ == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group.id).count()
289
315
  )
290
316
 
291
- test_app.delete(f"/admin/layer_groups/{group_id}", status=200)
317
+ test_app.delete(f"/admin/layer_groups/{group.id}", status=200)
292
318
 
293
319
  dbsession.expire_all()
294
320
 
295
- assert dbsession.query(LayerGroup).get(group_id) is None
296
- assert dbsession.query(TreeGroup).get(group_id) is None
297
- assert dbsession.query(TreeItem).get(group_id) is None
321
+ assert dbsession.query(LayerGroup).get(group.id) is None
322
+ assert dbsession.query(TreeGroup).get(group.id) is None
323
+ assert dbsession.query(TreeItem).get(group.id) is None
298
324
 
299
325
  assert (
300
326
  0
301
- == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group_id).count()
327
+ == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group.id).count()
302
328
  )
303
329
 
304
330
  assert (
305
331
  0
306
- == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group_id).count()
332
+ == dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group.id).count()
307
333
  )
334
+
335
+ log = dbsession.query(Log).one()
336
+ assert log.date != None
337
+ assert log.action == LogAction.DELETE
338
+ assert log.element_type == "layergroup"
339
+ assert log.element_id == group.id
340
+ assert log.element_name == group.name
341
+ assert log.username == "test_user"
@@ -38,7 +38,6 @@ def layer_vectortiles_test_data(dbsession, transact):
38
38
 
39
39
  @pytest.mark.usefixtures("layer_vectortiles_test_data", "test_app")
40
40
  class TestLayerVectortiles(AbstractViewsTests):
41
-
42
41
  _prefix = "/admin/layers_vectortiles"
43
42
 
44
43
  def test_index_rendering(self, test_app):
@@ -106,6 +105,8 @@ class TestLayerVectortiles(AbstractViewsTests):
106
105
  assert form["public"].checked
107
106
 
108
107
  def test_edit(self, test_app, layer_vectortiles_test_data, dbsession):
108
+ from c2cgeoportal_commons.models.main import Log, LogAction
109
+
109
110
  layer = layer_vectortiles_test_data["layers"][0]
110
111
 
111
112
  form = self.get_item(test_app, layer.id).form
@@ -158,8 +159,16 @@ class TestLayerVectortiles(AbstractViewsTests):
158
159
  assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in layer.interfaces}
159
160
  assert {ras[1].id, ras[3].id} == {ra.id for ra in layer.restrictionareas}
160
161
 
162
+ log = dbsession.query(Log).one()
163
+ assert log.date != None
164
+ assert log.action == LogAction.UPDATE
165
+ assert log.element_type == "layer_vectortiles"
166
+ assert log.element_id == layer.id
167
+ assert log.element_name == layer.name
168
+ assert log.username == "test_user"
169
+
161
170
  def test_submit_new(self, dbsession, test_app, layer_vectortiles_test_data):
162
- from c2cgeoportal_commons.models.main import LayerVectorTiles
171
+ from c2cgeoportal_commons.models.main import LayerVectorTiles, Log, LogAction
163
172
 
164
173
  resp = test_app.post(
165
174
  "/admin/layers_vectortiles/new",
@@ -178,6 +187,14 @@ class TestLayerVectortiles(AbstractViewsTests):
178
187
  r"http://localhost/admin/layers_vectortiles/(.*)\?msg_col=submit_ok", resp.location
179
188
  ).group(1)
180
189
 
190
+ log = dbsession.query(Log).one()
191
+ assert log.date != None
192
+ assert log.action == LogAction.INSERT
193
+ assert log.element_type == "layer_vectortiles"
194
+ assert log.element_id == layer.id
195
+ assert log.element_name == layer.name
196
+ assert log.username == "test_user"
197
+
181
198
  def test_duplicate(self, layer_vectortiles_test_data, test_app, dbsession):
182
199
  from c2cgeoportal_commons.models.main import LayerVectorTiles
183
200
 
@@ -212,12 +229,20 @@ class TestLayerVectortiles(AbstractViewsTests):
212
229
  assert layer_vectortiles_test_data["layers"][3].metadatas[1].name == layer.metadatas[1].name
213
230
 
214
231
  def test_delete(self, test_app, dbsession):
215
- from c2cgeoportal_commons.models.main import Layer, LayerVectorTiles, TreeItem
232
+ from c2cgeoportal_commons.models.main import Layer, LayerVectorTiles, Log, LogAction, TreeItem
233
+
234
+ layer = dbsession.query(LayerVectorTiles).first()
216
235
 
217
- layer_id = dbsession.query(LayerVectorTiles.id).first().id
236
+ test_app.delete(f"/admin/layers_vectortiles/{layer.id}", status=200)
218
237
 
219
- test_app.delete(f"/admin/layers_vectortiles/{layer_id}", status=200)
238
+ assert dbsession.query(LayerVectorTiles).get(layer.id) is None
239
+ assert dbsession.query(Layer).get(layer.id) is None
240
+ assert dbsession.query(TreeItem).get(layer.id) is None
220
241
 
221
- assert dbsession.query(LayerVectorTiles).get(layer_id) is None
222
- assert dbsession.query(Layer).get(layer_id) is None
223
- assert dbsession.query(TreeItem).get(layer_id) is None
242
+ log = dbsession.query(Log).one()
243
+ assert log.date != None
244
+ assert log.action == LogAction.DELETE
245
+ assert log.element_type == "layer_vectortiles"
246
+ assert log.element_id == layer.id
247
+ assert log.element_name == layer.name
248
+ assert log.username == "test_user"
tests/test_layers_wms.py CHANGED
@@ -39,7 +39,6 @@ def layer_wms_test_data(dbsession, transact):
39
39
 
40
40
  @pytest.mark.usefixtures("layer_wms_test_data", "test_app")
41
41
  class TestLayerWMSViews(AbstractViewsTests):
42
-
43
42
  _prefix = "/admin/layers_wms"
44
43
 
45
44
  def test_index_rendering(self, test_app):
@@ -154,6 +153,8 @@ class TestLayerWMSViews(AbstractViewsTests):
154
153
  assert form["public"].checked
155
154
 
156
155
  def test_edit(self, test_app, layer_wms_test_data, dbsession):
156
+ from c2cgeoportal_commons.models.main import Log, LogAction
157
+
157
158
  layer = layer_wms_test_data["layers"][0]
158
159
 
159
160
  form = self.get_item(test_app, layer.id).form
@@ -212,8 +213,16 @@ class TestLayerWMSViews(AbstractViewsTests):
212
213
  assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in layer.interfaces}
213
214
  assert {ras[1].id, ras[3].id} == {ra.id for ra in layer.restrictionareas}
214
215
 
216
+ log = dbsession.query(Log).one()
217
+ assert log.date != None
218
+ assert log.action == LogAction.UPDATE
219
+ assert log.element_type == "layer_wms"
220
+ assert log.element_id == layer.id
221
+ assert log.element_name == layer.name
222
+ assert log.username == "test_user"
223
+
215
224
  def test_submit_new(self, dbsession, test_app, layer_wms_test_data):
216
- from c2cgeoportal_commons.models.main import LayerWMS
225
+ from c2cgeoportal_commons.models.main import LayerWMS, Log, LogAction
217
226
 
218
227
  resp = test_app.post(
219
228
  "/admin/layers_wms/new",
@@ -237,6 +246,14 @@ class TestLayerWMSViews(AbstractViewsTests):
237
246
  r"http://localhost/admin/layers_wms/(.*)\?msg_col=submit_ok", resp.location
238
247
  ).group(1)
239
248
 
249
+ log = dbsession.query(Log).one()
250
+ assert log.date != None
251
+ assert log.action == LogAction.INSERT
252
+ assert log.element_type == "layer_wms"
253
+ assert log.element_id == layer.id
254
+ assert log.element_name == layer.name
255
+ assert log.username == "test_user"
256
+
240
257
  def test_duplicate(self, layer_wms_test_data, test_app, dbsession):
241
258
  from c2cgeoportal_commons.models.main import LayerWMS
242
259
 
@@ -339,12 +356,20 @@ class TestLayerWMSViews(AbstractViewsTests):
339
356
  assert "image/jpeg" == resp.form["image_type"].value
340
357
 
341
358
  def test_convert_without_wmts_defaults(self, test_app, layer_wms_test_data, dbsession):
342
- from c2cgeoportal_commons.models.main import LayerWMTS
359
+ from c2cgeoportal_commons.models.main import LayerWMTS, Log, LogAction
343
360
 
344
361
  dbsession.delete(LayerWMTS.get_default(dbsession))
345
362
  layer = layer_wms_test_data["layers"][3]
346
363
  test_app.post(f"/admin/layers_wms/{layer.id}/convert_to_wmts", status=200)
347
364
 
365
+ log = dbsession.query(Log).one()
366
+ assert log.date != None
367
+ assert log.action == LogAction.CONVERT_TO_WMTS
368
+ assert log.element_type == "layer_wms"
369
+ assert log.element_id == layer.id
370
+ assert log.element_name == layer.name
371
+ assert log.username == "test_user"
372
+
348
373
  def test_unicity_validator(self, layer_wms_test_data, test_app):
349
374
  layer = layer_wms_test_data["layers"][2]
350
375
  resp = test_app.get(f"/admin/layers_wms/{layer.id}/duplicate", status=200)
@@ -371,17 +396,25 @@ class TestLayerWMSViews(AbstractViewsTests):
371
396
  # assert str(layer.id) == re.match('http://localhost/admin/layers_wms/(.*)', resp.location).group(1)
372
397
 
373
398
  def test_delete(self, test_app, dbsession):
374
- from c2cgeoportal_commons.models.main import Layer, LayerWMS, TreeItem
399
+ from c2cgeoportal_commons.models.main import Layer, LayerWMS, Log, LogAction, TreeItem
400
+
401
+ layer = dbsession.query(LayerWMS).first()
375
402
 
376
- layer_id = dbsession.query(LayerWMS.id).first().id
403
+ test_app.delete(f"/admin/layers_wms/{layer.id}", status=200)
377
404
 
378
- test_app.delete(f"/admin/layers_wms/{layer_id}", status=200)
405
+ assert dbsession.query(LayerWMS).get(layer.id) is None
406
+ assert dbsession.query(Layer).get(layer.id) is None
407
+ assert dbsession.query(TreeItem).get(layer.id) is None
379
408
 
380
- assert dbsession.query(LayerWMS).get(layer_id) is None
381
- assert dbsession.query(Layer).get(layer_id) is None
382
- assert dbsession.query(TreeItem).get(layer_id) is None
409
+ log = dbsession.query(Log).one()
410
+ assert log.date != None
411
+ assert log.action == LogAction.DELETE
412
+ assert log.element_type == "layer_wms"
413
+ assert log.element_id == layer.id
414
+ assert log.element_name == layer.name
415
+ assert log.username == "test_user"
383
416
 
384
- def test_submit_new_no_layer_name(self, test_app, layer_wms_test_data):
417
+ def test_submit_new_no_layer_name(self, test_app, layer_wms_test_data, dbsession):
385
418
  resp = test_app.post(
386
419
  "/admin/layers_wms/new",
387
420
  {
tests/test_layers_wmts.py CHANGED
@@ -39,7 +39,6 @@ def layer_wmts_test_data(dbsession, transact):
39
39
 
40
40
  @pytest.mark.usefixtures("layer_wmts_test_data", "test_app")
41
41
  class TestLayerWMTS(AbstractViewsTests):
42
-
43
42
  _prefix = "/admin/layers_wmts"
44
43
 
45
44
  def test_index_rendering(self, test_app):
@@ -102,6 +101,8 @@ class TestLayerWMTS(AbstractViewsTests):
102
101
  assert default_wmts.matrix_set == self.get_first_field_named(form, "matrix_set").value
103
102
 
104
103
  def test_edit(self, test_app, layer_wmts_test_data, dbsession):
104
+ from c2cgeoportal_commons.models.main import Log, LogAction
105
+
105
106
  layer = layer_wmts_test_data["layers"][0]
106
107
 
107
108
  form = self.get_item(test_app, layer.id).form
@@ -160,6 +161,14 @@ class TestLayerWMTS(AbstractViewsTests):
160
161
  assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in layer.interfaces}
161
162
  assert {ras[1].id, ras[3].id} == {ra.id for ra in layer.restrictionareas}
162
163
 
164
+ log = dbsession.query(Log).one()
165
+ assert log.date != None
166
+ assert log.action == LogAction.UPDATE
167
+ assert log.element_type == "layer_wmts"
168
+ assert log.element_id == layer.id
169
+ assert log.element_name == layer.name
170
+ assert log.username == "test_user"
171
+
163
172
  def test_duplicate(self, layer_wmts_test_data, test_app, dbsession):
164
173
  from c2cgeoportal_commons.models.main import LayerWMTS
165
174
 
@@ -190,15 +199,23 @@ class TestLayerWMTS(AbstractViewsTests):
190
199
  ).group(1)
191
200
 
192
201
  def test_delete(self, test_app, dbsession):
193
- from c2cgeoportal_commons.models.main import Layer, LayerWMTS, TreeItem
202
+ from c2cgeoportal_commons.models.main import Layer, LayerWMTS, Log, LogAction, TreeItem
194
203
 
195
- layer_id = dbsession.query(LayerWMTS.id).first().id
204
+ layer = dbsession.query(LayerWMTS).first()
196
205
 
197
- test_app.delete(f"/admin/layers_wmts/{layer_id}", status=200)
206
+ test_app.delete(f"/admin/layers_wmts/{layer.id}", status=200)
198
207
 
199
- assert dbsession.query(LayerWMTS).get(layer_id) is None
200
- assert dbsession.query(Layer).get(layer_id) is None
201
- assert dbsession.query(TreeItem).get(layer_id) is None
208
+ assert dbsession.query(LayerWMTS).get(layer.id) is None
209
+ assert dbsession.query(Layer).get(layer.id) is None
210
+ assert dbsession.query(TreeItem).get(layer.id) is None
211
+
212
+ log = dbsession.query(Log).one()
213
+ assert log.date != None
214
+ assert log.action == LogAction.DELETE
215
+ assert log.element_type == "layer_wmts"
216
+ assert log.element_id == layer.id
217
+ assert log.element_name == layer.name
218
+ assert log.username == "test_user"
202
219
 
203
220
  def test_unicity_validator(self, layer_wmts_test_data, test_app):
204
221
  layer = layer_wmts_test_data["layers"][2]
@@ -248,8 +265,16 @@ class TestLayerWMTS(AbstractViewsTests):
248
265
  )
249
266
 
250
267
  def test_convert_without_wms_defaults(self, test_app, layer_wmts_test_data, dbsession):
251
- from c2cgeoportal_commons.models.main import LayerWMS
268
+ from c2cgeoportal_commons.models.main import LayerWMS, Log, LogAction
252
269
 
253
270
  dbsession.delete(LayerWMS.get_default(dbsession))
254
271
  layer = layer_wmts_test_data["layers"][3]
255
272
  test_app.post(f"/admin/layers_wmts/{layer.id}/convert_to_wms", status=200)
273
+
274
+ log = dbsession.query(Log).one()
275
+ assert log.date != None
276
+ assert log.action == LogAction.CONVERT_TO_WMS
277
+ assert log.element_type == "layer_wmts"
278
+ assert log.element_id == layer.id
279
+ assert log.element_name == layer.name
280
+ assert log.username == "test_user"
tests/test_layertree.py CHANGED
@@ -103,7 +103,6 @@ def layertree_test_data(dbsession, transact):
103
103
  )
104
104
  @pytest.mark.usefixtures("layertree_test_data", "test_app")
105
105
  class TestLayerTreeView(AbstractViewsTests):
106
-
107
106
  _prefix = "/admin/layertree"
108
107
 
109
108
  def test_index(self, test_app):
tests/test_left_menu.py CHANGED
@@ -24,7 +24,6 @@ def left_menu_test_data(dbsession, transact):
24
24
 
25
25
  @pytest.mark.usefixtures("test_app")
26
26
  class TestLeftMenu(AbstractViewsTests):
27
-
28
27
  _prefix = "/admin/roles"
29
28
 
30
29
  def test_index(self, test_app):
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2022, Camptocamp SA
1
+ # Copyright (c) 2022-2023, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
tests/test_logs.py ADDED
@@ -0,0 +1,103 @@
1
+ # pylint: disable=no-self-use,unsubscriptable-object
2
+
3
+ import datetime
4
+
5
+ import pytest
6
+ import pytz
7
+ from pyramid.testing import DummyRequest
8
+
9
+ from . import AbstractViewsTests
10
+
11
+
12
+ @pytest.fixture(scope="function")
13
+ @pytest.mark.usefixtures("dbsession", "transact")
14
+ def logs_test_data(dbsession, transact):
15
+ del transact
16
+
17
+ from c2cgeoportal_commons.models.main import AbstractLog
18
+ from c2cgeoportal_commons.models.main import Log as MainLog
19
+ from c2cgeoportal_commons.models.main import LogAction
20
+ from c2cgeoportal_commons.models.static import Log as StaticLog
21
+
22
+ logs = []
23
+ for i in range(0, 5):
24
+ log = MainLog(
25
+ date=datetime.datetime.now(pytz.utc),
26
+ action=[LogAction.INSERT, LogAction.UPDATE, LogAction.DELETE][i % 3],
27
+ element_type="role",
28
+ element_id=i,
29
+ element_name=f"role_{i}",
30
+ element_url_table="roles",
31
+ username="testuser",
32
+ )
33
+ dbsession.add(log)
34
+ logs.append(log)
35
+
36
+ log = StaticLog(
37
+ date=datetime.datetime.now(pytz.utc),
38
+ action=[LogAction.INSERT, LogAction.UPDATE, LogAction.DELETE][i % 3],
39
+ element_type="user",
40
+ element_id=i,
41
+ element_name=f"user_{i}",
42
+ element_url_table="users",
43
+ username="testuser",
44
+ )
45
+ dbsession.add(log)
46
+ logs.append(log)
47
+
48
+ dbsession.flush()
49
+
50
+ yield {
51
+ "logs": logs,
52
+ }
53
+
54
+
55
+ @pytest.mark.usefixtures("logs_test_data", "test_app")
56
+ class TestLog(AbstractViewsTests):
57
+ _prefix = "/admin/logs"
58
+
59
+ def test_index_rendering(self, test_app):
60
+ resp = self.get(test_app)
61
+
62
+ self.check_left_menu(resp, "Logs")
63
+
64
+ expected = [
65
+ ("actions", "", "false"),
66
+ ("id", "id", "true"),
67
+ ("date", "Date"),
68
+ ("username", "Username"),
69
+ ("action", "Action"),
70
+ ("element_type", "Element type"),
71
+ ("element_id", "Element identifier"),
72
+ ("element_name", "Element name"),
73
+ ]
74
+ self.check_grid_headers(resp, expected, new=False)
75
+
76
+ def test_grid_default_sort_on_date_desc(self, test_app, logs_test_data):
77
+ json = self.check_search(test_app)
78
+ expected_ids = [
79
+ log.id
80
+ for log in sorted(
81
+ logs_test_data["logs"],
82
+ key=lambda log: log.date,
83
+ reverse=True,
84
+ )
85
+ ]
86
+ result_ids = [int(row["_id_"]) for row in json["rows"]]
87
+ assert result_ids == expected_ids
88
+
89
+ def test_grid_sort_on_element_type(self, test_app, logs_test_data):
90
+ json = self.check_search(test_app, sort="element_type")
91
+ expected_ids = [
92
+ log.id
93
+ for log in sorted(
94
+ logs_test_data["logs"],
95
+ key=lambda log: (log.element_type, -log.date.timestamp()),
96
+ )
97
+ ]
98
+ result_ids = [int(row["_id_"]) for row in json["rows"]]
99
+ assert result_ids == expected_ids
100
+
101
+ def test_grid_search(self, test_app):
102
+ self.check_search(test_app, "role", total=5)
103
+ self.check_search(test_app, "user_2", total=1)
tests/test_metadatas.py CHANGED
@@ -59,7 +59,6 @@ def metadatas_test_data(dbsession, transact):
59
59
 
60
60
  @pytest.mark.usefixtures("metadatas_test_data", "test_app")
61
61
  class TestMetadatasView(AbstractViewsTests):
62
-
63
62
  _prefix = "/admin/"
64
63
 
65
64
  def __metadata_ui_types(self):
@@ -35,7 +35,6 @@ def oauth2_clients_test_data(dbsession, transact):
35
35
 
36
36
  @pytest.mark.usefixtures("oauth2_clients_test_data", "test_app")
37
37
  class TestOAuth2Client(TestTreeGroup):
38
-
39
38
  _prefix = "/admin/oauth2_clients"
40
39
 
41
40
  def test_index_rendering(self, test_app):
@@ -59,7 +58,8 @@ class TestOAuth2Client(TestTreeGroup):
59
58
  self.check_search(test_app, client.client_id, total=1)
60
59
 
61
60
  def test_submit_new(self, dbsession, test_app, oauth2_clients_test_data):
62
- from c2cgeoportal_commons.models.static import OAuth2Client
61
+ from c2cgeoportal_commons.models.main import LogAction
62
+ from c2cgeoportal_commons.models.static import Log, OAuth2Client
63
63
 
64
64
  resp = test_app.post(
65
65
  "/admin/oauth2_clients/new",
@@ -84,7 +84,18 @@ class TestOAuth2Client(TestTreeGroup):
84
84
  assert oauth2_client.secret == "12345"
85
85
  assert oauth2_client.redirect_uri == "http://127.0.0.1:7070/bis"
86
86
 
87
+ log = dbsession.query(Log).one()
88
+ assert log.date != None
89
+ assert log.action == LogAction.INSERT
90
+ assert log.element_type == "oauth2_client"
91
+ assert log.element_id == oauth2_client.id
92
+ assert log.element_name == oauth2_client.client_id
93
+ assert log.username == "test_user"
94
+
87
95
  def test_edit_then_save(self, dbsession, test_app, oauth2_clients_test_data):
96
+ from c2cgeoportal_commons.models.main import LogAction
97
+ from c2cgeoportal_commons.models.static import Log
98
+
88
99
  oauth2_client = oauth2_clients_test_data["oauth2_clients"][10]
89
100
 
90
101
  dbsession.expire(oauth2_client)
@@ -112,6 +123,14 @@ class TestOAuth2Client(TestTreeGroup):
112
123
  assert "New secret" == oauth2_client.secret
113
124
  assert "New redirect URI" == oauth2_client.redirect_uri
114
125
 
126
+ log = dbsession.query(Log).one()
127
+ assert log.date != None
128
+ assert log.action == LogAction.UPDATE
129
+ assert log.element_type == "oauth2_client"
130
+ assert log.element_id == oauth2_client.id
131
+ assert log.element_name == oauth2_client.client_id
132
+ assert log.username == "test_user"
133
+
115
134
  def test_duplicate(self, oauth2_clients_test_data, test_app, dbsession):
116
135
  from c2cgeoportal_commons.models.static import OAuth2Client
117
136
 
@@ -134,11 +153,20 @@ class TestOAuth2Client(TestTreeGroup):
134
153
  assert oauth2_client_proto.id != oauth2_client.id
135
154
 
136
155
  def test_delete(self, test_app, dbsession):
137
- from c2cgeoportal_commons.models.static import OAuth2Client
138
-
139
- oauth2_client_id = dbsession.query(OAuth2Client.id).first().id
140
- test_app.delete(f"/admin/oauth2_clients/{oauth2_client_id}", status=200)
141
- assert dbsession.query(OAuth2Client).get(oauth2_client_id) is None
156
+ from c2cgeoportal_commons.models.main import LogAction
157
+ from c2cgeoportal_commons.models.static import Log, OAuth2Client
158
+
159
+ oauth2_client = dbsession.query(OAuth2Client).first()
160
+ test_app.delete(f"/admin/oauth2_clients/{oauth2_client.id}", status=200)
161
+ assert dbsession.query(OAuth2Client).get(oauth2_client.id) is None
162
+
163
+ log = dbsession.query(Log).one()
164
+ assert log.date != None
165
+ assert log.action == LogAction.DELETE
166
+ assert log.element_type == "oauth2_client"
167
+ assert log.element_id == oauth2_client.id
168
+ assert log.element_name == oauth2_client.client_id
169
+ assert log.username == "test_user"
142
170
 
143
171
  def test_unicity_validator(self, oauth2_clients_test_data, test_app):
144
172
  oauth2_client_proto = oauth2_clients_test_data["oauth2_clients"][7]