Skip to content

Commit

Permalink
Save user groups list in custom field (#960)
Browse files Browse the repository at this point in the history
* Add add_user_group_field and edit_user_group_field.

* Add fields to the form

* Typo field type.

* Add user group fields management in the form.

* Add logging fields management on editing.

* Extend cleaning form logging field.

* Update detail project page

* Fix getting form data

* Update tests.

---------

Co-authored-by: wlorenzetti <[email protected]>
  • Loading branch information
wlorenzetti and wlorenzetti authored Oct 25, 2024
1 parent d990a64 commit 315ed84
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 20 deletions.
67 changes: 62 additions & 5 deletions g3w-admin/editing/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ class ActiveEditingLayerForm(ActiveEditingMixin, G3WRequestFormMixin, G3WProject
#' more than 200 characters long.<br>'
'Value stored into the field it will be so structured: '
'<i>[username]</i>'))
add_user_group_field = forms.ChoiceField(choices=[], label=_('User Groups adding data field'), required=False,
help_text=_('Optional: select layer field to store '
'user groups name that entered the data. '
'Showed only string field. <br>'
# 'more than 200 characters long.<br>'
'Value stored into the field it will be so structured: '
'<i>[user group name 1, user group name 2, ...]</i>'))
edit_user_group_field = forms.ChoiceField(choices=[], label=_('User Groups editing data field'), required=False,
help_text=_('Optional: select layer field to store '
'user groups name that updated the data. '
'Showed only string field. <br>'
# ' more than 200 characters long.<br>'
'Value stored into the field it will be so structured: '
'<i>[user group name 1, user group name 2, ...]</i>'))

def __init__(self, *args, **kwargs):

