Remove concept of ownership from folders by removing the user field.
"Ownership" now is now determined by ACL of a folder, like the rest of the objects in the system.
This commit is contained in:
@@ -8,5 +8,4 @@ from .models import Folder
|
||||
@admin.register(Folder)
|
||||
class FolderAdmin(admin.ModelAdmin):
|
||||
filter_horizontal = ('documents',)
|
||||
list_display = ('label', 'user', 'datetime_created')
|
||||
list_filter = ('user',)
|
||||
list_display = ('label', 'datetime_created')
|
||||
|
||||
@@ -67,7 +67,6 @@ class FoldersApp(MayanAppConfig):
|
||||
SourceColumn(
|
||||
source=Folder, label=_('Created'), attribute='datetime_created'
|
||||
)
|
||||
SourceColumn(source=Folder, label=_('User'), attribute='user')
|
||||
SourceColumn(
|
||||
source=Folder, label=_('Documents'),
|
||||
func=lambda context: context['object'].get_document_count(
|
||||
|
||||
23
mayan/apps/folders/migrations/0005_auto_20160308_0437.py
Normal file
23
mayan/apps/folders/migrations/0005_auto_20160308_0437.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def merge_label_and_user(apps, schema_editor):
|
||||
Folder = apps.get_model('folders', 'Folder')
|
||||
|
||||
for folder in Folder.objects.all():
|
||||
folder.label = '{}-{}'.format(folder.user.username, folder.label)
|
||||
folder.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('folders', '0004_documentfolder'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(merge_label_and_user),
|
||||
]
|
||||
22
mayan/apps/folders/migrations/0006_auto_20160308_0445.py
Normal file
22
mayan/apps/folders/migrations/0006_auto_20160308_0445.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('folders', '0005_auto_20160308_0437'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='folder',
|
||||
unique_together=set([('label',)]),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='folder',
|
||||
name='user',
|
||||
),
|
||||
]
|
||||
@@ -1,6 +1,5 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
@@ -20,7 +19,6 @@ class Folder(models.Model):
|
||||
label = models.CharField(
|
||||
db_index=True, max_length=128, verbose_name=_('Label')
|
||||
)
|
||||
user = models.ForeignKey(User, verbose_name=_('User'))
|
||||
datetime_created = models.DateTimeField(
|
||||
auto_now_add=True, verbose_name=_('Datetime created')
|
||||
)
|
||||
@@ -42,7 +40,7 @@ class Folder(models.Model):
|
||||
|
||||
class Meta:
|
||||
ordering = ('label',)
|
||||
unique_together = ('label', 'user')
|
||||
unique_together = ('label', )
|
||||
verbose_name = _('Folder')
|
||||
verbose_name_plural = _('Folders')
|
||||
|
||||
|
||||
@@ -18,16 +18,14 @@ class FolderSerializer(serializers.HyperlinkedModelSerializer):
|
||||
view_name='rest_api:folder-document-list'
|
||||
)
|
||||
documents_count = serializers.SerializerMethodField()
|
||||
user = UserSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
'url': {'view_name': 'rest_api:folder-detail'},
|
||||
'user': {'view_name': 'rest_api:user-detail'}
|
||||
}
|
||||
fields = (
|
||||
'datetime_created', 'documents', 'documents_count', 'id', 'label',
|
||||
'url', 'user'
|
||||
'url'
|
||||
)
|
||||
model = Folder
|
||||
|
||||
@@ -41,7 +39,6 @@ class NewFolderSerializer(serializers.Serializer):
|
||||
def create(self, validated_data):
|
||||
try:
|
||||
data = validated_data.copy()
|
||||
data.update({'user': self.context['request'].user})
|
||||
return Folder.objects.create(**data)
|
||||
except Exception as exception:
|
||||
raise ValidationError(exception)
|
||||
|
||||
@@ -42,12 +42,9 @@ class FolderAPITestCase(APITestCase):
|
||||
|
||||
self.assertEqual(Folder.objects.count(), 1)
|
||||
self.assertEqual(folder.label, TEST_FOLDER_LABEL)
|
||||
self.assertEqual(folder.user, self.admin_user)
|
||||
|
||||
def test_folder_delete(self):
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
self.client.delete(
|
||||
reverse('rest_api:folder-detail', args=(folder.pk,))
|
||||
@@ -56,9 +53,7 @@ class FolderAPITestCase(APITestCase):
|
||||
self.assertEqual(Folder.objects.count(), 0)
|
||||
|
||||
def test_folder_edit(self):
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
self.client.put(
|
||||
reverse('rest_api:folder-detail', args=(folder.pk,)),
|
||||
@@ -71,9 +66,7 @@ class FolderAPITestCase(APITestCase):
|
||||
|
||||
@override_settings(OCR_AUTO_OCR=False)
|
||||
def test_folder_add_document(self):
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
document_type = DocumentType.objects.create(
|
||||
label=TEST_DOCUMENT_TYPE
|
||||
@@ -93,9 +86,7 @@ class FolderAPITestCase(APITestCase):
|
||||
|
||||
@override_settings(OCR_AUTO_OCR=False)
|
||||
def test_folder_remove_document(self):
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
document_type = DocumentType.objects.create(
|
||||
label=TEST_DOCUMENT_TYPE
|
||||
|
||||
@@ -12,6 +12,8 @@ from user_management.tests.literals import (
|
||||
|
||||
from ..models import Folder
|
||||
|
||||
from .literals import TEST_FOLDER_LABEL
|
||||
|
||||
|
||||
class FolderTestCase(TestCase):
|
||||
def setUp(self):
|
||||
@@ -32,23 +34,21 @@ class FolderTestCase(TestCase):
|
||||
def tearDown(self):
|
||||
self.document_type.delete()
|
||||
|
||||
def test_creation_of_folder(self):
|
||||
folder = Folder.objects.create(label='test', user=self.user)
|
||||
def test_folder_creation(self):
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
self.assertEqual(Folder.objects.all().count(), 1)
|
||||
self.assertEqual(list(Folder.objects.all()), [folder])
|
||||
folder.delete()
|
||||
|
||||
def test_addition_of_documents(self):
|
||||
folder = Folder.objects.create(label='test', user=self.user)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
folder.documents.add(self.document)
|
||||
|
||||
self.assertEqual(folder.documents.count(), 1)
|
||||
self.assertEqual(list(folder.documents.all()), [self.document])
|
||||
folder.delete()
|
||||
|
||||
def test_addition_and_deletion_of_documents(self):
|
||||
folder = Folder.objects.create(label='test', user=self.user)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
folder.documents.add(self.document)
|
||||
|
||||
self.assertEqual(folder.documents.count(), 1)
|
||||
@@ -58,5 +58,3 @@ class FolderTestCase(TestCase):
|
||||
|
||||
self.assertEqual(folder.documents.count(), 0)
|
||||
self.assertEqual(list(folder.documents.all()), [])
|
||||
|
||||
folder.delete()
|
||||
|
||||
@@ -43,12 +43,9 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
self.assertContains(response, text='created', status_code=200)
|
||||
self.assertEqual(Folder.objects.count(), 1)
|
||||
self.assertEqual(Folder.objects.first().label, TEST_FOLDER_LABEL)
|
||||
self.assertEqual(Folder.objects.first().user, self.user)
|
||||
|
||||
def test_folder_create_duplicate_view_with_permission(self):
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
||||
|
||||
@@ -62,16 +59,14 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
}
|
||||
)
|
||||
|
||||
self.assertContains(response, text='Error', status_code=200)
|
||||
self.assertContains(response, text='exists', status_code=200)
|
||||
self.assertEqual(Folder.objects.count(), 1)
|
||||
self.assertEqual(Folder.objects.first().pk, folder.pk)
|
||||
|
||||
def test_folder_delete_view_no_permission(self):
|
||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post('folders:folder_delete', args=(folder.pk,))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
@@ -84,9 +79,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
permission_folder_delete.stored_permission
|
||||
)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_delete', args=(folder.pk,), follow=True
|
||||
@@ -98,9 +91,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
def test_folder_edit_view_no_permission(self):
|
||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_edit', args=(folder.pk,), data={
|
||||
@@ -118,9 +109,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
permission_folder_edit.stored_permission
|
||||
)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_edit', args=(folder.pk,), data={
|
||||
@@ -129,7 +118,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
)
|
||||
|
||||
folder = Folder.objects.get(pk=folder.pk)
|
||||
self.assertContains(response, text='saved', status_code=200)
|
||||
self.assertContains(response, text='update', status_code=200)
|
||||
self.assertEqual(folder.label, TEST_FOLDER_EDITED_LABEL)
|
||||
|
||||
def test_folder_add_document_view_no_permission(self):
|
||||
@@ -137,9 +126,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
|
||||
self.role.permissions.add(permission_folder_view.stored_permission)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_add_document', args=(self.document.pk,), data={
|
||||
@@ -163,9 +150,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
permission_document_view.stored_permission
|
||||
)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_add_document', args=(self.document.pk,), data={
|
||||
@@ -185,9 +170,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
|
||||
self.role.permissions.add(permission_folder_view.stored_permission)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_add_multiple_documents', data={
|
||||
@@ -207,9 +190,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
permission_folder_add_document.stored_permission
|
||||
)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.admin_user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
response = self.post(
|
||||
'folders:folder_add_multiple_documents', data={
|
||||
@@ -227,9 +208,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
def test_folder_remove_document_view_no_permission(self):
|
||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
folder.documents.add(self.document)
|
||||
|
||||
@@ -254,9 +233,7 @@ class FolderViewTestCase(GenericDocumentViewTestCase):
|
||||
permission_folder_remove_document.stored_permission
|
||||
)
|
||||
|
||||
folder = Folder.objects.create(
|
||||
label=TEST_FOLDER_LABEL, user=self.user
|
||||
)
|
||||
folder = Folder.objects.create(label=TEST_FOLDER_LABEL)
|
||||
|
||||
folder.documents.add(self.document)
|
||||
self.assertEqual(folder.documents.count(), 1)
|
||||
|
||||
@@ -7,8 +7,8 @@ from .api_views import (
|
||||
APIFolderDocumentView, APIFolderListView, APIFolderView
|
||||
)
|
||||
from .views import (
|
||||
DocumentFolderListView, FolderCreateView, FolderDetailView, FolderEditView,
|
||||
FolderListView
|
||||
DocumentFolderListView, FolderCreateView, FolderDeleteView,
|
||||
FolderDetailView, FolderEditView, FolderListView
|
||||
)
|
||||
|
||||
urlpatterns = patterns(
|
||||
@@ -17,7 +17,8 @@ urlpatterns = patterns(
|
||||
url(r'^create/$', FolderCreateView.as_view(), name='folder_create'),
|
||||
url(r'^(?P<pk>\d+)/edit/$', FolderEditView.as_view(), name='folder_edit'),
|
||||
url(
|
||||
r'^(?P<folder_id>\d+)/delete/$', 'folder_delete', name='folder_delete'
|
||||
r'^(?P<pk>\d+)/delete/$', FolderDeleteView.as_view(),
|
||||
name='folder_delete'
|
||||
),
|
||||
url(r'^(?P<pk>\d+)/$', FolderDetailView.as_view(), name='folder_view'),
|
||||
url(
|
||||
|
||||
@@ -13,7 +13,8 @@ from django.utils.translation import ugettext_lazy as _, ungettext
|
||||
|
||||
from acls.models import AccessControlList
|
||||
from common.views import (
|
||||
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
|
||||
SingleObjectCreateView, SingleObjectDeleteView, SingleObjectEditView,
|
||||
SingleObjectListView
|
||||
)
|
||||
from documents.permissions import permission_document_view
|
||||
from documents.models import Document
|
||||
@@ -40,11 +41,13 @@ class FolderEditView(SingleObjectEditView):
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'object': self.get_object(),
|
||||
'object_name': _('Folder'),
|
||||
'title': _('Edit folder: %s') % self.get_object(),
|
||||
}
|
||||
|
||||
|
||||
class FolderListView(SingleObjectListView):
|
||||
model = Folder
|
||||
object_permission = permission_folder_view
|
||||
|
||||
def get_extra_context(self):
|
||||
@@ -53,81 +56,30 @@ class FolderListView(SingleObjectListView):
|
||||
'title': _('Folders'),
|
||||
}
|
||||
|
||||
def get_folder_queryset(self):
|
||||
return Folder.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = self.get_folder_queryset()
|
||||
return super(FolderListView, self).get_queryset()
|
||||
|
||||
|
||||
class FolderCreateView(SingleObjectCreateView):
|
||||
fields = ('label',)
|
||||
model = Folder
|
||||
view_permission = permission_folder_create
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
Folder.objects.get(
|
||||
label=form.cleaned_data['label'], user=self.request.user
|
||||
)
|
||||
except Folder.DoesNotExist:
|
||||
instance = form.save(commit=False)
|
||||
instance.user = self.request.user
|
||||
instance.save()
|
||||
return super(FolderCreateView, self).form_valid(form)
|
||||
else:
|
||||
messages.error(
|
||||
self.request,
|
||||
_(
|
||||
'A folder named: %s, already exists.'
|
||||
) % form.cleaned_data['label']
|
||||
)
|
||||
return super(FolderCreateView, self).form_invalid(form)
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'object_name': _('Folder'),
|
||||
'title': _('Create folder'),
|
||||
}
|
||||
|
||||
|
||||
def folder_delete(request, folder_id):
|
||||
folder = get_object_or_404(Folder, pk=folder_id)
|
||||
class FolderDeleteView(SingleObjectDeleteView):
|
||||
model = Folder
|
||||
object_permission = permission_folder_delete
|
||||
post_action_redirect = reverse_lazy('folders:folder_list')
|
||||
|
||||
try:
|
||||
Permission.check_permissions(request.user, (permission_folder_delete,))
|
||||
except PermissionDenied:
|
||||
AccessControlList.objects.check_access(
|
||||
permission_folder_delete, request.user, folder
|
||||
)
|
||||
|
||||
post_action_redirect = reverse('folders:folder_list')
|
||||
|
||||
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
||||
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
||||
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
folder.delete()
|
||||
messages.success(request, _('Folder: %s deleted successfully.') % folder)
|
||||
except Exception as exception:
|
||||
messages.error(request, _('Folder: %(folder)s delete error: %(error)s') % {
|
||||
'folder': folder, 'error': exception})
|
||||
|
||||
return HttpResponseRedirect(next)
|
||||
|
||||
context = {
|
||||
'delete_view': True,
|
||||
'previous': previous,
|
||||
'next': next,
|
||||
'object': folder,
|
||||
'title': _('Delete the folder: %s?') % folder,
|
||||
}
|
||||
|
||||
return render_to_response(
|
||||
'appearance/generic_confirm.html', context,
|
||||
context_instance=RequestContext(request)
|
||||
)
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'object_name': _('Folder'),
|
||||
'object': self.get_object(),
|
||||
'title': _('Delete the folder: %s?') % self.get_object(),
|
||||
}
|
||||
|
||||
|
||||
class FolderDetailView(DocumentListView):
|
||||
@@ -260,7 +212,7 @@ class DocumentFolderListView(FolderListView):
|
||||
'title': _('Folders containing document: %s') % self.document,
|
||||
}
|
||||
|
||||
def get_folder_queryset(self):
|
||||
def get_queryset(self):
|
||||
return self.document.document_folders().all()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user