diff --git a/g3w-admin/filemanager/apps.py b/g3w-admin/filemanager/apps.py index b827105d5..ba2f07296 100644 --- a/g3w-admin/filemanager/apps.py +++ b/g3w-admin/filemanager/apps.py @@ -8,6 +8,10 @@ class FilemanagerConfig(AppConfig): name = 'filemanager' def ready(self): + + # Import signals receivers + import filemanager.receivers + from django.conf import settings import filemanager.filemanager_settings for a in dir(filemanager.filemanager_settings): diff --git a/g3w-admin/filemanager/receivers.py b/g3w-admin/filemanager/receivers.py new file mode 100644 index 000000000..db32d4792 --- /dev/null +++ b/g3w-admin/filemanager/receivers.py @@ -0,0 +1,41 @@ +# coding=utf-8 +"""" Django signals receivers +.. note:: This program is free software; you can redistribute it and/or modify + it under the terms of the Mozilla Public License 2.0. + +""" + +__author__ = "lorenzetti@gis3w.it" +__date__ = "2023-08-29" +__copyright__ = "Copyright 2015 - 2023, Gis3w" +__license__ = "MPL 2.0" + +from django.conf import settings +from django.dispatch import receiver +from usersmanage.signals import after_save_user_form +from usersmanage.configs import G3W_EDITOR1 +from usersmanage.utils import userHasGroups + +from os import makedirs, path +import logging + +logger = logging.getLogger('filemanager') + + + +@receiver(after_save_user_form) +def make_project_data_subdir(sender, user, **kwargs): + """ + Given a user instance create if not exists a folder into `settings.DATASOURCE_PATH` + """ + + # Check if user is an Editor level 1 + if not userHasGroups(user, [G3W_EDITOR1]): + return + + makedirs(path.join(settings.DATASOURCE_PATH, user.username), exist_ok=True) + + + + + diff --git a/g3w-admin/filemanager/tests/test_api.py b/g3w-admin/filemanager/tests/test_api.py index a1d9f8727..36e076b3e 100644 --- a/g3w-admin/filemanager/tests/test_api.py +++ b/g3w-admin/filemanager/tests/test_api.py @@ -38,6 +38,12 @@ def test_files_folders_get(self): # as editor1 client.login(username=self.test_editor1.username, password=self.test_editor1.username) res = client.get(url) + self.assertEqual(res.status_code, 200) + client.logout() + + # as viewer1 + client.login(username=self.test_viewer1.username, password=self.test_viewer1.username) + res = client.get(url) self.assertEqual(res.status_code, 403) client.logout() diff --git a/g3w-admin/filemanager/tests/test_views.py b/g3w-admin/filemanager/tests/test_views.py index a9900caa7..f9c3c50dd 100644 --- a/g3w-admin/filemanager/tests/test_views.py +++ b/g3w-admin/filemanager/tests/test_views.py @@ -25,7 +25,6 @@ def test_main_view(self): url = reverse('filemanager-home') client = Client() - print(url) # TEST ACL # ==================================== # not login: redirect to login page. @@ -36,6 +35,12 @@ def test_main_view(self): # as editor1 client.login(username=self.test_editor1.username, password=self.test_editor1.username) res = client.get(url) + self.assertEqual(res.status_code, 200) + client.logout() + + # as viewer1 + client.login(username=self.test_viewer1.username, password=self.test_viewer1.username) + res = client.get(url) self.assertEqual(res.status_code, 403) client.logout() @@ -52,7 +57,6 @@ def test_server_config(self): url = reverse('filemanager-serve-file-config', args=['filemanager.config.json']) client = Client() - print (url) # TEST ACL # ==================================== # not login: redirect to login page. @@ -63,6 +67,12 @@ def test_server_config(self): # as editor1 client.login(username=self.test_editor1.username, password=self.test_editor1.username) res = client.get(url) + self.assertEqual(res.status_code, 200) + client.logout() + + # as viewer1 + client.login(username=self.test_viewer1.username, password=self.test_viewer1.username) + res = client.get(url) self.assertEqual(res.status_code, 403) client.logout() diff --git a/g3w-admin/filemanager/views.py b/g3w-admin/filemanager/views.py index 7881d2188..f2f7abf5d 100644 --- a/g3w-admin/filemanager/views.py +++ b/g3w-admin/filemanager/views.py @@ -4,6 +4,7 @@ from django.http.response import JsonResponse, HttpResponse from django.utils.decorators import method_decorator from usersmanage.decorators import user_passes_test_or_403 +from usersmanage.utils import userHasGroups, G3W_EDITOR1 from .filemanager import FileManager import json import os @@ -13,7 +14,7 @@ class FilemanagerView(TemplateView): """Main templateview for fielmanager""" template_name = 'filemanager/filemanager.html' - @method_decorator(user_passes_test_or_403(lambda u: u.is_superuser)) + @method_decorator(user_passes_test_or_403(lambda u: u.is_superuser or userHasGroups(u, [G3W_EDITOR1]))) def dispatch(self, *args, **kwargs): return super(FilemanagerView, self).dispatch(*args, **kwargs) @@ -30,7 +31,7 @@ class FilemanagerServeConfigView(View): """ Filemanager main config view Return main RichFileManager json config settings. """ - @method_decorator(user_passes_test_or_403(lambda u: u.is_superuser)) + @method_decorator(user_passes_test_or_403(lambda u: u.is_superuser or userHasGroups(u, [G3W_EDITOR1]))) def dispatch(self, *args, **kwargs): return super(FilemanagerServeConfigView, self).dispatch(*args, **kwargs) @@ -59,7 +60,7 @@ def get(self, request, *args, **kwargs): @csrf_exempt -@user_passes_test_or_403(lambda u: u.is_superuser) +@user_passes_test_or_403(lambda u: u.is_superuser or userHasGroups(u, [G3W_EDITOR1])) def files_view(request): """File Manager API endpoint""" @@ -74,6 +75,10 @@ def files_view(request): else: root_folder = settings.DATASOURCE_PATH + # Append user.username to the root_folder if user is an Editor level 1 + if userHasGroups(request.user, [G3W_EDITOR1]): + root_folder = os.path.join(root_folder, request.user.username) + fileManager = FileManager(request, root_folder=root_folder) mode = None diff --git a/g3w-admin/qdjango/tests/data/value_relation_qgis328.qgs b/g3w-admin/qdjango/tests/data/value_relation_qgis328.qgs index f9fa19706..bc195ecca 100644 --- a/g3w-admin/qdjango/tests/data/value_relation_qgis328.qgs +++ b/g3w-admin/qdjango/tests/data/value_relation_qgis328.qgs @@ -1,5 +1,5 @@ - + @@ -21,24 +21,23 @@ - + - + poi_2c470d17_a234_464c_83f8_416bcdedda17 - poi_type_2e216f86_c925_4039_a760_52dc4e2b87b9 - + - + @@ -70,156 +69,131 @@ - - - - - - - + - + - - degrees - - 0 - 0 - 0 - 0 - - 0 - - - GEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],CS[ellipsoidal,2],AXIS["geodetic latitude (Lat)",north,ORDER[1],ANGLEUNIT["degree",0.0174532925199433]],AXIS["geodetic longitude (Lon)",east,ORDER[2],ANGLEUNIT["degree",0.0174532925199433]],USAGE[SCOPE["Horizontal component of 3D system."],AREA["World."],BBOX[-90,-180,90,180]],ID["EPSG",4326]] - +proj=longlat +datum=WGS84 +no_defs - 3452 - 4326 - EPSG:4326 - WGS 84 - longlat - EPSG:7030 - true - - - 0 - - - + Annotazioni_8a9f9d8b_d1e4_4305_85b4_c2110f051d89 @@ -270,18 +244,18 @@ - + - 29099307.18904989957809448 - 6524716.7632708502933383 - 55421878.81687570363283157 - 23153423.48566510155797005 + 29099307.1890498623251915 + 6524716.76327085494995117 + 55421878.81687566637992859 + 23153423.48566505685448647 - -98.59647594787405467 - 50.45080665626462491 - 137.86320815819431118 - 86.96255517361525733 + -98.59647594787440994 + 50.45080665626466754 + 137.86320815819399854 + 86.96255517361522891 poi_2c470d17_a234_464c_83f8_416bcdedda17 dbname='./geodata/value_relation_filter.sqlite' table="poi" (geometry) @@ -335,7 +309,7 @@ - + @@ -360,181 +334,181 @@ 1 0 - + - + - + - + - + - + - + - + - + - + - + @@ -545,64 +519,65 @@ - 0 0 1 - - + + + - + - + @@ -610,20 +585,20 @@ - + - + - + @@ -651,59 +626,59 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - @@ -757,7 +732,7 @@ def my_form_open(dialog, layer, feature): "cod" - + poi_type_2e216f86_c925_4039_a760_52dc4e2b87b9 dbname='./geodata/value_relation_filter.sqlite' table="poi_type" @@ -818,138 +793,138 @@ def my_form_open(dialog, layer, feature): 1 0 - + - + - + - + - + - + - + - + @@ -958,18 +933,18 @@ def my_form_open(dialog, layer, feature): - + - + @@ -995,35 +970,35 @@ def my_form_open(dialog, layer, feature): - - - + + + - - - + + + - - - + + + - - - + + + - + - + - @@ -1049,7 +1024,6 @@ def my_form_open(dialog, layer, feature): - @@ -1169,9 +1143,9 @@ def my_form_open(dialog, layer, feature): @@ -1200,9 +1174,9 @@ def my_form_open(dialog, layer, feature): - + - + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs @@ -1216,41 +1190,41 @@ def my_form_open(dialog, layer, feature): - + - + - + diff --git a/g3w-admin/templates/include/navbar_right_menu.html b/g3w-admin/templates/include/navbar_right_menu.html index 5b28407e8..2af496025 100644 --- a/g3w-admin/templates/include/navbar_right_menu.html +++ b/g3w-admin/templates/include/navbar_right_menu.html @@ -1,5 +1,6 @@ {% load i18n %} {% load static %} +{% load auth_extras %} \ No newline at end of file diff --git a/g3w-admin/templates/include/sidebar_right.html b/g3w-admin/templates/include/sidebar_right.html index a1cdfba72..ec25f4177 100644 --- a/g3w-admin/templates/include/sidebar_right.html +++ b/g3w-admin/templates/include/sidebar_right.html @@ -8,6 +8,7 @@

