diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 94515f8807..0000000000 --- a/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!docker diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 587fe9f65f..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -FROM ubuntu:15.04 - -MAINTAINER Roberto Rosario "roberto.rosario@mayan-edms.com" - -# Install base Ubuntu libraries -RUN apt-get update && apt-get install -y netcat-openbsd python-dev python-pip gpgv nginx libpq-dev git-core libjpeg-dev libmagic1 libpng-dev libreoffice libtiff-dev gcc ghostscript gpgv tesseract-ocr unpaper poppler-utils && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -f /var/cache/apt/archives/*.deb - -ENV MAYAN_INSTALL_DIR=/usr/local/lib/python2.7/dist-packages/mayan - -# Install Mayan EDMS, latest production release -RUN pip install mayan-edms==2.0.0 - -# Install Python clients for PostgreSQL, REDIS, and uWSGI -RUN pip install psycopg2 redis uwsgi - -# Create Mayan EDMS basic settings/local.py file -RUN mayan-edms.py createsettings - -# Install Mayan EDMS static media files -RUN mayan-edms.py collectstatic --noinput - -ADD docker /docker - -# Setup Mayan EDMS settings file overrides -RUN cat /docker/conf/mayan/settings.py >> $MAYAN_INSTALL_DIR/settings/local.py - -# Setup NGINX -RUN rm /etc/nginx/sites-enabled/default -RUN ln -s /docker/conf/nginx/mayan-edms /etc/nginx/sites-enabled/mayan-edms - -# Setup UWSGI -RUN mkdir /var/log/uwsgi - -# Persistent Mayan EDMS files -VOLUME $MAYAN_INSTALL_DIR/media - -ENTRYPOINT ["/docker/entrypoint.sh"] - -EXPOSE 80 -CMD ["/docker/bin/run.sh"] diff --git a/HISTORY.rst b/HISTORY.rst index bf4c85d3ff..4fa58db1c3 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,19 +1,34 @@ 2.1 (2016-XX) +============= - Upgrade to use Django 1.8.8. Issue #246. - Upgrade requirements. - Remove remaining references to Django's User model. Issue #225 - Rename 'Content' search box to 'OCR'. - Remove included login required middleware using django-stronghold instead (http://mikegrouchy.com/django-stronghold/). + +2.0.2 (2016-02-09) +================== +- Install testing dependencies when installing development dependencies. +- Fix GitLab issue #250 "Empty optional lookup metadata trigger validation error". +- Fix OCR API test. +- Move metadata form value validation to .clean() method. +- Only extract validation error messages from ValidationError exception instances. +- Don't store empty metadata value if the update checkbox is not checked. +- Add 2 second delay to document version tests to workaround MySQL limitation. +- Strip HTML tags from the browser title. +- Remove Docker and Docker Compose files. + + 2.0.1 (2016-01-22) ================== - Fix GitLab issue #243, "System allows a user to skip entering values for a required metadata field while uploading a new document" - Fix GitLab issue #245, "Add multiple metadata not possible" - Updated Vagrantfile to provision a production box too. + 2.0 (2015-12-04) ================ - - New source homepage: https://gitlab.com/mayan-edms/mayan-edms - Update to Django 1.7 - New Bootstrap Frontend UI @@ -85,7 +100,6 @@ 1.1 (2015-02-10) ================ - - Uses Celery for background tasks - Removal of the splash screen - Adds a home view with common function buttons @@ -111,7 +125,6 @@ 1.0 (2014-08-27) ================ - - New home @ https://github.com/mayan-edms/mayan-edms - Updated to use Django 1.6 - Translation updates diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 371f567166..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,21 +0,0 @@ -postgres: - env_file: - - ./environment - image: postgres - volumes: - - /var/lib/postgresql/data - -redis: - image: redis - -mayan-edms: - env_file: - - ./environment - image: mayanedms/monolithic - links: - - postgres - - redis - ports: - - "80:80" - volumes: - - /usr/local/lib/python2.7/dist-packages/mayan/media diff --git a/docker/bin/run.sh b/docker/bin/run.sh deleted file mode 100755 index ad74092f90..0000000000 --- a/docker/bin/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Launch NGINX daemon -nginx - -# Launch the workers -mayan-edms.py celery worker --settings=mayan.settings.production -Ofair -l ERROR -B & - -# Launch uWSGI in foreground -/usr/local/bin/uwsgi --ini /docker/conf/uwsgi/uwsgi.ini diff --git a/docker/conf/mayan/settings.py b/docker/conf/mayan/settings.py deleted file mode 100644 index 50b90ae9bc..0000000000 --- a/docker/conf/mayan/settings.py +++ /dev/null @@ -1,15 +0,0 @@ -import os - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': os.environ.get('POSTGRES_DB'), - 'USER': os.environ.get('POSTGRES_USER'), - 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), - 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR'), - 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT'), - } -} - -BROKER_URL = 'redis://{}:{}/0'.format(os.environ.get('REDIS_PORT_6379_TCP_ADDR'), os.environ.get('REDIS_PORT_6379_TCP_PORT')) -CELERY_RESULT_BACKEND = 'redis://{}:{}/0'.format(os.environ.get('REDIS_PORT_6379_TCP_ADDR'), os.environ.get('REDIS_PORT_6379_TCP_PORT')) diff --git a/docker/conf/nginx/mayan-edms b/docker/conf/nginx/mayan-edms deleted file mode 100644 index 3522f55517..0000000000 --- a/docker/conf/nginx/mayan-edms +++ /dev/null @@ -1,22 +0,0 @@ -server { - listen 80; - server_name localhost; - - location / { - include uwsgi_params; - uwsgi_pass unix:/run/mayan.sock; - - client_max_body_size 30M; # Increse if your plan to upload bigger documents - proxy_read_timeout 30s; # Increase if your document uploads take more than 30 seconds - } - - location /static { - alias /usr/local/lib/python2.7/dist-packages/mayan/media/static; - expires 1h; - } - - location /favicon.ico { - alias /usr/local/lib/python2.7/dist-packages/mayan/media/static/appearance/images/favicon.ico; - expires 1h; - } -} diff --git a/docker/conf/uwsgi/uwsgi.ini b/docker/conf/uwsgi/uwsgi.ini deleted file mode 100644 index 6e2e1ff95f..0000000000 --- a/docker/conf/uwsgi/uwsgi.ini +++ /dev/null @@ -1,14 +0,0 @@ -[uwsgi] -chdir = $(MAYAN_INSTALL_DIR) -chmod-socket = 664 -chown-socket = www-data:www-data -env = DJANGO_SETTINGS_MODULE=mayan.settings.production -gid = root -logto = /var/log/uwsgi/%n.log -pythonpath = /usr/local/lib/python2.7/dist-packages -master = True -max-requests = 5000 -socket = /run/mayan.sock -uid = root -vacuum = True -wsgi-file = $(MAYAN_INSTALL_DIR)/wsgi.py diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh deleted file mode 100755 index 13fe1f395a..0000000000 --- a/docker/entrypoint.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -e - -if [[ -z $POSTGRES_PORT_5432_TCP_ADDR ]]; then - echo "** ERROR: You need to link the Postgres container." - exit 1 -fi - -until nc -z $POSTGRES_PORT_5432_TCP_ADDR $POSTGRES_PORT_5432_TCP_PORT; do - echo "$(date) - waiting for Postgres..." - sleep 1 -done - -# Migrate database, create initial admin user -mayan-edms.py initialsetup - -exec "$@" diff --git a/docs/releases/2.0.2.rst b/docs/releases/2.0.2.rst new file mode 100644 index 0000000000..a4378ba89e --- /dev/null +++ b/docs/releases/2.0.2.rst @@ -0,0 +1,94 @@ +=============================== +Mayan EDMS v2.0.2 release notes +=============================== + +Released: February 15, 2016 + +Welcome to Mayan EDMS v2.0.2 + +What's new +========== + +Fine tune "Update" checkbox from the metadata entry form +-------------------------------------------------------- +Previously the update checkbox was ignored during the metadata step of the +document upload wizard with the wizard always creating a metadata entry for the +new document even if the entry was left blank. The checkbox now controls whether +or not the wizard will store try to create the metadata entry. + +Fix empty optional lookup metadata fields behavior +-------------------------------------------------- +An edge case was fixed that caused validation to be executed for empty metadata +fields that had a value lookup list. + +Remove Docker files +------------------- +Included Docker and Docker Compose files were removed since the Mayan EDMS Docker +(https://gitlab.com/mayan-edms/mayan-edms-docker) repository is stable. + +Other changes +------------- +- Only extract validation error messages from ValidationError exception instances. +- Add 2 second delay to document version tests to workaround MySQL not storing + the millisecond part of the document version's timestamp. +- Install testing dependencies when installing development dependencies. +- Fix OCR API test for document version page OCR content. +- Move metadata form value validation to .clean() method. +- Add HTML tags stripping to the browser title generation template. + +Removals +-------- +* None + +Upgrading from a previous version +--------------------------------- + +Using PIP +~~~~~~~~~ + +Type in the console:: + + $ pip install -U mayan-edms + +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. + +Next upgrade/add the new requirements:: + + $ pip install --upgrade -r requirements.txt + +Common steps +~~~~~~~~~~~~ + +Migrate existing database schema with:: + + $ mayan-edms.py performupgrade + +Add new static media:: + + $ mayan-edms.py collectstatic --noinput + +The upgrade procedure is now complete. + + +Backward incompatible changes +============================= + +* None + +Bugs fixed or issues closed +=========================== + +* `GitLab issue #250 `_ Empty optional lookup metadata trigger validation error. + +.. _PyPI: https://pypi.python.org/pypi/mayan-edms/ diff --git a/docs/releases/index.rst b/docs/releases/index.rst index ba35ac60e1..ceabfccbb1 100644 --- a/docs/releases/index.rst +++ b/docs/releases/index.rst @@ -23,6 +23,8 @@ versions of the documentation contain the release notes for any later releases. :maxdepth: 1 2.0 + 2.0.1 + 2.0.2 1.0 series ---------- diff --git a/environment b/environment deleted file mode 100644 index 2ef2c9d6c2..0000000000 --- a/environment +++ /dev/null @@ -1,3 +0,0 @@ -POSTGRES_DB=mayan -POSTGRES_PASSWORD=mayanpassword -POSTGRES_USER=mayan diff --git a/mayan/__init__.py b/mayan/__init__.py index f2ebf34dfa..80a146098f 100644 --- a/mayan/__init__.py +++ b/mayan/__init__.py @@ -1,8 +1,8 @@ from __future__ import unicode_literals __title__ = 'Mayan EDMS' -__version__ = '2.0.1' -__build__ = 0x020001 +__version__ = '2.0.2' +__build__ = 0x020002 __author__ = 'Roberto Rosario' __author_email__ = 'roberto.rosario@mayan-edms.com' __description__ = 'Free Open Source Electronic Document Management System' diff --git a/mayan/apps/appearance/templates/appearance/calculate_form_title.html b/mayan/apps/appearance/templates/appearance/calculate_form_title.html index da6f1c075a..e27204e32c 100644 --- a/mayan/apps/appearance/templates/appearance/calculate_form_title.html +++ b/mayan/apps/appearance/templates/appearance/calculate_form_title.html @@ -1,7 +1,7 @@ {% load i18n %} {% if title %} - {{ title }} + {{ title|striptags }} {% else %} {% if read_only %} {% blocktrans %}Details for: {{ object }}{% endblocktrans %} diff --git a/mayan/apps/appearance/templates/appearance/generic_wizard.html b/mayan/apps/appearance/templates/appearance/generic_wizard.html index 58e35cc735..b3fe60da99 100644 --- a/mayan/apps/appearance/templates/appearance/generic_wizard.html +++ b/mayan/apps/appearance/templates/appearance/generic_wizard.html @@ -2,6 +2,8 @@ {% load i18n %} +{% block title %}{% include 'appearance/calculate_form_title.html' %}{% endblock %} + {% block content %}

