Files
mayan-edms/mayan/apps/documents/managers.py
Roberto Rosario 55cd928069 Documents: Add default filtering of stubs
Add filter(is_stub) to the default Document model manager.

Now only the Passthrough manager can access document stubs.

Remove the explicit filtering of stubs from code that obtains
the queryset from the default document manager.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
2018-12-05 03:05:39 -04:00

285 lines
9.8 KiB
Python

from __future__ import unicode_literals
from datetime import timedelta
import logging
from django.apps import apps
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models import F, Max
from django.utils.encoding import force_text
from django.utils.timezone import now
from .literals import STUB_EXPIRATION_INTERVAL
from .settings import setting_favorite_count, setting_recent_access_count
logger = logging.getLogger(__name__)
class DocumentManager(models.Manager):
def get_by_natural_key(self, uuid):
return self.model.passthrough.get(uuid=force_text(uuid))
def get_queryset(self):
return TrashCanQuerySet(
self.model, using=self._db
).filter(in_trash=False).filter(is_stub=False)
def invalidate_cache(self):
for document in self.model.objects.all():
document.invalidate_cache()
class DocumentPageManager(models.Manager):
def get_by_natural_key(self, page_number, document_version_natural_key):
DocumentVersion = apps.get_model(
app_label='documents', model_name='DocumentVersion'
)
try:
document_version = DocumentVersion.objects.get_by_natural_key(*document_version_natural_key)
except DocumentVersion.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document_version__pk=document_version.pk, page_number=page_number)
class DocumentTypeManager(models.Manager):
def check_delete_periods(self):
logger.info('Executing')
for document_type in self.all():
logger.info(
'Checking deletion period of document type: %s', document_type
)
if document_type.delete_time_period and document_type.delete_time_unit:
delta = timedelta(
**{
document_type.delete_time_unit: document_type.delete_time_period
}
)
logger.info(
'Document type: %s, has a deletion period delta of: %s',
document_type, delta
)
for document in document_type.deleted_documents.filter(deleted_date_time__lt=now() - delta):
logger.info(
'Document "%s" with id: %d, trashed on: %s, exceded '
'delete period', document, document.pk,
document.deleted_date_time
)
document.delete()
else:
logger.info(
'Document type: %s, has a no retention delta', document_type
)
logger.info('Finshed')
def check_trash_periods(self):
logger.info('Executing')
for document_type in self.all():
logger.info(
'Checking trash period of document type: %s', document_type
)
if document_type.trash_time_period and document_type.trash_time_unit:
delta = timedelta(
**{
document_type.trash_time_unit: document_type.trash_time_period
}
)
logger.info(
'Document type: %s, has a trash period delta of: %s',
document_type, delta
)
for document in document_type.documents.filter(date_added__lt=now() - delta):
logger.info(
'Document "%s" with id: %d, added on: %s, exceded '
'trash period', document, document.pk,
document.date_added
)
document.delete()
else:
logger.info(
'Document type: %s, has a no retention delta', document_type
)
logger.info('Finshed')
def get_by_natural_key(self, label):
return self.get(label=label)
class DocumentVersionManager(models.Manager):
def get_by_natural_key(self, checksum, document_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
try:
document = Document.objects.get_by_natural_key(*document_natural_key)
except Document.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document__pk=document.pk, checksum=checksum)
class DuplicatedDocumentManager(models.Manager):
def clean_empty_duplicate_lists(self):
self.filter(documents=None).delete()
def get_duplicated_documents(self):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
return Document.objects.filter(
pk__in=self.filter(documents__isnull=False).values_list(
'document_id', flat=True
)
)
def scan(self):
"""
Find duplicates by iterating over all documents and then
find matching latest version checksums
"""
Document = apps.get_model(
app_label='documents', model_name='Document'
)
for document in Document.objects.all():
self.scan_for(document=document, scan_children=False)
def scan_for(self, document, scan_children=True):
"""
Find duplicates by matching latest version checksums
"""
if not document.latest_version:
return None
Document = apps.get_model(
app_label='documents', model_name='Document'
)
# Get the documents whose latest version matches the checksum
# of the current document and exclude the current document
duplicates = Document.objects.annotate(
max_timestamp=Max('versions__timestamp')
).filter(
versions__timestamp=F('max_timestamp'),
versions__checksum=document.checksum
).exclude(pk=document.pk)
if duplicates.exists():
instance, created = self.get_or_create(document=document)
instance.documents.add(*duplicates)
else:
self.filter(document=document).delete()
if scan_children:
for document in duplicates:
self.scan_for(document=document, scan_children=False)
class FavoriteDocumentManager(models.Manager):
def add_for_user(self, user, document):
favorite_document, created = self.model.objects.get_or_create(
user=user, document=document
)
old_favorites_to_delete = self.filter(user=user).values_list('pk', flat=True)[setting_favorite_count.value:]
self.filter(pk__in=list(old_favorites_to_delete)).delete()
def get_by_natural_key(self, datetime_accessed, document_natural_key, user_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
User = get_user_model()
try:
document = Document.objects.get_by_natural_key(*document_natural_key)
except Document.DoesNotExist:
raise self.model.DoesNotExist
else:
try:
user = User.objects.get_by_natural_key(*user_natural_key)
except User.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document__pk=document.pk, user__pk=user.pk)
def get_for_user(self, user):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
return Document.objects.filter(favorites__user=user)
def remove_for_user(self, user, document):
self.get(user=user, document=document).delete()
class PassthroughManager(models.Manager):
def delete_stubs(self):
for stale_stub_document in self.filter(is_stub=True, date_added__lt=now() - timedelta(seconds=STUB_EXPIRATION_INTERVAL)):
stale_stub_document.delete(to_trash=False)
class RecentDocumentManager(models.Manager):
def add_document_for_user(self, user, document):
if user.is_authenticated:
new_recent, created = self.model.objects.get_or_create(
user=user, document=document
)
if not created:
# document already in the recent list, just save to force
# accessed date and time update
new_recent.save()
recent_to_delete = self.filter(user=user).values_list('pk', flat=True)[setting_recent_access_count.value:]
self.filter(pk__in=list(recent_to_delete)).delete()
return new_recent
def get_by_natural_key(self, datetime_accessed, document_natural_key, user_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
User = get_user_model()
try:
document = Document.objects.get_by_natural_key(*document_natural_key)
except Document.DoesNotExist:
raise self.model.DoesNotExist
else:
try:
user = User.objects.get_by_natural_key(*user_natural_key)
except User.DoesNotExist:
raise self.model.DoesNotExist
return self.get(
document__pk=document.pk, user__pk=user.pk,
datetime_accessed=datetime_accessed
)
def get_for_user(self, user):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
if user.is_authenticated:
return Document.objects.filter(
recent__user=user
).order_by('-recent__datetime_accessed')
else:
return Document.objects.none()
class TrashCanManager(models.Manager):
def get_queryset(self):
return super(
TrashCanManager, self
).get_queryset().filter(in_trash=True)
class TrashCanQuerySet(models.QuerySet):
def delete(self, to_trash=True):
for instance in self:
instance.delete(to_trash=to_trash)