Skip to content

Commit

Permalink
feat(projects,sync): prevent update tasks or views when sync is enabled
Browse files Browse the repository at this point in the history
Signed-off-by: David Wallace <[email protected]>
  • Loading branch information
MyPyDavid committed Feb 14, 2025
1 parent e7f7bd0 commit 49c073c
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 51 deletions.
52 changes: 16 additions & 36 deletions rdmo/projects/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,21 @@ class Meta:
'catalog': forms.RadioSelect()
}

def save(self, commit=True, *args, **kwargs):
if 'cancel' in self.data:
return self.instance

def save(self, *args, **kwargs):
# if the catalog is the same, do nothing
if self.instance.catalog.id == self.cleaned_data.get('catalog'):
return self.instance

return super().save(commit=commit)
return super().save(*args, **kwargs)


class ProjectUpdateTasksForm(forms.ModelForm):

use_required_attribute = False

def __init__(self, *args, **kwargs):
if settings.PROJECT_TASKS_SYNC:
raise ValidationError(_("Editing tasks is disabled."))

tasks = kwargs.pop('tasks')
super().__init__(*args, **kwargs)
self.fields['tasks'].queryset = tasks
Expand All @@ -190,28 +189,20 @@ class Meta:
'tasks': forms.CheckboxSelectMultiple()
}

def save(self, commit=True, *args, **kwargs):
if 'cancel' in self.data:
return self.instance

# If the tasks are the same, do nothing
current_tasks = set(self.instance.tasks.values_list('id', flat=True))
new_tasks = set(self.cleaned_data.get('tasks').values_list('id', flat=True)) if self.cleaned_data.get(
'tasks') else set()

if current_tasks == new_tasks:
return self.instance

# Save the updated tasks
self.instance.tasks.set(self.cleaned_data.get('tasks'))
return super().save(commit=commit)
def save(self, *args, **kwargs):
if settings.PROJECT_TASKS_SYNC:
raise ValidationError(_("Editing tasks is disabled."))
super().save(*args, **kwargs)


class ProjectUpdateViewsForm(forms.ModelForm):

use_required_attribute = False

def __init__(self, *args, **kwargs):
if settings.PROJECT_VIEWS_SYNC:
raise ValidationError(_("Editing views is disabled."))

views = kwargs.pop('views')
super().__init__(*args, **kwargs)
self.fields['views'].queryset = views
Expand All @@ -226,22 +217,11 @@ class Meta:
'views': forms.CheckboxSelectMultiple()
}

def save(self, commit=True, *args, **kwargs):
if 'cancel' in self.data:
return self.instance

# If the views are the same, do nothing
current_views = set(self.instance.views.values_list('id', flat=True))
new_views = ( set(self.cleaned_data.get('views').values_list('id', flat=True))
if self.cleaned_data.get('views') else set()
)

if current_views == new_views:
return self.instance
def save(self, *args, **kwargs):
if settings.PROJECT_VIEWS_SYNC:
raise ValidationError(_("Editing views is disabled."))
super().save(*args, **kwargs)

# Save the updated views
self.instance.views.set(self.cleaned_data.get('views'))
return super().save(commit=commit)

class ProjectUpdateParentForm(forms.ModelForm):

Expand Down
2 changes: 1 addition & 1 deletion rdmo/projects/serializers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class Meta:
def validate_views(self, value):
"""Block updates to views if syncing is enabled."""
if settings.PROJECT_VIEWS_SYNC and value:
raise ValidationError(_('Updating views is not allowed.'))
raise ValidationError(_('Editing views is disabled.'))
return value


Expand Down
62 changes: 58 additions & 4 deletions rdmo/projects/tests/test_view_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,8 @@ def test_project_update_catalog_post(db, client, username, password, project_id)

@pytest.mark.parametrize('username,password', users)
@pytest.mark.parametrize('project_id', projects)
def test_project_update_tasks_get(db, client, username, password, project_id):
def test_project_update_tasks_get(db, client, settings, username, password, project_id):
settings.PROJECT_TASKS_SYNC = False
client.login(username=username, password=password)

url = reverse('project_update_tasks', args=[project_id])
Expand All @@ -466,9 +467,22 @@ def test_project_update_tasks_get(db, client, username, password, project_id):
assert response.status_code == 302


def test_project_update_tasks_get_not_allowed(db, client, settings):
assert settings.PROJECT_TASKS_SYNC
client.login(username='owner', password='owner')

url = reverse('project_update_tasks', args=[project_id])
data = {
'tasks': [1]
}
response = client.get(url, data)

assert response.status_code == 404

@pytest.mark.parametrize('username,password', users)
@pytest.mark.parametrize('project_id', projects)
def test_project_update_tasks_post(db, client, username, password, project_id):
def test_project_update_tasks_post(db, client, settings, username, password, project_id):
settings.PROJECT_TASKS_SYNC = False
client.login(username=username, password=password)
project = Project.objects.get(pk=project_id)

Expand All @@ -490,9 +504,23 @@ def test_project_update_tasks_post(db, client, username, password, project_id):
assert list(Project.objects.get(pk=project_id).tasks.values('id')) == list(project.tasks.values('id'))


