Compare commits
2 Commits
features/t
...
features/d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0ae0d06c7 | ||
|
|
924778d42f |
27
HISTORY.rst
27
HISTORY.rst
@@ -1,32 +1,7 @@
|
||||
3.2.4 (2019-06-XX)
|
||||
==================
|
||||
* Support configurable GUnicorn timeouts. Defaults to
|
||||
current value of 120 seconds.
|
||||
* Fix help text of the platformtemplate command.
|
||||
|
||||
3.2.3 (2019-06-21)
|
||||
==================
|
||||
* Add support for disabling the random primary key
|
||||
test mixin.
|
||||
* Fix mailing profile log columns mappings.
|
||||
GitLab issue #626. Thanks to Jesaja Everling (@jeverling)
|
||||
for the report.
|
||||
* Fix the Django SMTP backend username field name.
|
||||
GitLab issue #625. Thanks to Jesaja Everling (@jeverling)
|
||||
for the report and the research.
|
||||
* Increase the Django STMP username.
|
||||
GitLab issue #625. Thanks to Jesaja Everling (@jeverling)
|
||||
for the report and the research.
|
||||
|
||||
3.2.2 (2019-06-19)
|
||||
3.2.2 (2019-06-XX)
|
||||
==================
|
||||
* Fix document type change view. Closes GitLab issue #614
|
||||
Thanks to Christoph Roeder (@brightdroid) for the report.
|
||||
* Fix document parsing tool view typo. Closes GitLab issue #615.
|
||||
Thanks to Tyler Page (@iamtpage) for the report.
|
||||
* Update the task_check_interval_source reference
|
||||
GitLab issue #617. Thanks to Lukas Gill (@lukkigi) for
|
||||
the report and debug information.
|
||||
|
||||
3.2.1 (2019-06-14)
|
||||
==================
|
||||
|
||||
@@ -57,8 +57,9 @@ apt-get update \
|
||||
&& echo "maxmemory-policy allkeys-lru" >> /etc/redis/redis.conf \
|
||||
# Disable saving the Redis database
|
||||
echo "save \"\"" >> /etc/redis/redis.conf \
|
||||
# Only provision 1 database
|
||||
&& echo "databases 1" >> /etc/redis/redis.conf
|
||||
# Only provision 2 database. One for the broker and the other for
|
||||
# results
|
||||
&& echo "databases 2" >> /etc/redis/redis.conf
|
||||
|
||||
|
||||
####
|
||||
@@ -96,14 +97,14 @@ apt-get install -y --no-install-recommends \
|
||||
libssl-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
python-dev \
|
||||
python-virtualenv \
|
||||
python3-dev \
|
||||
python3-virtualenv \
|
||||
&& mkdir -p "${PROJECT_INSTALL_DIR}" \
|
||||
&& chown -R mayan:mayan "${PROJECT_INSTALL_DIR}" \
|
||||
&& chown -R mayan:mayan /src
|
||||
|
||||
USER mayan
|
||||
RUN python -m virtualenv "${PROJECT_INSTALL_DIR}" \
|
||||
RUN python3 -m virtualenv -p /usr/bin/python3 "${PROJECT_INSTALL_DIR}" \
|
||||
&& . "${PROJECT_INSTALL_DIR}/bin/activate" \
|
||||
&& pip install --no-cache-dir --no-use-pep517 \
|
||||
librabbitmq==1.6.1 \
|
||||
|
||||
@@ -22,7 +22,6 @@ export MAYAN_SETTINGS_MODULE=${MAYAN_SETTINGS_MODULE:-mayan.settings.production}
|
||||
|
||||
export MAYAN_GUNICORN_BIN=${MAYAN_PYTHON_BIN_DIR}gunicorn
|
||||
export MAYAN_GUNICORN_WORKERS=${MAYAN_GUNICORN_WORKERS:-2}
|
||||
export MAYAN_GUNICORN_TIMEOUT=${MAYAN_GUNICORN_TIMEOUT:-120}
|
||||
export MAYAN_PIP_BIN=${MAYAN_PYTHON_BIN_DIR}pip
|
||||
export MAYAN_STATIC_ROOT=${MAYAN_INSTALL_DIR}/static
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.2.3
|
||||
3.2.1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Version 3.2.2
|
||||
=============
|
||||
|
||||
Released: June 19, 2019
|
||||
Released: June 17, 2019
|
||||
|
||||
|
||||
Changes
|
||||
@@ -9,11 +9,6 @@ Changes
|
||||
|
||||
- Fix document type change view. Closes GitLab issue #614.
|
||||
Thanks to Christoph Roeder (@brightdroid) for the report.
|
||||
- Fix document parsing tool view typo. Closes GitLab issue #615.
|
||||
Thanks to Tyler Page (@iamtpage) for the report.
|
||||
- Update the task_check_interval_source reference
|
||||
GitLab issue #617. Thanks to Lukas Gill (@lukkigi) for
|
||||
the report and debug information.
|
||||
|
||||
Removals
|
||||
--------
|
||||
@@ -33,7 +28,7 @@ Remove deprecated requirements::
|
||||
|
||||
Type in the console::
|
||||
|
||||
$ pip install mayan-edms==3.2.2
|
||||
$ pip install mayan-edms==3.2.1
|
||||
|
||||
the requirements will also be updated automatically.
|
||||
|
||||
@@ -103,7 +98,5 @@ Bugs fixed or issues closed
|
||||
---------------------------
|
||||
|
||||
- :gitlab-issue:`614` change type exception
|
||||
- :gitlab-issue:`615` TypeError: success() got an unexpected keyword argument 'requrest'
|
||||
- :gitlab-issue:`617` Watcher Task not running
|
||||
|
||||
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
Version 3.2.3
|
||||
=============
|
||||
|
||||
Released: June 21, 2019
|
||||
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
- Add support for disabling the random primary key
|
||||
test mixin.
|
||||
- Fix mailing profile log columns mappings.
|
||||
GitLab issue #626. Thanks to Jesaja Everling (@jeverling)
|
||||
for the report.
|
||||
- Fix the Django SMTP backend username field name.
|
||||
GitLab issue #625. Thanks to Jesaja Everling (@jeverling)
|
||||
for the report and the research.
|
||||
- Increase the Django STMP username.
|
||||
GitLab issue #625. Thanks to Jesaja Everling (@jeverling)
|
||||
for the report and the research.
|
||||
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
- None
|
||||
|
||||
|
||||
Upgrading from a previous version
|
||||
---------------------------------
|
||||
|
||||
If installed via Python's PIP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ curl https://gitlab.com/mayan-edms/mayan-edms/raw/master/removals.txt | pip uninstall -r /dev/stdin
|
||||
|
||||
Type in the console::
|
||||
|
||||
$ pip install mayan-edms==3.2.1
|
||||
|
||||
the requirements will also be updated automatically.
|
||||
|
||||
|
||||
Using Git
|
||||
^^^^^^^^^
|
||||
|
||||
If you installed Mayan EDMS by cloning the Git repository issue the commands::
|
||||
|
||||
$ git reset --hard HEAD
|
||||
$ git pull
|
||||
|
||||
otherwise download the compressed archived and uncompress it overriding the
|
||||
existing installation.
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ pip uninstall -y -r removals.txt
|
||||
|
||||
Next upgrade/add the new requirements::
|
||||
|
||||
$ pip install --upgrade -r requirements.txt
|
||||
|
||||
|
||||
Common steps
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Perform these steps after updating the code from either step above.
|
||||
|
||||
Make a backup of your supervisord file::
|
||||
|
||||
sudo cp /etc/supervisor/conf.d/mayan.conf /etc/supervisor/conf.d/mayan.conf.bck
|
||||
|
||||
Update the supervisord configuration file. Replace the environment
|
||||
variables values show here with your respective settings. This step will refresh
|
||||
the supervisord configuration file with the new queues and the latest
|
||||
recommended layout::
|
||||
|
||||
MAYAN_DATABASE_ENGINE=django.db.backends.postgresql MAYAN_DATABASE_NAME=mayan \
|
||||
MAYAN_DATABASE_PASSWORD=mayanuserpass MAYAN_DATABASE_USER=mayan \
|
||||
MAYAN_DATABASE_HOST=127.0.0.1 MAYAN_MEDIA_ROOT=/opt/mayan-edms/media \
|
||||
/opt/mayan-edms/bin/mayan-edms.py platformtemplate supervisord > /etc/supervisor/conf.d/mayan.conf
|
||||
|
||||
Edit the supervisord configuration file and update any setting the template
|
||||
generator missed::
|
||||
|
||||
vi /etc/supervisor/conf.d/mayan.conf
|
||||
|
||||
Migrate existing database schema with::
|
||||
|
||||
$ mayan-edms.py performupgrade
|
||||
|
||||
Add new static media::
|
||||
|
||||
$ mayan-edms.py preparestatic --noinput
|
||||
|
||||
The upgrade procedure is now complete.
|
||||
|
||||
|
||||
Backward incompatible changes
|
||||
-----------------------------
|
||||
|
||||
- None
|
||||
|
||||
|
||||
Bugs fixed or issues closed
|
||||
---------------------------
|
||||
|
||||
- :gitlab-issue:`619` poplib.POP3_SSL and poplib.POP3 initialized with wrong kwarg
|
||||
- :gitlab-issue:`625` mayan.apps.mailer.mailers.DjangoSMTP uses "user", but django.core.mail.backends.smtp.EmailBackend expects "username"
|
||||
- :gitlab-issue:`626` Mailing profile error log is empty, despite errors
|
||||
|
||||
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
@@ -1,103 +0,0 @@
|
||||
Version 3.2.4
|
||||
=============
|
||||
|
||||
Released: June XX, 2019
|
||||
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
- Support configurable GUnicorn timeouts. Defaults to
|
||||
current value of 120 seconds.
|
||||
- Fix help text of the platformtemplate command.
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
- None
|
||||
|
||||
|
||||
Upgrading from a previous version
|
||||
---------------------------------
|
||||
|
||||
If installed via Python's PIP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ curl https://gitlab.com/mayan-edms/mayan-edms/raw/master/removals.txt | pip uninstall -r /dev/stdin
|
||||
|
||||
Type in the console::
|
||||
|
||||
$ pip install mayan-edms==3.2.3
|
||||
|
||||
the requirements will also be updated automatically.
|
||||
|
||||
|
||||
Using Git
|
||||
^^^^^^^^^
|
||||
|
||||
If you installed Mayan EDMS by cloning the Git repository issue the commands::
|
||||
|
||||
$ git reset --hard HEAD
|
||||
$ git pull
|
||||
|
||||
otherwise download the compressed archived and uncompress it overriding the
|
||||
existing installation.
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ pip uninstall -y -r removals.txt
|
||||
|
||||
Next upgrade/add the new requirements::
|
||||
|
||||
$ pip install --upgrade -r requirements.txt
|
||||
|
||||
|
||||
Common steps
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Perform these steps after updating the code from either step above.
|
||||
|
||||
Make a backup of your supervisord file::
|
||||
|
||||
sudo cp /etc/supervisor/conf.d/mayan.conf /etc/supervisor/conf.d/mayan.conf.bck
|
||||
|
||||
Update the supervisord configuration file. Replace the environment
|
||||
variables values show here with your respective settings. This step will refresh
|
||||
the supervisord configuration file with the new queues and the latest
|
||||
recommended layout::
|
||||
|
||||
MAYAN_DATABASE_ENGINE=django.db.backends.postgresql MAYAN_DATABASE_NAME=mayan \
|
||||
MAYAN_DATABASE_PASSWORD=mayanuserpass MAYAN_DATABASE_USER=mayan \
|
||||
MAYAN_DATABASE_HOST=127.0.0.1 MAYAN_MEDIA_ROOT=/opt/mayan-edms/media \
|
||||
/opt/mayan-edms/bin/mayan-edms.py platformtemplate supervisord > /etc/supervisor/conf.d/mayan.conf
|
||||
|
||||
Edit the supervisord configuration file and update any setting the template
|
||||
generator missed::
|
||||
|
||||
vi /etc/supervisor/conf.d/mayan.conf
|
||||
|
||||
Migrate existing database schema with::
|
||||
|
||||
$ mayan-edms.py performupgrade
|
||||
|
||||
Add new static media::
|
||||
|
||||
$ mayan-edms.py preparestatic --noinput
|
||||
|
||||
The upgrade procedure is now complete.
|
||||
|
||||
|
||||
Backward incompatible changes
|
||||
-----------------------------
|
||||
|
||||
- None
|
||||
|
||||
|
||||
Bugs fixed or issues closed
|
||||
---------------------------
|
||||
|
||||
- :gitlab-issue:`628` mailbox.user in POP3Email gets passed keyword argument, but only accepts "user" or positional argument
|
||||
|
||||
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
@@ -20,8 +20,6 @@ versions of the documentation contain the release notes for any later releases.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
3.2.4
|
||||
3.2.3
|
||||
3.2.2
|
||||
3.2.1
|
||||
3.2
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__title__ = 'Mayan EDMS'
|
||||
__version__ = '3.2.3'
|
||||
__build__ = 0x030203
|
||||
__build_string__ = 'v3.2.3_Fri Jun 21 00:01:37 2019 -0400'
|
||||
__version__ = '3.2.1'
|
||||
__build__ = 0x030201
|
||||
__build_string__ = 'v3.2.1_Fri Jun 14 03:01:40 2019 -0400'
|
||||
__django_version__ = '1.11'
|
||||
__author__ = 'Roberto Rosario'
|
||||
__author_email__ = 'roberto.rosario@mayan-edms.com'
|
||||
|
||||
@@ -144,7 +144,6 @@ class RandomPrimaryKeyModelMonkeyPatchMixin(object):
|
||||
random_primary_key_random_floor = 100
|
||||
random_primary_key_random_ceiling = 10000
|
||||
random_primary_key_maximum_attempts = 100
|
||||
random_primary_key_enable = True
|
||||
|
||||
@staticmethod
|
||||
def get_unique_primary_key(model):
|
||||
@@ -171,49 +170,47 @@ class RandomPrimaryKeyModelMonkeyPatchMixin(object):
|
||||
return primary_key
|
||||
|
||||
def setUp(self):
|
||||
if self.random_primary_key_enable:
|
||||
self.method_save_original = models.Model.save
|
||||
self.method_save_original = models.Model.save
|
||||
|
||||
def method_save_new(instance, *args, **kwargs):
|
||||
if instance.pk:
|
||||
return self.method_save_original(instance, *args, **kwargs)
|
||||
else:
|
||||
# Set meta.auto_created to True to have the original save_base
|
||||
# not send the pre_save signal which would normally send
|
||||
# the instance without a primary key. Since we assign a random
|
||||
# primary key any pre_save signal handler that relies on an
|
||||
# empty primary key will fail.
|
||||
# The meta.auto_created and manual pre_save sending emulates
|
||||
# the original behavior. Since meta.auto_created also disables
|
||||
# the post_save signal we must also send it ourselves.
|
||||
# This hack work with Django 1.11 .save_base() but can break
|
||||
# in future versions if that method is updated.
|
||||
pre_save.send(
|
||||
sender=instance.__class__, instance=instance, raw=False,
|
||||
update_fields=None,
|
||||
)
|
||||
instance._meta.auto_created = True
|
||||
instance.pk = RandomPrimaryKeyModelMonkeyPatchMixin.get_unique_primary_key(
|
||||
model=instance._meta.model
|
||||
)
|
||||
instance.id = instance.pk
|
||||
def method_save_new(instance, *args, **kwargs):
|
||||
if instance.pk:
|
||||
return self.method_save_original(instance, *args, **kwargs)
|
||||
else:
|
||||
# Set meta.auto_created to True to have the original save_base
|
||||
# not send the pre_save signal which would normally send
|
||||
# the instance without a primary key. Since we assign a random
|
||||
# primary key any pre_save signal handler that relies on an
|
||||
# empty primary key will fail.
|
||||
# The meta.auto_created and manual pre_save sending emulates
|
||||
# the original behavior. Since meta.auto_created also disables
|
||||
# the post_save signal we must also send it ourselves.
|
||||
# This hack work with Django 1.11 .save_base() but can break
|
||||
# in future versions if that method is updated.
|
||||
pre_save.send(
|
||||
sender=instance.__class__, instance=instance, raw=False,
|
||||
update_fields=None,
|
||||
)
|
||||
instance._meta.auto_created = True
|
||||
instance.pk = RandomPrimaryKeyModelMonkeyPatchMixin.get_unique_primary_key(
|
||||
model=instance._meta.model
|
||||
)
|
||||
instance.id = instance.pk
|
||||
|
||||
result = instance.save_base(force_insert=True)
|
||||
instance._meta.auto_created = False
|
||||
result = instance.save_base(force_insert=True)
|
||||
instance._meta.auto_created = False
|
||||
|
||||
post_save.send(
|
||||
sender=instance.__class__, instance=instance, created=True,
|
||||
update_fields=None, raw=False
|
||||
)
|
||||
post_save.send(
|
||||
sender=instance.__class__, instance=instance, created=True,
|
||||
update_fields=None, raw=False
|
||||
)
|
||||
|
||||
return result
|
||||
return result
|
||||
|
||||
setattr(models.Model, 'save', method_save_new)
|
||||
setattr(models.Model, 'save', method_save_new)
|
||||
super(RandomPrimaryKeyModelMonkeyPatchMixin, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
if self.random_primary_key_enable:
|
||||
models.Model.save = self.method_save_original
|
||||
models.Model.save = self.method_save_original
|
||||
super(RandomPrimaryKeyModelMonkeyPatchMixin, self).tearDown()
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@ from mayan.apps.documents.tests import (
|
||||
)
|
||||
|
||||
from ..permissions import (
|
||||
permission_content_view, permission_document_type_parsing_setup,
|
||||
permission_parse_document
|
||||
permission_content_view, permission_document_type_parsing_setup
|
||||
)
|
||||
from ..utils import get_document_content
|
||||
|
||||
@@ -107,43 +106,3 @@ class DocumentContentViewsTestCase(GenericDocumentViewTestCase):
|
||||
|
||||
response = self._request_test_document_type_parsing_settings()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
||||
class DocumentContentToolsViewsTestCase(GenericDocumentViewTestCase):
|
||||
_skip_file_descriptor_test = True
|
||||
|
||||
# Ensure we use a PDF file
|
||||
test_document_filename = TEST_HYBRID_DOCUMENT
|
||||
|
||||
def _request_document_parsing_tool_view(self):
|
||||
return self.post(
|
||||
viewname='document_parsing:document_type_submit', data={
|
||||
'document_type': self.test_document_type.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _get_document_content(self):
|
||||
return ''.join(list(get_document_content(document=self.test_document)))
|
||||
|
||||
def test_document_parsing_tool_view_no_permission(self):
|
||||
|
||||
response = self._request_document_parsing_tool_view()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(
|
||||
response=response, status_code=200,
|
||||
text=self.test_document_type.label
|
||||
)
|
||||
|
||||
self.assertNotEqual(
|
||||
self._get_document_content(), TEST_DOCUMENT_CONTENT
|
||||
)
|
||||
|
||||
def test_document_parsing_tool_view_with_permission(self):
|
||||
self.grant_permission(permission=permission_parse_document)
|
||||
|
||||
response = self._request_document_parsing_tool_view()
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
self.assertEqual(
|
||||
self._get_document_content(), TEST_DOCUMENT_CONTENT
|
||||
)
|
||||
|
||||
@@ -185,7 +185,7 @@ class DocumentTypeSubmitView(FormView):
|
||||
'%(count)d documents added to the parsing queue.'
|
||||
) % {
|
||||
'count': count,
|
||||
}, request=self.request
|
||||
}, requrest=self.request
|
||||
)
|
||||
|
||||
return HttpResponseRedirect(redirect_to=self.get_success_url())
|
||||
|
||||
@@ -18,9 +18,6 @@ event_document_new_version = namespace.add_event_type(
|
||||
event_document_properties_edit = namespace.add_event_type(
|
||||
label=_('Document properties edited'), name='document_edit'
|
||||
)
|
||||
event_document_trashed = namespace.add_event_type(
|
||||
label=_('Document moved to trash'), name='document_trashed'
|
||||
)
|
||||
# The type of an existing document is changed to another type
|
||||
event_document_type_change = namespace.add_event_type(
|
||||
label=_('Document type changed'), name='document_type_change'
|
||||
|
||||
@@ -5,7 +5,7 @@ import uuid
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.files import File
|
||||
from django.db import models, transaction
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.timezone import now
|
||||
@@ -13,7 +13,7 @@ from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from ..events import (
|
||||
event_document_create, event_document_properties_edit,
|
||||
event_document_trashed, event_document_type_change,
|
||||
event_document_type_change,
|
||||
)
|
||||
from ..managers import DocumentManager, PassthroughManager, TrashCanManager
|
||||
from ..settings import setting_language
|
||||
@@ -104,14 +104,11 @@ class Document(models.Model):
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
to_trash = kwargs.pop('to_trash', True)
|
||||
_user = kwargs.pop('_user', None)
|
||||
|
||||
if not self.in_trash and to_trash:
|
||||
with transaction.atomic():
|
||||
self.in_trash = True
|
||||
self.deleted_date_time = now()
|
||||
self.save()
|
||||
event_document_trashed.commit(actor=_user, target=self)
|
||||
self.in_trash = True
|
||||
self.deleted_date_time = now()
|
||||
self.save()
|
||||
else:
|
||||
for version in self.versions.all():
|
||||
version.delete()
|
||||
@@ -180,23 +177,21 @@ class Document(models.Model):
|
||||
user = kwargs.pop('_user', None)
|
||||
_commit_events = kwargs.pop('_commit_events', True)
|
||||
new_document = not self.pk
|
||||
super(Document, self).save(*args, **kwargs)
|
||||
|
||||
with transaction.atomic():
|
||||
super(Document, self).save(*args, **kwargs)
|
||||
|
||||
if new_document:
|
||||
if user:
|
||||
self.add_as_recent_document_for_user(user)
|
||||
event_document_create.commit(
|
||||
actor=user, target=self, action_object=self.document_type
|
||||
)
|
||||
else:
|
||||
event_document_create.commit(
|
||||
target=self, action_object=self.document_type
|
||||
)
|
||||
if new_document:
|
||||
if user:
|
||||
self.add_as_recent_document_for_user(user)
|
||||
event_document_create.commit(
|
||||
actor=user, target=self, action_object=self.document_type
|
||||
)
|
||||
else:
|
||||
if _commit_events:
|
||||
event_document_properties_edit.commit(actor=user, target=self)
|
||||
event_document_create.commit(
|
||||
target=self, action_object=self.document_type
|
||||
)
|
||||
else:
|
||||
if _commit_events:
|
||||
event_document_properties_edit.commit(actor=user, target=self)
|
||||
|
||||
def save_to_file(self, *args, **kwargs):
|
||||
return self.latest_version.save_to_file(*args, **kwargs)
|
||||
@@ -205,16 +200,15 @@ class Document(models.Model):
|
||||
has_changed = self.document_type != document_type
|
||||
|
||||
self.document_type = document_type
|
||||
with transaction.atomic():
|
||||
self.save()
|
||||
if has_changed or force:
|
||||
post_document_type_change.send(
|
||||
sender=self.__class__, instance=self
|
||||
)
|
||||
self.save()
|
||||
if has_changed or force:
|
||||
post_document_type_change.send(
|
||||
sender=self.__class__, instance=self
|
||||
)
|
||||
|
||||
event_document_type_change.commit(actor=_user, target=self)
|
||||
if _user:
|
||||
self.add_as_recent_document_for_user(user=_user)
|
||||
event_document_type_change.commit(actor=_user, target=self)
|
||||
if _user:
|
||||
self.add_as_recent_document_for_user(user=_user)
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
|
||||
@@ -228,6 +228,9 @@ class DocumentViewTestMixin(object):
|
||||
data={'id_list': self.test_document.pk}
|
||||
)
|
||||
|
||||
def _request_empty_trash_view(self):
|
||||
return self.post(viewname='documents:trash_can_empty')
|
||||
|
||||
def _request_document_print_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_print', kwargs={
|
||||
@@ -236,52 +239,3 @@ class DocumentViewTestMixin(object):
|
||||
'page_group': PAGE_RANGE_ALL
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class DocumentTrashViewMixin(object):
|
||||
def _request_document_delete_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_document_delete_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_document_list_deleted_view(self):
|
||||
return self.get(viewname='documents:document_list_deleted')
|
||||
|
||||
def _request_document_restore_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
def _request_document_restore_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_document_trash_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_empty_trash_view(self):
|
||||
return self.post(viewname='documents:trash_can_empty')
|
||||
|
||||
def _request_document_trash_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3,16 +3,12 @@ from __future__ import unicode_literals
|
||||
from actstream.models import Action
|
||||
from django_downloadview import assert_download_response
|
||||
|
||||
from ..events import (
|
||||
event_document_download, event_document_trashed, event_document_view
|
||||
)
|
||||
from ..events import event_document_download, event_document_view
|
||||
from ..permissions import (
|
||||
permission_document_download, permission_document_trash,
|
||||
permission_document_view
|
||||
permission_document_download, permission_document_view
|
||||
)
|
||||
|
||||
from .base import GenericDocumentViewTestCase
|
||||
from .mixins import DocumentTrashViewMixin
|
||||
|
||||
|
||||
TEST_DOCUMENT_TYPE_EDITED_LABEL = 'test document type edited label'
|
||||
@@ -88,20 +84,3 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
|
||||
self.assertEqual(event.actor, self._test_case_user)
|
||||
self.assertEqual(event.target, self.test_document)
|
||||
self.assertEqual(event.verb, event_document_view.id)
|
||||
|
||||
|
||||
class DocumentTrashEventsTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCase):
|
||||
def test_document_trash_event_with_permissions(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_access(
|
||||
obj=self.test_document, permission=permission_document_trash
|
||||
)
|
||||
|
||||
response = self._request_document_trash_post_view()
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
event = Action.objects.any(obj=self.test_document).first()
|
||||
#self.assertEqual(event.actor, self._test_case_user)
|
||||
self.assertEqual(event.target, self.test_document)
|
||||
self.assertEqual(event.verb, event_document_trashed.id)
|
||||
|
||||
@@ -7,10 +7,16 @@ from ..permissions import (
|
||||
)
|
||||
|
||||
from .base import GenericDocumentViewTestCase
|
||||
from .mixins import DocumentTrashViewMixin
|
||||
|
||||
|
||||
class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCase):
|
||||
class TrashedDocumentTestCase(GenericDocumentViewTestCase):
|
||||
def _request_document_restore_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def test_document_restore_get_view_no_permission(self):
|
||||
self.test_document.delete()
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
@@ -37,6 +43,13 @@ class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCas
|
||||
|
||||
self.assertEqual(Document.objects.count(), document_count)
|
||||
|
||||
def _request_document_restore_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def test_document_restore_post_view_no_permission(self):
|
||||
self.test_document.delete()
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
@@ -61,6 +74,13 @@ class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCas
|
||||
self.assertEqual(DeletedDocument.objects.count(), 0)
|
||||
self.assertEqual(Document.objects.count(), 1)
|
||||
|
||||
def _request_document_trash_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def test_document_trash_get_view_no_permissions(self):
|
||||
document_count = Document.objects.count()
|
||||
|
||||
@@ -81,6 +101,13 @@ class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCas
|
||||
|
||||
self.assertEqual(Document.objects.count(), document_count)
|
||||
|
||||
def _request_document_trash_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def test_document_trash_post_view_no_permissions(self):
|
||||
response = self._request_document_trash_post_view()
|
||||
self.assertEqual(response.status_code, 404)
|
||||
@@ -99,6 +126,13 @@ class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCas
|
||||
self.assertEqual(DeletedDocument.objects.count(), 1)
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
|
||||
def _request_document_delete_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def test_document_delete_get_view_no_permissions(self):
|
||||
self.test_document.delete()
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
@@ -131,6 +165,13 @@ class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCas
|
||||
DeletedDocument.objects.count(), trashed_document_count
|
||||
)
|
||||
|
||||
def _request_document_delete_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def test_document_delete_post_view_no_permissions(self):
|
||||
self.test_document.delete()
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
@@ -157,6 +198,9 @@ class TrashedDocumentTestCase(DocumentTrashViewMixin, GenericDocumentViewTestCas
|
||||
self.assertEqual(DeletedDocument.objects.count(), 0)
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
|
||||
def _request_document_list_deleted_view(self):
|
||||
return self.get(viewname='documents:document_list_deleted')
|
||||
|
||||
def test_deleted_document_list_view_no_permissions(self):
|
||||
self.test_document.delete()
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ class MailerApp(MayanAppConfig):
|
||||
|
||||
LogEntry = self.get_model(model_name='LogEntry')
|
||||
UserMailer = self.get_model(model_name='UserMailer')
|
||||
UserMailerLogEntry = self.get_model(model_name='UserMailerLogEntry')
|
||||
|
||||
MailerBackend.initialize()
|
||||
|
||||
@@ -80,13 +79,6 @@ class MailerApp(MayanAppConfig):
|
||||
SourceColumn(
|
||||
source=UserMailer, attribute='backend_label'
|
||||
)
|
||||
SourceColumn(
|
||||
attribute='datetime', label=_('Date and time'),
|
||||
source=UserMailerLogEntry
|
||||
)
|
||||
SourceColumn(
|
||||
attribute='message', label=_('Message'), source=UserMailerLogEntry
|
||||
)
|
||||
|
||||
ModelPermission.register(
|
||||
model=Document, permissions=(
|
||||
|
||||
@@ -96,7 +96,7 @@ class UserMailerDynamicForm(DynamicModelForm):
|
||||
if self.instance.backend_data:
|
||||
backend_data = json.loads(self.instance.backend_data)
|
||||
for key in self.instance.get_backend().fields:
|
||||
self.fields[key].initial = backend_data.get(key)
|
||||
self.fields[key].initial = backend_data[key]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ class DjangoSMTP(MailerBackend):
|
||||
Backend that wraps Django's SMTP backend
|
||||
"""
|
||||
class_fields = (
|
||||
'host', 'port', 'use_tls', 'use_ssl', 'username', 'password'
|
||||
'host', 'port', 'use_tls', 'use_ssl', 'user', 'password'
|
||||
)
|
||||
class_path = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
field_order = (
|
||||
'host', 'port', 'use_tls', 'use_ssl', 'username', 'password', 'from'
|
||||
'host', 'port', 'use_tls', 'use_ssl', 'user', 'password', 'from'
|
||||
)
|
||||
fields = {
|
||||
'from': {
|
||||
@@ -60,14 +60,14 @@ class DjangoSMTP(MailerBackend):
|
||||
'that "Use TLS" and "Use SSL" are mutually exclusive, '
|
||||
'so only set one of those settings to True.'
|
||||
), 'required': False
|
||||
}, 'username': {
|
||||
}, 'user': {
|
||||
'label': _('Username'),
|
||||
'class': 'django.forms.CharField', 'default': '',
|
||||
'help_text': _(
|
||||
'Username to use for the SMTP server. If empty, '
|
||||
'authentication won\'t attempted.'
|
||||
), 'kwargs': {
|
||||
'max_length': 254
|
||||
'max_length': 48
|
||||
}, 'required': False
|
||||
}, 'password': {
|
||||
'label': _('Password'),
|
||||
|
||||
@@ -208,7 +208,7 @@ class UserMailerLogEntryListView(SingleObjectListView):
|
||||
return {
|
||||
'hide_object': True,
|
||||
'object': self.get_user_mailer(),
|
||||
'title': _('Error log for: %s') % self.get_user_mailer(),
|
||||
'title': _('%s error log') % self.get_user_mailer(),
|
||||
}
|
||||
|
||||
def get_source_queryset(self):
|
||||
|
||||
@@ -108,7 +108,7 @@ class PlatformTemplate(object):
|
||||
class PlatformTemplateSupervisord(PlatformTemplate):
|
||||
context_defaults = {
|
||||
'BROKER_URL': 'redis://127.0.0.1:6379/0',
|
||||
'CELERY_RESULT_BACKEND': 'redis://127.0.0.1:6379/0',
|
||||
'CELERY_RESULT_BACKEND': 'redis://127.0.0.1:6379/1',
|
||||
}
|
||||
label = _('Template for Supervisord.')
|
||||
name = 'supervisord'
|
||||
@@ -120,10 +120,6 @@ class PlatformTemplateSupervisord(PlatformTemplate):
|
||||
name='GUNICORN_WORKERS', default=2,
|
||||
environment_name='MAYAN_GUNICORN_WORKERS'
|
||||
),
|
||||
Variable(
|
||||
name='GUNICORN_TIMEOUT', default=120,
|
||||
environment_name='MAYAN_GUNICORN_TIMEOUT'
|
||||
),
|
||||
Variable(
|
||||
name='DATABASE_CONN_MAX_AGE', default=0,
|
||||
environment_name='MAYAN_DATABASE_CONN_MAX_AGE'
|
||||
|
||||
@@ -16,8 +16,7 @@ class Command(management.BaseCommand):
|
||||
)
|
||||
parser.add_argument(
|
||||
'--context', action='store', default='', dest='context',
|
||||
help='Pass a context to the template in the form of a JSON encoded '
|
||||
'dictionary.',
|
||||
help='Show a list of available templates.',
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
||||
@@ -16,7 +16,7 @@ environment=
|
||||
[program:mayan-gunicorn]
|
||||
autorestart = true
|
||||
autostart = true
|
||||
command = {{ INSTALLATION_PATH }}/bin/gunicorn -w {{ GUNICORN_WORKERS }} mayan.wsgi --max-requests 500 --max-requests-jitter 50 --worker-class gevent --bind 0.0.0.0:8000 --timeout {{ GUNICORN_TIMEOUT }}
|
||||
command = {{ INSTALLATION_PATH }}/bin/gunicorn -w {{ GUNICORN_WORKERS }} mayan.wsgi --max-requests 500 --max-requests-jitter 50 --worker-class gevent --bind 0.0.0.0:8000 --timeout 120
|
||||
user = mayan
|
||||
|
||||
{% for worker in workers %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[program:mayan-gunicorn]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = /bin/bash -c "${MAYAN_GUNICORN_BIN} -w ${MAYAN_GUNICORN_WORKERS} mayan.wsgi --max-requests 500 --max-requests-jitter 50 --worker-class gevent --bind 0.0.0.0:8000 --env DJANGO_SETTINGS_MODULE=${MAYAN_SETTINGS_MODULE}" --timeout ${MAYAN_GUNICORN_TIMEOUT}
|
||||
command = /bin/bash -c "${MAYAN_GUNICORN_BIN} -w ${MAYAN_GUNICORN_WORKERS} mayan.wsgi --max-requests 500 --max-requests-jitter 50 --worker-class gevent --bind 0.0.0.0:8000 --env DJANGO_SETTINGS_MODULE=${MAYAN_SETTINGS_MODULE}" --timeout 120
|
||||
redirect_stderr = true
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
|
||||
@@ -234,7 +234,7 @@ class IntervalBaseModel(OutOfProcessSource):
|
||||
PeriodicTask.objects.create(
|
||||
name=self._get_periodic_task_name(),
|
||||
interval=interval_instance,
|
||||
task='mayan.apps.sources.tasks.task_check_interval_source',
|
||||
task='sources.tasks.task_check_interval_source',
|
||||
kwargs=json.dumps({'source_id': self.pk})
|
||||
)
|
||||
|
||||
|
||||
@@ -277,15 +277,15 @@ class POP3Email(EmailBaseModel):
|
||||
logger.debug('ssl: %s', self.ssl)
|
||||
|
||||
if self.ssl:
|
||||
mailbox = poplib.POP3_SSL(host=self.host, port=self.port)
|
||||
mailbox = poplib.POP3_SSL(host=self.host, post=self.port)
|
||||
else:
|
||||
mailbox = poplib.POP3(
|
||||
host=self.host, port=self.port, timeout=self.timeout
|
||||
host=self.host, post=self.port, timeout=self.timeout
|
||||
)
|
||||
|
||||
mailbox.getwelcome()
|
||||
mailbox.user(self.username)
|
||||
mailbox.pass_(self.password)
|
||||
mailbox.user(username=self.username)
|
||||
mailbox.pass_(password=self.password)
|
||||
messages_info = mailbox.list()
|
||||
|
||||
logger.debug(msg='messages_info:')
|
||||
|
||||
@@ -203,10 +203,7 @@ class POP3SourceTestCase(GenericDocumentTestCase):
|
||||
def list(self, which=None):
|
||||
return (None, ['1 test'])
|
||||
|
||||
def user(self, user):
|
||||
return
|
||||
|
||||
def pass_(self, pswd):
|
||||
def pass_(self, password):
|
||||
return
|
||||
|
||||
def quit(self):
|
||||
@@ -217,7 +214,10 @@ class POP3SourceTestCase(GenericDocumentTestCase):
|
||||
1, [TEST_EMAIL_BASE64_FILENAME]
|
||||
)
|
||||
|
||||
@mock.patch('poplib.POP3_SSL', autospec=True)
|
||||
def user(self, username):
|
||||
return
|
||||
|
||||
@mock.patch('poplib.POP3_SSL')
|
||||
def test_download_document(self, mock_poplib):
|
||||
mock_poplib.return_value = POP3SourceTestCase.MockMailbox()
|
||||
self.source = POP3Email.objects.create(
|
||||
|
||||
Reference in New Issue
Block a user