{% trans 'Configurations' %}

- {% if user.is_staff %}
  • diff --git a/g3w-admin/usersmanage/tests/test_forms.py b/g3w-admin/usersmanage/tests/test_forms.py index 6840183e8..1042ee7ae 100644 --- a/g3w-admin/usersmanage/tests/test_forms.py +++ b/g3w-admin/usersmanage/tests/test_forms.py @@ -10,8 +10,12 @@ __date__ = '2020-04-14' __copyright__ = 'Copyright 2015 - 2020, Gis3w' +import os.path + +from django.conf import settings from django.test.client import RequestFactory from django.core.exceptions import ObjectDoesNotExist + from usersmanage.forms import G3WUserForm, User, USER_BACKEND_DEFAULT, G3WUserGroupForm, AuthGroup from usersmanage.utils import userHasGroups from .utils import setup_testing_user_relations @@ -84,6 +88,9 @@ def test_user_form_crud(self): self.assertTrue(u.is_superuser) self.assertTrue(u.is_staff) + # Check creation oh a sub directory inside settings.DATASOURCE_PATH + self.assertFalse(os.path.exists(f"{settings.DATASOURCE_PATH}/{u.username}")) + # Update user initial_data = copy.copy(form_data) form_data.update({ @@ -152,6 +159,9 @@ def test_user_form_crud(self): self.assertTrue(u.is_superuser) self.assertFalse(u.is_staff) + # Check creation oh a sub directory inside settings.DATASOURCE_PATH + self.assertFalse(os.path.exists(f"{settings.DATASOURCE_PATH}/{u.username}")) + u.delete() del (u) @@ -181,6 +191,9 @@ def test_user_form_crud(self): self.assertFalse(u.is_superuser) self.assertFalse(u.is_staff) + # Check creation oh a sub directory inside settings.DATASOURCE_PATH + self.assertTrue(os.path.exists(f"{settings.DATASOURCE_PATH}/{u.username}")) + u.delete() del (u)