{% include 'appearance/calculate_form_title.html' %}


diff --git a/mayan/apps/documents/tests/test_links.py b/mayan/apps/documents/tests/test_links.py index 34ce90a01d..44e168ee90 100644 --- a/mayan/apps/documents/tests/test_links.py +++ b/mayan/apps/documents/tests/test_links.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals +import time + from django.core.files import File from django.core.urlresolvers import reverse @@ -37,6 +39,10 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase): self.assertEqual(resolved_link, None) def test_document_version_revert_link_with_permission(self): + # Needed by MySQL as milliseconds value is not store in timestamp + # field + time.sleep(2) + with open(TEST_SMALL_DOCUMENT_PATH) as file_object: self.document.new_version(file_object=File(file_object)) diff --git a/mayan/apps/documents/tests/test_models.py b/mayan/apps/documents/tests/test_models.py index 0e844013b6..52945f03f1 100644 --- a/mayan/apps/documents/tests/test_models.py +++ b/mayan/apps/documents/tests/test_models.py @@ -85,8 +85,8 @@ class DocumentTestCase(TestCase): def test_auto_trashing(self): """ - Test document type trashing policies. Documents are moved to the trash, - x amount of time after being uploaded + Test document type trashing policies. Documents are moved to the + trash, x amount of time after being uploaded """ self.document_type.trash_time_period = 1 @@ -94,7 +94,9 @@ class DocumentTestCase(TestCase): self.document_type.trash_time_unit = 'seconds' self.document_type.save() - time.sleep(1) + # Needed by MySQL as milliseconds value is not store in timestamp + # field + time.sleep(2) self.assertEqual(Document.objects.count(), 1) self.assertEqual(DeletedDocument.objects.count(), 0) @@ -123,6 +125,8 @@ class DocumentTestCase(TestCase): self.assertEqual(Document.objects.count(), 0) self.assertEqual(DeletedDocument.objects.count(), 1) + # Needed by MySQL as milliseconds value is not store in timestamp + # field time.sleep(2) DocumentType.objects.check_delete_periods() @@ -216,8 +220,9 @@ class DocumentVersionTestCase(TestCase): def test_revert_version(self): self.assertEqual(self.document.versions.count(), 1) - # Needed by MySQL as milliseconds value is not store in timestamp field - time.sleep(1) + # Needed by MySQL as milliseconds value is not store in timestamp + # field + time.sleep(2) with open(TEST_DOCUMENT_PATH) as file_object: self.document.new_version( diff --git a/mayan/apps/metadata/forms.py b/mayan/apps/metadata/forms.py index df5e69bb6a..30660c5246 100644 --- a/mayan/apps/metadata/forms.py +++ b/mayan/apps/metadata/forms.py @@ -79,10 +79,14 @@ class MetadataForm(forms.Form): attrs={'readonly': 'readonly'} ) - def clean_value(self): - return self.metadata_type.validate_value( - document_type=self.document_type, value=self.cleaned_data['value'] - ) + def clean(self): + if self.cleaned_data.get('update') and hasattr(self, 'metadata_type'): + self.cleaned_data['value'] = self.metadata_type.validate_value( + document_type=self.document_type, + value=self.cleaned_data.get('value') + ) + + return self.cleaned_data MetadataFormSet = formset_factory(MetadataForm, extra=0) diff --git a/mayan/apps/metadata/models.py b/mayan/apps/metadata/models.py index 8b4784b27a..619a19aa4a 100644 --- a/mayan/apps/metadata/models.py +++ b/mayan/apps/metadata/models.py @@ -126,7 +126,7 @@ class MetadataType(models.Model): if self.lookup: lookup_options = self.get_lookup_values() - if value not in lookup_options: + if value and value not in lookup_options: raise ValidationError( _('Value is not one of the provided options.') ) diff --git a/mayan/apps/metadata/tests/test_models.py b/mayan/apps/metadata/tests/test_models.py index 4826a7c64a..3d96286a64 100644 --- a/mayan/apps/metadata/tests/test_models.py +++ b/mayan/apps/metadata/tests/test_models.py @@ -63,8 +63,9 @@ class MetadataTestCase(TestCase): self.document.metadata_value_of.test, TEST_DEFAULT_VALUE ) - def test_lookup(self): + def test_lookup_with_incorrect_value(self): self.metadata_type.lookup = TEST_LOOKUP_TEMPLATE + self.metadata_type.save() document_metadata = DocumentMetadata( document=self.document, metadata_type=self.metadata_type, @@ -76,8 +77,15 @@ class MetadataTestCase(TestCase): document_metadata.full_clean() document_metadata.save() - # Should not return error - document_metadata.value = TEST_CORRECT_LOOKUP_VALUE + def test_lookup_with_correct_value(self): + self.metadata_type.lookup = TEST_LOOKUP_TEMPLATE + self.metadata_type.save() + + document_metadata = DocumentMetadata( + document=self.document, metadata_type=self.metadata_type, + value=TEST_CORRECT_LOOKUP_VALUE + ) + document_metadata.full_clean() document_metadata.save() @@ -85,6 +93,22 @@ class MetadataTestCase(TestCase): self.document.metadata_value_of.test, TEST_CORRECT_LOOKUP_VALUE ) + def test_empty_optional_lookup(self): + """ + Checks for GitLab issue #250 + Empty optional lookup metadata trigger validation error + """ + + self.metadata_type.lookup = TEST_LOOKUP_TEMPLATE + self.metadata_type.save() + + document_metadata = DocumentMetadata( + document=self.document, metadata_type=self.metadata_type + ) + + document_metadata.full_clean() + document_metadata.save() + def test_validation(self): self.metadata_type.validation = TEST_DATE_VALIDATOR diff --git a/mayan/apps/metadata/views.py b/mayan/apps/metadata/views.py index 1ad80529ec..cd0ee7dd44 100644 --- a/mayan/apps/metadata/views.py +++ b/mayan/apps/metadata/views.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals from django.conf import settings from django.contrib import messages -from django.core.exceptions import PermissionDenied +from django.core.exceptions import PermissionDenied, ValidationError from django.core.urlresolvers import reverse, reverse_lazy from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render_to_response @@ -125,20 +125,24 @@ def metadata_edit(request, document_id=None, document_id_list=None): except Exception as exception: errors.append(exception) - if errors: - for error in errors: - if settings.DEBUG: - raise + for error in errors: + if settings.DEBUG: + raise + else: + if isinstance(error, ValidationError): + exception_message = ', '.join(error.messages) else: - messages.error( - request, _( - 'Error editing metadata for document: ' - '%(document)s; %(exception)s.' - ) % { - 'document': document, - 'exception': ', '.join(exception.messages) - } - ) + exception_message = unicode(error) + + messages.error( + request, _( + 'Error editing metadata for document: ' + '%(document)s; %(exception)s.' + ) % { + 'document': document, + 'exception': exception_message + } + ) else: messages.success( request, diff --git a/mayan/apps/ocr/tests/test_api.py b/mayan/apps/ocr/tests/test_api.py index e6649853df..76044ce15f 100644 --- a/mayan/apps/ocr/tests/test_api.py +++ b/mayan/apps/ocr/tests/test_api.py @@ -71,11 +71,11 @@ class OCRAPITestCase(APITestCase): self.assertTrue('Mayan EDMS Documentation' in content) - def test_get_document_version_content(self): + def test_get_document_version_page_content(self): response = self.client.get( reverse( 'rest_api:document-page-content-view', - args=(self.document.latest_version.pk,) + args=(self.document.latest_version.pages.first().pk,) ), ) diff --git a/mayan/apps/sources/wizards.py b/mayan/apps/sources/wizards.py index 97f00befda..bd239e4381 100644 --- a/mayan/apps/sources/wizards.py +++ b/mayan/apps/sources/wizards.py @@ -104,8 +104,9 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView): try: for identifier, metadata in enumerate(self.get_cleaned_data_for_step(STEP_METADATA)): - query_dict['metadata%s_id' % identifier] = metadata['id'] - query_dict['metadata%s_value' % identifier] = metadata['value'] + if metadata.get('update'): + query_dict['metadata%s_id' % identifier] = metadata['id'] + query_dict['metadata%s_value' % identifier] = metadata['value'] except TypeError: pass diff --git a/requirements/development.txt b/requirements/development.txt index 1d17bfbf84..ac329961bb 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -11,3 +11,5 @@ ipython==4.0.3 transifex-client==0.11 wheel==0.26.0 + +-r testing-base.txt