diff --git a/app/api/projects.py b/app/api/projects.py index 6673ad13..c86efeb9 100644 --- a/app/api/projects.py +++ b/app/api/projects.py @@ -136,3 +136,18 @@ class ProjectViewSet(viewsets.ModelViewSet): return Response({'error': _("Invalid permissions")}, status=status.HTTP_400_BAD_REQUEST) return Response({'success': True}, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None): + project = get_and_check_project(request, pk, ('delete_project', )) + + # Owner? Delete the project + if project.owner == request.user: + return super().destroy(self, request, pk=pk) + else: + # Do not remove the project, simply remove all user's permissions to the project + # to avoid shared projects from being accidentally deleted + for p in ["add", "change", "delete", "view"]: + perm = p + "_project" + remove_perm(perm, request.user, project) + return Response(status=status.HTTP_204_NO_CONTENT) + \ No newline at end of file diff --git a/app/static/app/js/components/EditProjectDialog.jsx b/app/static/app/js/components/EditProjectDialog.jsx index 633b7afa..ce28ada5 100644 --- a/app/static/app/js/components/EditProjectDialog.jsx +++ b/app/static/app/js/components/EditProjectDialog.jsx @@ -140,7 +140,7 @@ class EditProjectDialog extends React.Component {
- { this.nameInput = domNode; }} value={this.state.name} onChange={this.handleChange('name')} /> + { this.nameInput = domNode; }} value={this.state.name} onChange={this.handleChange('name')} onKeyPress={e => this.dialog.handleEnter(e)} />
diff --git a/app/static/app/js/components/FormDialog.jsx b/app/static/app/js/components/FormDialog.jsx index c0e76eb4..f296fce2 100644 --- a/app/static/app/js/components/FormDialog.jsx +++ b/app/static/app/js/components/FormDialog.jsx @@ -102,6 +102,12 @@ class FormDialog extends React.Component { } } + handleEnter = e => { + if (e.key === 'Enter' || e.keyCode === 13){ + this.handleSave(e); + } + } + handleSave(e){ e.preventDefault(); diff --git a/app/tests/test_api.py b/app/tests/test_api.py index 9144c5f8..bdbc9d81 100644 --- a/app/tests/test_api.py +++ b/app/tests/test_api.py @@ -255,7 +255,7 @@ class TestApi(BootTestCase): # Can't delete a project for which we just have view permissions res = client.delete('/api/projects/{}/'.format(other_temp_project.id)) - self.assertTrue(res.status_code == status.HTTP_403_FORBIDDEN) + self.assertTrue(res.status_code == status.HTTP_404_NOT_FOUND) # Can delete a project for which we have delete permissions assign_perm('delete_project', user, other_temp_project) diff --git a/app/tests/test_api_projects.py b/app/tests/test_api_projects.py index ae865289..ab2993e8 100644 --- a/app/tests/test_api_projects.py +++ b/app/tests/test_api_projects.py @@ -104,4 +104,25 @@ class TestApiProjects(BootTestCase): self.assertEqual(res.status_code, status.HTTP_200_OK) perms = get_perms(user, project) - self.assertEqual(len(perms), 4) \ No newline at end of file + self.assertEqual(len(perms), 4) + + # Re-add permissions for other user + res = client.post("/api/projects/{}/edit/".format(project.id), { + 'permissions': [{'username': 'testuser2', 'permissions': ['view', 'add', 'change', 'delete']}] + }, format="json") + self.assertEqual(res.status_code, status.HTTP_200_OK) + + # Other user deletes project + res = other_client.delete("/api/projects/{}/".format(project.id)) + self.assertEqual(res.status_code, status.HTTP_204_NO_CONTENT) + project.refresh_from_db() + + # Other user can no longer see the project (permissions have been revoked) + res = other_client.get("/api/projects/{}/".format(project.id)) + self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND) + perms = get_perms(other_user, project) + self.assertEqual(len(perms), 0) + + # Project is still there + res = client.get("/api/projects/{}/".format(project.id)) + self.assertEqual(res.status_code, status.HTTP_200_OK) \ No newline at end of file