Expand Down Expand Up @@ -117,6 +131,8 @@ def __init__(self, *args, **kwargs):
layout_args += [
Field('add_user_field', css_class='select2', style="width:100%;"),
Field('edit_user_field', css_class='select2', style="width:100%;"),
Field('add_user_group_field', css_class='select2', style="width:100%;"),
Field('edit_user_group_field', css_class='select2', style="width:100%;"),
HTML(_('Select viewers with \'view permission\' on project that can edit layer:')),
Field('viewer_users', css_class='select2', style="width:100%;"),
Div(css_class='users_atomic_capabilities'),
Expand All @@ -126,19 +142,56 @@ def __init__(self, *args, **kwargs):

self.helper.layout = Layout(*layout_args)

def clean_add_user_field(self):

# Create general error message
self.logging_fields_except = ValidationError(_("'User adding data field' and 'User editing data field' and "
"'User group adding data field' and 'User group editing data field' "
"must be unique."))

if self.cleaned_data['add_user_field'] and self.cleaned_data['add_user_field'] in (
self.data.get('edit_user_field', None),
self.data.get('add_user_group_field', None),
self.data.get('edit_user_group_field', None)):
raise self.logging_fields_except

return self.cleaned_data['add_user_field']

def clean_edit_user_field(self):

if self.cleaned_data['edit_user_field'] and self.cleaned_data['add_user_field']:
if self.cleaned_data['edit_user_field'] == self.cleaned_data['add_user_field']:
raise ValidationError(_("'User adding data field' and 'User editing data field' "
"cannot assume the same value."))
if self.cleaned_data['edit_user_field'] and self.cleaned_data['edit_user_field'] in (
self.data.get('add_user_field', None),
self.data.get('add_user_group_field', None),
self.data.get('edit_user_group_field', None)):
raise self.logging_fields_except

return self.cleaned_data['edit_user_field']

def clean_add_user_group_field(self):

if self.cleaned_data['add_user_group_field'] and self.cleaned_data['add_user_group_field'] in (
self.data.get('edit_user_field', None),
self.data.get('add_user_field', None),
self.data.get('edit_user_group_field', None)):
raise self.logging_fields_except

return self.cleaned_data['add_user_group_field']

def clean_edit_user_group_field(self):

if self.cleaned_data['edit_user_group_field'] and self.cleaned_data['edit_user_group_field'] in (
self.data.get('edit_user_field', None),
self.data.get('add_user_field', None),
self.data.get('add_user_group_field', None)):
raise self.logging_fields_except

return self.cleaned_data['edit_user_group_field']


def _set_add_edit_user_field_choices(self):
"""
Set choices for add_user_field select and edit_user_field select
Set choices for add_user_field select and edit_user_field select and for
add_user_group_field, edit_user_group_field.
"""

touse = []
Expand All @@ -152,6 +205,9 @@ def _set_add_edit_user_field_choices(self):
self.fields['edit_user_field'].choices = \
self.fields['add_user_field'].choices = [(None, '--------')] + [(f, f) for f in touse]

self.fields['edit_user_group_field'].choices = \
self.fields['add_user_group_field'].choices = [(None, '--------')] + [(f, f) for f in touse]


class ActiveEditingMultiLayerForm(ActiveEditingMixin, G3WRequestFormMixin, G3WProjectFormMixin, forms.Form):
"""
Expand All @@ -174,6 +230,7 @@ class ActiveEditingMultiLayerForm(ActiveEditingMixin, G3WRequestFormMixin, G3WPr
label=_('User viewer groups')
)


def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)
Expand Down
23 changes: 23 additions & 0 deletions g3w-admin/editing/migrations/0014_auto_20241022_0657.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.25 on 2024-10-22 06:57

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('editing', '0013_g3weditinglayer_visible'),
]

operations = [
migrations.AddField(
model_name='g3weditinglayer',
name='add_user_group_field',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='g3weditinglayer',
name='edit_user_group_field',
field=models.TextField(blank=True, null=True),
),
]
23 changes: 23 additions & 0 deletions g3w-admin/editing/migrations/0015_auto_20241022_0707.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.25 on 2024-10-22 07:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('editing', '0014_auto_20241022_0657'),
]

operations = [
migrations.AlterField(
model_name='g3weditinglayer',
name='add_user_group_field',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name='g3weditinglayer',
name='edit_user_group_field',
field=models.CharField(blank=True, max_length=255, null=True),
),
]
2 changes: 2 additions & 0 deletions g3w-admin/editing/models/editing.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class G3WEditingLayer(models.Model):
add_user_field = models.CharField(null=True, blank=True, max_length=255)
edit_user_field = models.CharField(null=True, blank=True, max_length=255)
visible = models.BooleanField(default=True, null=True, blank=True, help_text="Show layer in layers list to edit")
add_user_group_field = models.CharField(null=True, blank=True, max_length=255)
edit_user_group_field = models.CharField(null=True, blank=True, max_length=255)

class Meta:
app_label = 'editing'
Expand Down
51 changes: 40 additions & 11 deletions g3w-admin/editing/receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
)
from qdjango.vector import LayerVectorView, MODE_CONFIG
from qdjango.models import GeoConstraintRule
from usersmanage.utils import get_user_groups
from .models import (
G3WEditingFeatureLock,
G3WEditingLayer,
Expand Down Expand Up @@ -315,24 +316,52 @@ def fill_logging_fields(sender, **kwargs):

mode = kwargs["mode"]
user = kwargs["user"]
user_groups = ", ".join([g.name for g in get_user_groups(user)])
try:
el = G3WEditingLayer.objects.get(
app_name="qdjango", layer_id=kwargs["layer_metadata"].layer_id
)
if el.add_user_field and mode == EDITING_POST_DATA_ADDED:
kwargs["data"]["feature"]["properties"][
el.add_user_field
] = f"{user.username}"
if mode == EDITING_POST_DATA_ADDED:

# Remove edit_suer_field property if is active
# Set the user and user group
# ---------------------------
if el.add_user_field:
kwargs["data"]["feature"]["properties"][
el.add_user_field
] = f"{user.username}"

# Remove edit_user_field property if is active
if el.edit_user_field:
del kwargs["data"]["feature"]["properties"][el.edit_user_field]

if el.add_user_group_field:
kwargs["data"]["feature"]["properties"][
el.add_user_group_field
] = f"{user_groups}"

# Remove edit_user_field property if is active
if el.edit_user_group_field:
del kwargs["data"]["feature"]["properties"][el.edit_user_group_field]


if mode == EDITING_POST_DATA_UPDATED:

# Set the user and user group
# ---------------------------
if el.edit_user_field:
del kwargs["data"]["feature"]["properties"][el.edit_user_field]
if el.edit_user_field and mode == EDITING_POST_DATA_UPDATED:
kwargs['data']['feature']['properties'][el.edit_user_field] = f"{user.username}"
kwargs['data']['feature']['properties'][el.edit_user_field] = f"{user.username}"

# Remove add_user_field property if is active
if el.add_user_field:
del(kwargs['data']['feature']['properties'][el.add_user_field])

if el.edit_user_group_field:
kwargs['data']['feature']['properties'][el.edit_user_group_field] = f"{user_groups}"

# Remove add_user_field property if is active
if el.add_user_group_field:
del (kwargs['data']['feature']['properties'][el.add_user_group_field])

# Remove add_user_field property if is active
if el.add_user_field:
del(kwargs['data']['feature']['properties'][el.add_user_field])
except Exception as e:
logger.error(f"[EDITING] - FILL LOGGING FIELDS: {e}")

Expand Down
Binary file modified g3w-admin/editing/tests/data/logging_test.db
Binary file not shown.
110 changes: 109 additions & 1 deletion g3w-admin/editing/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ def test_editing_fields_loggin_commit_mode_api(self):
editing_layer = self.logging_project.instance.layer_set.all()[0]

# Activate logging field
G3WEditingLayer.objects.create(app_name='qdjango', layer_id=editing_layer.pk,
el = G3WEditingLayer.objects.create(app_name='qdjango', layer_id=editing_layer.pk,
add_user_field='insert_log', edit_user_field='update_log')

# ADD
Expand Down Expand Up @@ -1091,6 +1091,114 @@ def test_editing_fields_loggin_commit_mode_api(self):
self.assertTrue(f'admin01' in qgs_feature.attribute('insert_log'))
self.assertTrue(f'admin01' in qgs_feature.attribute('update_log'))

self.client.logout()

# TEST AS TEST_USER4 (VIEWER)
# -----------------------------------------------------------------
assign_perm('view_project', self.test_user4, self.logging_project.instance)
self.client.login(username=self.test_user4.username, password=self.test_user4.username)

el.add_user_field = ''
el.add_user_group_field = 'insert_log'
el.edit_user_field = ''
el.edit_user_group_field = 'update_log'

el.save()

# Set permission for user
assign_perm('add_feature', self.test_user4, editing_layer)
assign_perm('change_feature', self.test_user4, editing_layer)
assign_perm('delete_feature', self.test_user4, editing_layer)
assign_perm('change_attr_feature', self.test_user4, editing_layer)
assign_perm('change_layer', self.test_user4, editing_layer)

# INSERT
# ======
payload = {
"add": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-18219.126089871206,
-9298.036763106677
]
},
"properties": {
"name": "test data 3",
"insert_log": None,
"update_log": None
},
"id": "_new_76_1648018518851"
}
],
"update": [],
"delete": [],
"relations": {},
"lockids": []
}

response = self.client.post(commit_path, payload, format='json')
self.assertEqual(response.status_code, 200)

jresult = json.loads(response.content)
self.assertTrue(jresult['result'])

newid = jresult['response']['new'][0]['id']
newlockid = jresult['response']['new_lockids'][0]['lockid']

qgs_feature = editing_layer.qgis_layer.getFeature(int(newid))

self.assertTrue(f'Viewer user group1' in qgs_feature.attribute('insert_log'))
self.assertFalse(qgs_feature.attribute('update_log'))

# UPDATE
# ======

payload = {
"update": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-18219.126089871206,
-9298.036763106677
]
},
"properties": {
"name": "test data 3",
"insert_log": None,
"update_log": None
},
"id": newid
}
],
"add": [],
"delete": [],
"relations": {},
"lockids": [
{
"featureid": newid,
"lockid": newlockid
}
],
}

response = self.client.post(commit_path, payload, format='json')
self.assertEqual(response.status_code, 200)

jresult = json.loads(response.content)
self.assertTrue(jresult['result'])

qgs_feature = editing_layer.qgis_layer.getFeature(int(newid))

self.assertTrue(f'Viewer user group1' in qgs_feature.attribute('insert_log'))
self.assertTrue(f'Viewer user group1' in qgs_feature.attribute('update_log'))

self.client.logout()

def test_editing_provider_default_value(self):
""" Test Editing API mode: MODE_COMMIT with fields having provider default values """

Expand Down
Loading

0 comments on commit 315ed84

Please sign in to comment.