def test_project_update_tasks_post_not_allowed(db, client, settings):
assert settings.PROJECT_TASKS_SYNC
client.login(username='owner', password='owner')

url = reverse('project_update_tasks', args=[project_id])
data = {
'tasks': [1]
}
response = client.post(url, data)

assert response.status_code == 404


@pytest.mark.parametrize('username,password', users)
@pytest.mark.parametrize('project_id', projects)
def test_project_update_views_get(db, client, username, password, project_id):
def test_project_update_views_get(db, client, settings, username, password, project_id):
settings.PROJECT_VIEWS_SYNC = False
client.login(username=username, password=password)

url = reverse('project_update_views', args=[project_id])
Expand All @@ -507,9 +535,23 @@ def test_project_update_views_get(db, client, username, password, project_id):
assert response.status_code == 302


def test_project_update_views_get_not_allowed(db, client, settings):
assert settings.PROJECT_VIEWS_SYNC
client.login(username='owner', password='owner')

url = reverse('project_update_views', args=[project_id])
data = {
'tasks': [1]
}
response = client.get(url, data)

assert response.status_code == 404


@pytest.mark.parametrize('username,password', users)
@pytest.mark.parametrize('project_id', projects)
def test_project_update_views_post(db, client, username, password, project_id):
def test_project_update_views_post(db, client, settings, username, password, project_id):
settings.PROJECT_VIEWS_SYNC = False
client.login(username=username, password=password)
project = Project.objects.get(pk=project_id)

Expand All @@ -531,6 +573,18 @@ def test_project_update_views_post(db, client, username, password, project_id):
assert list(Project.objects.get(pk=project_id).views.values('id')) == list(project.views.values('id'))


def test_project_update_views_post_not_allowed(db, client, settings):
assert settings.PROJECT_VIEWS_SYNC
client.login(username='owner', password='owner')

url = reverse('project_update_views', args=[project_id])
data = {
'tasks': [1]
}
response = client.post(url, data)

assert response.status_code == 404

@pytest.mark.parametrize('username,password', users)
@pytest.mark.parametrize('project_id', projects)
def test_project_update_parent_get(db, client, username, password, project_id):
Expand Down
4 changes: 2 additions & 2 deletions rdmo/projects/tests/test_viewset_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,16 +431,16 @@ def test_update_parent(db, client, username, password, project_id):

def test_update_project_views_not_allowed(db, client, settings):
assert settings.PROJECT_VIEWS_SYNC
client.login(username='owner', password='owner')

client.login(username='owner', password='owner')
url = reverse(urlnames['detail'], args=[project_id])
data = {
'views': [1]
}
response = client.put(url, data, content_type='application/json')

assert response.status_code == 400
assert 'Updating views is not allowed' in ' '.join(response.json()['views'])
assert 'Editing views is disabled' in ' '.join(response.json()['views'])


@pytest.mark.parametrize('username,password', users)
Expand Down
28 changes: 20 additions & 8 deletions rdmo/projects/views/project_update.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging

from django.conf import settings
from django.http import Http404
from django.views.generic import UpdateView

from rdmo.core.views import ObjectPermissionMixin, RedirectViewMixin
Expand Down Expand Up @@ -81,37 +83,47 @@ class ProjectUpdateTasksView(ObjectPermissionMixin, RedirectViewMixin, UpdateVie
form_class = ProjectUpdateTasksForm
permission_required = 'projects.change_project_object'

def dispatch(self, request, *args, **kwargs):
if settings.PROJECT_TASKS_SYNC:
raise Http404
return super().dispatch(request, *args, **kwargs)

def get_form_kwargs(self):
tasks = Task.objects.filter_current_site() \
.filter_catalog(self.object.catalog) \
.filter_group(self.request.user) \
.filter_availability(self.request.user)
tasks = Task.objects.filter_available_tasks_for_project(self.object)

form_kwargs = super().get_form_kwargs()
form_kwargs.update({
'tasks': tasks
})
return form_kwargs

def get_success_url(self):
return self.get_object().get_absolute_url()


class ProjectUpdateViewsView(ObjectPermissionMixin, RedirectViewMixin, UpdateView):
model = Project
queryset = Project.objects.all()
form_class = ProjectUpdateViewsForm
permission_required = 'projects.change_project_object'

def dispatch(self, request, *args, **kwargs):
if settings.PROJECT_VIEWS_SYNC:
raise Http404
return super().dispatch(request, *args, **kwargs)

def get_form_kwargs(self):
views = View.objects.filter_current_site() \
.filter_catalog(self.object.catalog) \
.filter_group(self.request.user) \
.filter_availability(self.request.user)
views = View.objects.filter_available_views_for_project(self.object)

form_kwargs = super().get_form_kwargs()
form_kwargs.update({
'views': views
})
return form_kwargs

def get_success_url(self):
return self.get_object().get_absolute_url()


class ProjectUpdateParentView(ObjectPermissionMixin, RedirectViewMixin, UpdateView):
model = Project
Expand Down

0 comments on commit 49c073c

Please sign in to comment.