Merge branch 'development'
@@ -4,4 +4,7 @@ source=
|
||||
omit=
|
||||
mayan/bin/mayan-edms.py
|
||||
mayan/wsgi.py
|
||||
mayan/settings/*
|
||||
tests.py
|
||||
mayan/apps/*/tests/*
|
||||
*migrations*
|
||||
|
||||
2
.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!docker
|
||||
6
.gitignore
vendored
@@ -7,7 +7,7 @@ settings_local.py
|
||||
/celerybeat-schedule
|
||||
document_storage/
|
||||
/misc/mayan.geany
|
||||
image_cache/
|
||||
mayan/media/document_cache/
|
||||
build/
|
||||
_build/
|
||||
gpg_home/
|
||||
@@ -22,3 +22,7 @@ static_collected/
|
||||
*egg-info*
|
||||
mayan/settings/local.py
|
||||
.vagrant
|
||||
.tox/
|
||||
coverage.xml
|
||||
.coverage.tox*
|
||||
htmlcov/
|
||||
|
||||
35
.gitlab-ci.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
image: python:2.7
|
||||
services:
|
||||
- mysql
|
||||
- postgres
|
||||
before_script:
|
||||
- apt-get update -qq
|
||||
- apt-get install -qq python-dev gcc tesseract-ocr tesseract-ocr-deu unpaper ghostscript libjpeg-dev libpng-dev libtiff-dev poppler-utils libreoffice
|
||||
variables:
|
||||
POSTGRES_DB: "mayan_edms"
|
||||
POSTGRES_PASSWORD: "postgres"
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: "mayan_edms"
|
||||
test:mysql:
|
||||
script:
|
||||
- pip install -r requirements/testing.txt
|
||||
- pip install -q mysql-python
|
||||
- apt-get install -qq mysql-client
|
||||
- mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD" -e "ALTER DATABASE $MYSQL_DATABASE CHARACTER SET utf8 COLLATE utf8_unicode_ci;"
|
||||
- coverage run manage.py runtests --settings=mayan.settings.testing.gitlab-ci.db_mysql --nomigrations
|
||||
- bash <(curl https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -t $CODECOV_TOKEN
|
||||
tags:
|
||||
- mysql
|
||||
test:postgres:
|
||||
script:
|
||||
- pip install -r requirements/testing.txt
|
||||
- pip install -q psycopg2
|
||||
- coverage run manage.py runtests --settings=mayan.settings.testing.gitlab-ci.db_postgres --nomigrations
|
||||
- bash <(curl https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -t $CODECOV_TOKEN
|
||||
tags:
|
||||
- postgres
|
||||
test:sqlite:
|
||||
script:
|
||||
- pip install -r requirements/testing.txt
|
||||
- coverage run manage.py runtests --settings=mayan.settings.testing.gitlab-ci --nomigrations
|
||||
- bash <(curl https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -t $CODECOV_TOKEN
|
||||
21
.magnum.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
language: python
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-dev gcc tesseract-ocr tesseract-ocr-deu unpaper ghostscript libjpeg-dev libpng-dev poppler-utils
|
||||
install:
|
||||
- pip install -r requirements/testing.txt
|
||||
- pip install -q mysql-python
|
||||
- pip install -q psycopg2
|
||||
before_script:
|
||||
- mysql -u root -e 'create database mayan_edms;'
|
||||
- psql -c 'create database mayan_edms;' -U postgres
|
||||
script:
|
||||
- export TEST_APPS="acls authentication django_gpg document_indexing document_signatures documents dynamic_search folders lock_manager ocr permissions sources tags"
|
||||
- coverage run manage.py test $TEST_APPS --settings=mayan.settings.testing.base
|
||||
- coverage run manage.py test $TEST_APPS --settings=mayan.settings.magnum.db_mysql
|
||||
- coverage run manage.py test $TEST_APPS --settings=mayan.settings.magnum.db_postgres
|
||||
after_script:
|
||||
- coveralls
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
11
.travis.yml
@@ -1,17 +1,14 @@
|
||||
language: python
|
||||
python:
|
||||
- 2.6
|
||||
- 2.7
|
||||
env:
|
||||
global:
|
||||
- TEST_APPS="document_indexing documents dynamic_search lock_manager document_signatures folders ocr sources tags"
|
||||
matrix:
|
||||
- DB=mysql
|
||||
- DB=postgres
|
||||
- DB=sqlite
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-dev gcc tesseract-ocr unpaper ghostscript libjpeg-dev libpng-dev poppler-utils
|
||||
- sudo apt-get install -qq python-dev gcc tesseract-ocr tesseract-ocr-deu unpaper ghostscript libjpeg-dev libpng-dev poppler-utils libreoffice
|
||||
install:
|
||||
- "pip install -r requirements/testing.txt"
|
||||
- if [[ $DB == mysql ]]; then pip install -q mysql-python; fi
|
||||
@@ -20,9 +17,9 @@ before_script:
|
||||
- mysql -e 'create database mayan_edms;'
|
||||
- psql -c 'create database mayan_edms;' -U postgres
|
||||
script:
|
||||
- if [[ $DB == mysql ]]; then coverage run manage.py test $TEST_APPS --settings=mayan.settings.travis.db_mysql; fi
|
||||
- if [[ $DB == postgres ]]; then coverage run manage.py test $TEST_APPS --settings=mayan.settings.travis.db_postgres; fi
|
||||
- if [[ $DB == sqlite ]]; then coverage run manage.py test $TEST_APPS --settings=mayan.settings.travis.base; fi
|
||||
- if [[ $DB == mysql ]]; then coverage run manage.py runtests --settings=mayan.settings.testing.travis.db_mysql --nomigrations; fi
|
||||
- if [[ $DB == postgres ]]; then coverage run manage.py runtests --settings=mayan.settings.testing.travis.db_postgres --nomigrations; fi
|
||||
- if [[ $DB == sqlite ]]; then coverage run manage.py runtests --settings=mayan.settings.testing.base --nomigrations; fi
|
||||
after_success:
|
||||
- coveralls
|
||||
branches:
|
||||
|
||||
112
.tx/config
@@ -1,178 +1,188 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[mayan-edms.apps-acls]
|
||||
[mayan-edms.acls-2-0]
|
||||
file_filter = mayan/apps/acls/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/acls/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-checkouts]
|
||||
[mayan-edms.appearance-2-0]
|
||||
file_filter = mayan/apps/appearance/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/appearance/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.authentication-2-0]
|
||||
file_filter = mayan/apps/authentication/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/authentication/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.checkouts-2-0]
|
||||
file_filter = mayan/apps/checkouts/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/checkouts/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-common]
|
||||
[mayan-edms.common-2-0]
|
||||
file_filter = mayan/apps/common/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/common/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-converter]
|
||||
[mayan-edms.converter-2-0]
|
||||
file_filter = mayan/apps/converter/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/converter/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-django_gpg]
|
||||
[mayan-edms.django_gpg-2-0]
|
||||
file_filter = mayan/apps/django_gpg/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/django_gpg/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-documents]
|
||||
[mayan-edms.documents-2-0]
|
||||
file_filter = mayan/apps/documents/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/documents/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-document_comments]
|
||||
[mayan-edms.document_comments-2-0]
|
||||
file_filter = mayan/apps/document_comments/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_comments/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-document_indexing]
|
||||
[mayan-edms.document_indexing-2-0]
|
||||
file_filter = mayan/apps/document_indexing/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_indexing/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-document_signatures]
|
||||
[mayan-edms.document_signatures-2-0]
|
||||
file_filter = mayan/apps/document_signatures/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_signatures/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-document_states]
|
||||
[mayan-edms.document_states-2-0]
|
||||
file_filter = mayan/apps/document_states/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_states/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-dynamic_search]
|
||||
[mayan-edms.dynamic_search-2-0]
|
||||
file_filter = mayan/apps/dynamic_search/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/dynamic_search/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-events]
|
||||
[mayan-edms.events-2-0]
|
||||
file_filter = mayan/apps/events/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/events/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-folders]
|
||||
[mayan-edms.folders-2-0]
|
||||
file_filter = mayan/apps/folders/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/folders/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-installation]
|
||||
[mayan-edms.installation-2-0]
|
||||
file_filter = mayan/apps/installation/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/installation/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-linking]
|
||||
[mayan-edms.linking-2-0]
|
||||
file_filter = mayan/apps/linking/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/linking/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-mailer]
|
||||
[mayan-edms.lock_manager-2-0]
|
||||
file_filter = mayan/apps/lock_manager/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/lock_manager/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.mailer-2-0]
|
||||
file_filter = mayan/apps/mailer/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/mailer/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-main]
|
||||
file_filter = mayan/apps/main/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/main/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-metadata]
|
||||
[mayan-edms.metadata-2-0]
|
||||
file_filter = mayan/apps/metadata/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/metadata/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-navigation]
|
||||
[mayan-edms.mirroring-2-0]
|
||||
file_filter = mayan/apps/mirroring/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/mirroring/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.navigation-2-0]
|
||||
file_filter = mayan/apps/navigation/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/navigation/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-ocr]
|
||||
[mayan-edms.ocr-2-0]
|
||||
file_filter = mayan/apps/ocr/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/ocr/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-permissions]
|
||||
[mayan-edms.permissions-2-0]
|
||||
file_filter = mayan/apps/permissions/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/permissions/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-project_setup]
|
||||
file_filter = mayan/apps/project_setup/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/project_setup/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-project_tools]
|
||||
file_filter = mayan/apps/project_tools/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/project_tools/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-rest_api]
|
||||
[mayan-edms.rest_api-2-0]
|
||||
file_filter = mayan/apps/rest_api/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/rest_api/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-smart_settings]
|
||||
[mayan-edms.smart_settings-2-0]
|
||||
file_filter = mayan/apps/smart_settings/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/smart_settings/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-statistics]
|
||||
file_filter = mayan/apps/statistics/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/statistics/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-sources]
|
||||
[mayan-edms.sources-2-0]
|
||||
file_filter = mayan/apps/sources/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/sources/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-tags]
|
||||
[mayan-edms.statistics-2-0]
|
||||
file_filter = mayan/apps/statistics/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/statistics/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.storage-2-0]
|
||||
file_filter = mayan/apps/storage/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/storage/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.tags-2-0]
|
||||
file_filter = mayan/apps/tags/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/tags/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.apps-user_management]
|
||||
[mayan-edms.user_management-2-0]
|
||||
file_filter = mayan/apps/user_management/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/user_management/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
|
||||
|
||||
40
Dockerfile
Normal file
@@ -0,0 +1,40 @@
|
||||
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"]
|
||||
60
HISTORY.rst
@@ -1,3 +1,58 @@
|
||||
2.0 (2015-10-xx)
|
||||
================
|
||||
|
||||
- New source homepage: https://gitlab.com/mayan-edms/mayan-edms
|
||||
- Update to Django 1.7
|
||||
- New Bootstrap Frontend UI
|
||||
- Easier theming and rebranding
|
||||
- Improved page navigation interface
|
||||
- Menu reorganization
|
||||
- Removal of famfam icon set
|
||||
- Improved document preview generation
|
||||
- Document submission for OCR changed to POST
|
||||
- New YAML based settings system
|
||||
- Removal of auto admin creation as separate app
|
||||
- Removal of dependencies
|
||||
- ACL system refactor
|
||||
- Object access control inheritance
|
||||
- Removal of anonymous user support
|
||||
- Metadata validators refactor
|
||||
- Trash can support
|
||||
- Retention policies
|
||||
- Support for sharing indexes as FUSE filesystems
|
||||
- Clickable preview images titles
|
||||
- Removal of eval
|
||||
- Smarter OCR, per page parsing or OCR fallback
|
||||
- Improve failure tolerance (not all Operational Errors are critical now)
|
||||
- RGB tags
|
||||
- Default document type and default document source
|
||||
- Link unbinding
|
||||
- Statistics refactor
|
||||
- Apps merge
|
||||
- New signals
|
||||
- Test improvements
|
||||
- Indexes recalculation after document creation too
|
||||
- Upgrade command
|
||||
- OCR data moved to ocr app from documents app
|
||||
- New internal document creation workflow return a document stub
|
||||
- Auto console debug logging during development and info during production
|
||||
- New class based and menu based navigation system
|
||||
- New class based transformations
|
||||
- Usage of Font Awesome icons set
|
||||
- Management command to remove obsolete permissions: `purgepermissions`
|
||||
- Normalization of 'title' and 'name' fields to 'label'
|
||||
- Improved API, now at version 1
|
||||
- Invert page title/project name order in browser title
|
||||
- Django's class based views pagination
|
||||
- Reduction of text strings
|
||||
- Removal of the CombinedSource class
|
||||
- Removal of default class ACLs
|
||||
- Removal of the ImageMagick and GraphicsMagick converter backends
|
||||
- Remove support for applying roles to new users automatically
|
||||
- Removal of the DOCUMENT_RESTRICTIONS_OVERRIDE permission
|
||||
- Removed the page_label field
|
||||
|
||||
|
||||
1.1.1 (2015-05-21)
|
||||
==================
|
||||
|
||||
@@ -41,9 +96,6 @@
|
||||
- More technical documentation
|
||||
|
||||
|
||||
For a full changelog and release notes go to: http://mayan.readthedocs.org/en/latest/releases/1.1.html
|
||||
|
||||
|
||||
1.0 (2014-08-27)
|
||||
================
|
||||
|
||||
@@ -63,5 +115,3 @@ For a full changelog and release notes go to: http://mayan.readthedocs.org/en/la
|
||||
- License change, Mayan EDMS in now licensed under the Apache 2.0 License
|
||||
- PyPI package, Mayan EDMS in now available on PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
- New REST API
|
||||
|
||||
For a full changelog and release notes go to: http://mayan.readthedocs.org/en/latest/releases/1.0.html
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
include README.rst LICENSE HISTORY.rst
|
||||
recursive-include mayan README *.txt *.html *.css *.ico *.png *.jpg *.js *.po *.mo *.ttf
|
||||
global-exclude mayan/settings/local.py mayan/settings/travis/* settings_local.* mayan.sqlite* db.sqlite* mayan/media gpg_home document_storage image_cache
|
||||
recursive-include mayan *.txt *.html *.css *.ico *.png *.jpg *.js *.po *.mo *.ttf *.woff *.woff2 LICENSE
|
||||
global-exclude mayan/settings/local.py mayan/settings/travis/* mayan/media/*
|
||||
|
||||
27
README.rst
@@ -1,15 +1,7 @@
|
||||
|Build Status| |Coverage Status| |PyPI badge| |Installs badge| |License badge| |Wheel badge|
|
||||
|Build Status| |Coverage badge| |PyPI badge| |Installs badge| |License badge|
|
||||
|
||||
|Logo|
|
||||
|
||||
|
||||
Notice: This project is being migrated to GitLab: https://gitlab.com/mayan-edms/mayan-edms. This repository will be removed once all tickets are closed.
|
||||
|
||||
.. image:: https://badges.gitter.im/Join%20Chat.svg
|
||||
:alt: Join the chat at https://gitter.im/mayan-edms/mayan-edms
|
||||
:target: https://gitter.im/mayan-edms/mayan-edms?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
@@ -59,7 +51,7 @@ Contribute
|
||||
- Fork `the repository`_ on GitHub to start making your changes to the **development** branch (or branch off of it).
|
||||
- Write a test which shows that the bug was fixed or that the feature works as expected.
|
||||
- Add yourself to the `contributors file`_.
|
||||
- Send a pull request
|
||||
- Send a merge request.
|
||||
|
||||
|
||||
.. _Website: http://www.mayan-edms.com
|
||||
@@ -69,20 +61,19 @@ Contribute
|
||||
.. _Mailing list (via Google Groups): http://groups.google.com/group/mayan-edms
|
||||
.. _Apache 2.0 License: https://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
.. _`the repository`: http://github.com/mayan-edms/mayan-edms
|
||||
.. _`contributors file`: https://github.com/mayan-edms/mayan-edms/blob/master/docs/topics/contributors.rst
|
||||
.. _`contributors file`: https://github.com/mayan-edms/mayan-edms/blob/development/docs/topics/contributors.rst
|
||||
|
||||
.. |Build Status| image:: http://img.shields.io/travis/mayan-edms/mayan-edms/master.svg?style=flat
|
||||
:target: https://travis-ci.org/mayan-edms/mayan-edms
|
||||
.. |Coverage Status| image:: http://img.shields.io/coveralls/mayan-edms/mayan-edms/master.svg?style=flat
|
||||
:target: https://coveralls.io/r/mayan-edms/mayan-edms?branch=master
|
||||
.. |Logo| image:: https://github.com/mayan-edms/mayan-edms/raw/master/docs/_static/mayan_logo.png
|
||||
.. |Animation| image:: https://github.com/mayan-edms/mayan-edms/raw/master/docs/_static/overview.gif
|
||||
.. |Build Status| image:: https://gitlab.com/ci/projects/6169/status.png?ref=development
|
||||
:target: https://gitlab.com/ci/projects/6169?ref=development
|
||||
.. |Logo| image:: https://github.com/mayan-edms/mayan-edms/raw/development/docs/_static/mayan_logo.png
|
||||
.. |Animation| image:: https://github.com/mayan-edms/mayan-edms/raw/development/docs/_static/overview.gif
|
||||
.. |Installs badge| image:: http://img.shields.io/pypi/dm/mayan-edms.svg?style=flat
|
||||
:target: https://crate.io/packages/mayan-edms/
|
||||
.. |PyPI badge| image:: http://img.shields.io/pypi/v/mayan-edms.svg?style=flat
|
||||
:target: http://badge.fury.io/py/mayan-edms
|
||||
.. |Wheel badge| image:: http://img.shields.io/badge/wheel-yes-green.svg?style=flat
|
||||
.. |License badge| image:: http://img.shields.io/badge/license-Apache%202.0-green.svg?style=flat
|
||||
.. |Analytics| image:: https://ga-beacon.appspot.com/UA-52965619-2/mayan-edms/readme?pixel
|
||||
.. |Coverage badge| image:: https://codecov.io/gitlab/mayan-edms/mayan-edms/coverage.svg?branch=development
|
||||
:target: https://codecov.io/gitlab/mayan-edms/mayan-edms?branch=development
|
||||
|
||||
|Analytics|
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<VirtualHost *:80>
|
||||
# Uncomment if libapache2-mod-xsendfile is installed
|
||||
# XSendFile On
|
||||
# XSendFileAllowAbove On
|
||||
ServerName mayan.yoursite.com
|
||||
ServerAdmin admin@yoursite.com
|
||||
DocumentRoot /var/www/mayan-edms
|
||||
WSGIScriptAlias / /var/www/mayan-edms/mayan/mayan-edms.wsgi
|
||||
|
||||
<Directory /var/www/mayan-edms>
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
Alias /static /var/www/mayan-edms/media/static
|
||||
<Location "/static">
|
||||
SetHandler None
|
||||
</Location>
|
||||
</VirtualHost>
|
||||
@@ -1,14 +0,0 @@
|
||||
# sample wsgi file for usage with apache webserver
|
||||
# mayan installation in a virtualenv /opt/mayan/venv
|
||||
# apache deployment in /var/www/mayan-edms
|
||||
import os
|
||||
import sys
|
||||
import site
|
||||
# set up python path to virtual environment
|
||||
site.addsitedir(‘/opt/mayan/venv/lib/python2.7/site-packages’)
|
||||
sys.path.append(‘/var/www/mayan-edms’)
|
||||
os.environ[‘PYTHON_EGG_CACHE’]=’/var/www/django/cache’
|
||||
#django WSGI specifics
|
||||
From django.core.handlers.wsgi import WSGIHandler
|
||||
os.environ[‘DJANGO_SETTING_MODULE’] = ‘mayan.settings.production’
|
||||
application = WSGIHandler()
|
||||
@@ -1,31 +0,0 @@
|
||||
# invoke gunicorn using
|
||||
# 'gunicorn -c <this_file> <project_module>.wsgi:application
|
||||
import os
|
||||
import multiprocessing
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
bind = settings.GUNICORN_BIND
|
||||
workers = multiprocessing.cpu_count() * 2 + 1
|
||||
|
||||
preload_app = True
|
||||
|
||||
chdir = settings.BASE_DIR
|
||||
|
||||
user = settings.PROCESS_USER
|
||||
group = user
|
||||
|
||||
log_dir = os.path.join(
|
||||
os.path.dirname(settings.BASE_DIR), 'gunicorn_logs', settings.PROCESS_NAME)
|
||||
if not os.path.isdir(log_dir):
|
||||
os.makedirs(log_dir)
|
||||
import pwd
|
||||
import grp
|
||||
os.chown(log_dir,
|
||||
pwd.getpwnam(user).pw_uid,
|
||||
grp.getgrnam(group).gr_gid)
|
||||
|
||||
accesslog = os.path.join(log_dir, 'access.log')
|
||||
errorlog = os.path.join(log_dir, 'error.log')
|
||||
|
||||
proc_name = settings.PROCESS_NAME
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
DJANGO_SETTINGS_MODULE='mayan.settings.celery_redis' celery -A mayan worker -l DEBUG -Q checkouts,mailing,uploads,converter,ocr,tools,indexing,metadata -Ofair -B
|
||||
DJANGO_SETTINGS_MODULE='mayan.settings.celery_redis' celery -A mayan worker -l DEBUG -Ofair -B
|
||||
|
||||
22
contrib/nginx/mayan
Normal file
@@ -0,0 +1,22 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:/usr/share/mayan-edms/uwsgi.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/share/mayan-edms/mayan/media/static;
|
||||
expires 1h;
|
||||
}
|
||||
|
||||
location /favicon.ico {
|
||||
alias /usr/share/mayan-edms/mayan/media/static/appearance/images/favicon.ico;
|
||||
expires 1h;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80 ipv6only=on;
|
||||
server_name mayan;
|
||||
access_log /var/log/nginx/access_mayan.log;
|
||||
error_log /var/log/nginx/error_mayan.log;
|
||||
|
||||
location / {
|
||||
uwsgi_pass unix:///run/uwsgi/app/mayan/socket;
|
||||
include uwsgi_params;
|
||||
uwsgi_param UWSGI_SCHEME $scheme;
|
||||
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
root /srv/mayan/projects/mayan/mayan-edms/mayan/media/;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
upstream app_server {
|
||||
server unix:/var/tmp/filesystem.sock fail_timeout=0;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
access_log off;
|
||||
error_log /var/log/nginx/mayan-edms_error.log;
|
||||
|
||||
gzip on;
|
||||
gzip_http_version 1.0;
|
||||
gzip_comp_level 2;
|
||||
gzip_proxied any;
|
||||
gzip_min_length 1100;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_types text/plain text/css application/x-javascript text/xml
|
||||
application/xml application/xml+rss text/javascript;
|
||||
|
||||
# Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
|
||||
gzip_disable "MSIE [1-6].(?!.*SV1)";
|
||||
|
||||
# Set a vary header so downstream proxies don't send cached gzipped content to IE6
|
||||
gzip_vary on;
|
||||
|
||||
location / {
|
||||
client_max_body_size 2M;
|
||||
proxy_read_timeout 600s;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
if (!-f $request_filename) {
|
||||
proxy_pass http://app_server;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
location /static {
|
||||
expires 1h;
|
||||
alias /usr/share/mayan-edms/lib/python2.7/site-packages/mayan/media/static;
|
||||
}
|
||||
|
||||
location /favicon.ico {
|
||||
alias /usr/share/mayan-edms/lib/python2.7/site-packages/mayan/media/static/core/images/favicon.ico;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name mayan.crossculturalconsult.com www.mayan.crossculturalconsult.com;
|
||||
|
||||
access_log /var/log/nginx/mayan.crossculturalconsult.com.access.log;
|
||||
error_log /var/log/nginx/mayan.crossculturalconsult.com.error.log;
|
||||
root /home/mayan/production/;
|
||||
|
||||
location /static/ {
|
||||
alias /home/mayan/production/static_collected/;
|
||||
}
|
||||
|
||||
location /media/ {
|
||||
alias /home/mayan/production/media/;
|
||||
}
|
||||
|
||||
location = /favicon.ico {
|
||||
alias /home/mayan/production/media/favicon.ico;
|
||||
}
|
||||
|
||||
location = /robots.txt {
|
||||
alias /home/mayan/production/media/robots.txt;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8731;
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
client_max_body_size 10m;
|
||||
}
|
||||
allow all;
|
||||
}
|
||||
BIN
contrib/sample_documents/I18N_title_áéíóúüñÑ.png.zip
Normal file
BIN
contrib/sample_documents/compressed_documents.zip
Normal file
BIN
contrib/sample_documents/deu_website.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
contrib/sample_documents/hybrid_text_and_image.pdf
Normal file
BIN
contrib/sample_documents/multi_page.tiff
Normal file
BIN
contrib/sample_documents/simple_2_page_document.doc
Normal file
@@ -1,16 +1,26 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
import os
|
||||
import optparse
|
||||
|
||||
import sh
|
||||
|
||||
APP_LIST = ('acls', 'checkouts', 'common', 'converter', 'django_gpg', 'documents',
|
||||
'document_comments', 'document_indexing', 'document_signatures', 'document_states', 'dynamic_search',
|
||||
'events', 'folders', 'installation', 'linking', 'mailer', 'main', 'metadata', 'navigation',
|
||||
'ocr', 'permissions', 'project_setup', 'project_tools', 'rest_api',
|
||||
'smart_settings', 'sources', 'statistics', 'tags', 'user_management')
|
||||
LANGUAGE_LIST = ('ar', 'bg', 'bs_BA', 'da', 'de_CH', 'de_DE', 'en', 'es', 'fa', 'fr', 'hu', 'hr_HR', 'id', 'it', 'lv', 'nb', 'nl_NL', 'pl', 'pt', 'pt_BR', 'ro_RO', 'ru', 'sl_SI', 'sq', 'tr_TR', 'vi_VN', 'zh_CN', 'zh_TW')
|
||||
APP_LIST = (
|
||||
'acls', 'appearance', 'authentication', 'checkouts', 'common',
|
||||
'converter', 'django_gpg', 'document_comments', 'document_indexing',
|
||||
'document_signatures', 'document_states', 'documents', 'dynamic_search',
|
||||
'events', 'folders', 'installation', 'linking', 'lock_manager', 'mailer',
|
||||
'metadata', 'mirroring', 'navigation', 'ocr', 'permissions', 'rest_api',
|
||||
'smart_settings', 'sources', 'statistics', 'storage', 'tags',
|
||||
'user_management'
|
||||
)
|
||||
LANGUAGE_LIST = (
|
||||
'ar', 'bg', 'bs_BA', 'da', 'de_DE', 'en', 'es', 'fa', 'fr', 'hu', 'id',
|
||||
'it', 'nl_NL', 'pl', 'pt', 'pt_BR', 'ro_RO', 'ru', 'sl_SI', 'vi_VN',
|
||||
'zh_CN',
|
||||
)
|
||||
|
||||
# Inactive translations
|
||||
# 'de_CH', 'hr_HR', 'lv', 'nb', 'sq', 'tr_TR', 'zh_TW'
|
||||
|
||||
makemessages = sh.Command('django-admin.py')
|
||||
makemessages = makemessages.bake('makemessages')
|
||||
@@ -22,7 +32,9 @@ transifex_client = sh.Command('tx')
|
||||
pull_translations = transifex_client.bake('pull')
|
||||
push_translations = transifex_client.bake('push')
|
||||
|
||||
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'mayan'))
|
||||
BASE_DIR = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), '..', '..', 'mayan')
|
||||
)
|
||||
|
||||
|
||||
def process(command, app_list, language_list):
|
||||
@@ -55,12 +67,30 @@ def process(command, app_list, language_list):
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-m', '--make', help='create message sources file', dest='make', default=False, action='store_true')
|
||||
parser.add_option('-c', '--compile', help='compile message files', dest='compile', default=False, action='store_true')
|
||||
parser.add_option('-p', '--pull', help='pull translation files', dest='pull', default=False, action='store_true')
|
||||
parser.add_option('-u', '--push', help='push translation files', dest='push', default=False, action='store_true')
|
||||
parser.add_option('-a', '--app', help='specify which app to process', dest='app', action='store', metavar='appname')
|
||||
parser.add_option('-l', '--lang', help='specify which language to process', dest='lang', action='store', metavar='language')
|
||||
parser.add_option(
|
||||
'-m', '--make', help='create message sources file', dest='make',
|
||||
default=False, action='store_true'
|
||||
)
|
||||
parser.add_option(
|
||||
'-c', '--compile', help='compile message files', dest='compile',
|
||||
default=False, action='store_true'
|
||||
)
|
||||
parser.add_option(
|
||||
'-p', '--pull', help='pull translation files', dest='pull',
|
||||
default=False, action='store_true'
|
||||
)
|
||||
parser.add_option(
|
||||
'-u', '--push', help='push translation files', dest='push',
|
||||
default=False, action='store_true'
|
||||
)
|
||||
parser.add_option(
|
||||
'-a', '--app', help='specify which app to process', dest='app',
|
||||
action='store', metavar='appname'
|
||||
)
|
||||
parser.add_option(
|
||||
'-l', '--lang', help='specify which language to process', dest='lang',
|
||||
action='store', metavar='language'
|
||||
)
|
||||
(opts, args) = parser.parse_args()
|
||||
|
||||
if not opts.make and not opts.compile:
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[program:openoffice]
|
||||
command = /usr/lib/libreoffice/program/soffice.bin "-accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" -headless -nodefault -nofirststartwizard -nolockcheck -nologo -norestore
|
||||
stdout_logfile= /var/log/libreoffice-headless.log
|
||||
redirect_stderr = true
|
||||
autostart = true
|
||||
26
contrib/supervisor/mayan-celery.conf
Normal file
@@ -0,0 +1,26 @@
|
||||
[program:mayan-worker]
|
||||
command = /usr/share/mayan-edms/bin/python /usr/share/mayan-edms/bin/mayan-edms.py celery --settings=mayan.settings.production worker -Ofair -l ERROR
|
||||
directory = /usr/share/mayan-edms
|
||||
user = www-data
|
||||
stdout_logfile = /var/log/mayan/worker-stdout.log
|
||||
stderr_logfile = /var/log/mayan/worker-stderr.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
startsecs = 10
|
||||
stopwaitsecs = 10
|
||||
killasgroup = true
|
||||
priority = 998
|
||||
|
||||
[program:mayan-beat]
|
||||
command = /usr/share/mayan-edms/bin/python /usr/share/mayan-edms/bin/mayan-edms.py celery --settings=mayan.settings.production beat -l ERROR
|
||||
directory = /usr/share/mayan-edms
|
||||
user = www-data
|
||||
numprocs = 1
|
||||
stdout_logfile = /var/log/mayan/beat-stdout.log
|
||||
stderr_logfile = /var/log/mayan/beat-stderr.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
startsecs = 10
|
||||
stopwaitsecs = 1
|
||||
killasgroup = true
|
||||
priority = 998
|
||||
@@ -1,7 +0,0 @@
|
||||
[program:mayan-edms]
|
||||
command = /usr/share/mayan-edms/contrib/scripts/gunicorn_start.sh
|
||||
user = www-data
|
||||
autostart = true
|
||||
autorestart = true
|
||||
redirect_stderr = true
|
||||
|
||||
6
contrib/supervisor/mayan-uwsgi.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
[program:mayan-uwsgi]
|
||||
command = /usr/share/mayan-edms/bin/uwsgi --ini /usr/share/mayan-edms/uwsgi.ini
|
||||
user = root
|
||||
autostart = true
|
||||
autorestart = true
|
||||
redirect_stderr = true
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Run the gunicorn service
|
||||
|
||||
# Make sure we're in the right virtual env and location
|
||||
source /home/mayan/.virtualenvs/production/bin/activate
|
||||
source /home/mayan/.virtualenvs/production/bin/postactivate
|
||||
|
||||
cd /home/mayan/production
|
||||
|
||||
exec gunicorn -c /home/mayan/production/deploy/gunicorn.conf.py mayan.wsgi:application
|
||||
@@ -1,10 +0,0 @@
|
||||
start on started rc
|
||||
stop on stopped rc
|
||||
|
||||
respawn
|
||||
respawn limit 3 5
|
||||
|
||||
setuid mayan
|
||||
setgid mayan
|
||||
|
||||
exec /home/mayan/production/deploy/production/service_demon.sh
|
||||
@@ -1,14 +0,0 @@
|
||||
# Sample file for uswgi with mayan installed in a virtualenv mayan
|
||||
# with project directory mayan e.g. for use with nginx connecting via
|
||||
# local unix socket
|
||||
[uwsgi]
|
||||
#socket = 127.0.0.1:3031
|
||||
plugin = python
|
||||
chdir = /srv/mayan/projects/mayan/mayan-edms
|
||||
virtualenv = /srv/mayan/.virtualenvs/mayan
|
||||
env = DJANGO_SETTINGS_MODULE=mayan.settings.production
|
||||
module = django.core.handlers.wsgi:WSGIHandler()
|
||||
processes = 4
|
||||
threads = 2
|
||||
stats = :9191
|
||||
buffer-size=32768
|
||||
21
docker-compose.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
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
|
||||
10
docker/bin/run.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/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
|
||||
15
docker/conf/mayan/settings.py
Normal file
@@ -0,0 +1,15 @@
|
||||
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'))
|
||||
22
docker/conf/nginx/mayan-edms
Normal file
@@ -0,0 +1,22 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
14
docker/conf/uwsgi/uwsgi.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
[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
|
||||
17
docker/entrypoint.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/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 "$@"
|
||||
@@ -128,3 +128,6 @@ doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
livehtml:
|
||||
sphinx-autobuild -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
||||
BIN
docs/_static/api.png
vendored
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/_static/document_view.png
vendored
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
docs/_static/main.png
vendored
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/_static/overview.gif
vendored
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 628 KiB |
BIN
docs/_static/page_view.png
vendored
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
docs/_static/setup.png
vendored
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
docs/_static/statistics.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
docs/_static/tools.png
vendored
Normal file
|
After Width: | Height: | Size: 67 KiB |
2
docs/_templates/donate.html
vendored
@@ -1,3 +1,5 @@
|
||||
<script type="text/javascript" src="https://gumroad.com/js/gumroad.js"></script>
|
||||
<a href="https://gumroad.com/l/UNApl" class="gumroad-button">Buy Mayan EDMS</a>
|
||||
<h3>Donate</h3>
|
||||
<p>
|
||||
Help support further improvements and development by donating on: <a href="https://www.patreon.com/siloraptor">Patreon</a>
|
||||
|
||||
20
docs/conf.py
@@ -33,7 +33,12 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "_ext"))
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||
#extensions = ["djangodocs", "sphinx.ext.intersphinx"]
|
||||
extensions = ['djangodocs']
|
||||
extensions = ['djangodocs', 'sphinxcontrib.blockdiag']
|
||||
|
||||
blockdiag_antialias = True
|
||||
blockdiag_html_image_format = "SVG"
|
||||
blockdiag_latex_image_format = "PDF"
|
||||
blockdiag_tex_image_format = "PDF"
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -229,20 +234,19 @@ man_pages = [
|
||||
import alabaster
|
||||
|
||||
html_theme_path = [alabaster.get_path()]
|
||||
extensions = ['alabaster']
|
||||
extensions.append('alabaster')
|
||||
html_theme = 'alabaster'
|
||||
html_sidebars = {
|
||||
'**': [
|
||||
'about.html', 'navigation.html', 'searchbox.html', 'donate.html',
|
||||
'about.html', 'donate.html', 'navigation.html', 'searchbox.html',
|
||||
]
|
||||
}
|
||||
html_theme_options = {
|
||||
'description': 'Free Open Source Electronic Document Management System',
|
||||
'github_user': 'mayan-edms',
|
||||
'github_repo': 'mayan-edms',
|
||||
'travis_button': True,
|
||||
'description': mayan.__description__,
|
||||
'github_button': False,
|
||||
'travis_button': False,
|
||||
'gratipay_user': 'rosarior',
|
||||
'github_banner': True,
|
||||
'github_banner': False,
|
||||
}
|
||||
|
||||
html_logo = '_static/logo_pyramid_only.png'
|
||||
|
||||
@@ -10,31 +10,36 @@ and installing it from PyPI with the following commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo apt-get install libjpeg-dev libmagic1 libpng-dev libreoffice libtiff-dev gcc ghostscript gpgv python-dev python-virtualenv tesseract-ocr unpaper poppler-utils -y
|
||||
$ virtualenv venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install mayan-edms
|
||||
$ mayan-edms.py initialsetup
|
||||
$ mayan-edms.py runserver
|
||||
sudo apt-get install libjpeg-dev libmagic1 libpng-dev libreoffice libtiff-dev gcc ghostscript gpgv python-dev python-virtualenv tesseract-ocr unpaper poppler-utils -y
|
||||
virtualenv venv
|
||||
source venv/bin/activate
|
||||
pip install mayan-edms
|
||||
mayan-edms.py initialsetup
|
||||
mayan-edms.py runserver
|
||||
|
||||
Point your browser to 127.0.0.1:8000 and use the automatically created admin
|
||||
account.
|
||||
|
||||
.. image:: /_static/overview.gif
|
||||
:alt: Overview
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
Features <topics/features>
|
||||
Installation <topics/installation>
|
||||
Getting started <topics/getting_started>
|
||||
Deploying <topics/deploying>
|
||||
Release notes and upgrading <releases/index>
|
||||
Concepts <topics/index>
|
||||
Development <topics/development>
|
||||
App creation <topics/app_creation>
|
||||
Translations <topics/translations>
|
||||
Contributors <topics/contributors>
|
||||
Screenshots <topics/screenshots>
|
||||
Licensing <topics/license>
|
||||
FAQ <topics/faq>
|
||||
Contact <topics/contact>
|
||||
|
||||
|
||||
.. _Django: http://www.djangoproject.com/
|
||||
.. _Free Open Source: http://en.wikipedia.org/wiki/Open_source
|
||||
.. _Electronic Document Management System: https://en.wikipedia.org/wiki/Document_management_system
|
||||
|
||||
@@ -13,7 +13,7 @@ While bug fixes and minor feature were the focus for this release, some
|
||||
bigger changes were included because of their importance. The parsing of
|
||||
documents saw a complete rewrite being now class based and allows for more
|
||||
than one parser per mimetype with sequencial fallback. This provides the
|
||||
best text extraction on deployments where users have control over the
|
||||
best text extraction on deployments where users have control over the
|
||||
installation and basic extraction when deploying on the cloud or other
|
||||
environments where users don't have the ability to install OS level
|
||||
binaries.
|
||||
@@ -24,7 +24,7 @@ What's new in Mayan EDMS v0.12.1
|
||||
|
||||
Fabric file (fabfile)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
A Fabric file is included to help users not very familiar with Ubuntu,
|
||||
A Fabric file is included to help users not very familiar with Ubuntu,
|
||||
Python and Django install **Mayan EDMS**, or for system administrators
|
||||
looking to automate the install whether in local or remote systems.
|
||||
At the moment the fabfile will install **Mayan EDMS** in the same configurations
|
||||
@@ -36,10 +36,10 @@ the fabfile as more are tested.
|
||||
Documentation update
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The installation instructions were updated to include the installation of
|
||||
the libpng-dev and libjpeg-dev libraries as well as the installation of
|
||||
the libpng-dev and libjpeg-dev libraries as well as the installation of
|
||||
the poppler-utils package. An additional step to help users test their
|
||||
new installation of **Mayan EDMS** was also added.
|
||||
|
||||
|
||||
Translations
|
||||
~~~~~~~~~~~~
|
||||
The Italian translation has been synchronized with the source files at
|
||||
@@ -50,30 +50,30 @@ Usability improvements
|
||||
The index instance view now feature the same multi document action
|
||||
buttons (Submit to OCR, delete, download, etc) as the mail and recent
|
||||
document views.
|
||||
|
||||
|
||||
Better office document conversion
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
A new method of converting office documents has been implemented, this
|
||||
new method doesn't require the use of the command line utility ``UNOCONV``.
|
||||
If this new method proves to work better than previous solutions the use
|
||||
of ``UNOCONV`` may be deprecated in the future. The conversion method
|
||||
adds just one new configuration option: :setting:`CONVERTER_LIBREOFFICE_PATH`
|
||||
adds just one new configuration option: `CONVERTER_LIBREOFFICE_PATH`
|
||||
which defaults to '/usr/bin/libreoffice'.
|
||||
|
||||
Better PDF text parsing
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Brian E. submitted a patch to use the Poppler package pdftotext utility to
|
||||
extract text from PDF files. This is now the default method Mayan EDMS
|
||||
will execute to try to extract text from a PDF and failing that will
|
||||
will execute to try to extract text from a PDF and failing that will
|
||||
fallback to the previous method. This change add a new configuration
|
||||
option: :setting:`OCR_PDFTOTEXT_PATH` to specify the location of the ``pdftotext``
|
||||
option: `OCR_PDFTOTEXT_PATH` to specify the location of the ``pdftotext``
|
||||
executable, it defaults to '/usr/bin/pdftotext'. Be sure to install the
|
||||
``poppler-utils`` os package to take advantage of this new parser.
|
||||
|
||||
Changed defaults
|
||||
~~~~~~~~~~~~~~~~
|
||||
The OCR queue is now active by default when first created during the
|
||||
``syncdb`` phase and the :setting:`OCR_AUTOMATIC_OCR` option now defaults
|
||||
The OCR queue is now active by default when first created during the
|
||||
``syncdb`` phase and the `OCR_AUTOMATIC_OCR` option now defaults
|
||||
to ``True``. These two changes are made to reduce the steps required for
|
||||
new users to start enjoying the benefits of automatic text extraction from
|
||||
uploaded documents without having to read the documentation and have a more
|
||||
@@ -95,7 +95,7 @@ Install the ``poppler-utils`` package:
|
||||
* Ubuntu, Debian::
|
||||
|
||||
$ apt-get install -y poppler-utils
|
||||
|
||||
|
||||
* Fedora::
|
||||
|
||||
$ yum install -y poppler-utils
|
||||
@@ -112,5 +112,5 @@ Bugs fixed
|
||||
* Issue #25 "Office document conversion error"
|
||||
|
||||
Stuff removed
|
||||
=============
|
||||
=============
|
||||
* None
|
||||
|
||||
@@ -27,10 +27,10 @@ Smarter auto admin creation
|
||||
**Mayan EDMS** creates a administrator user during the
|
||||
database creation phase to reduce the amount of steps required for a
|
||||
functional install. The creation of this account is controlled by the configuration
|
||||
option :setting:`COMMON_AUTO_CREATE_ADMIN`, the username of the account is
|
||||
specified with the configuration option :setting:`COMMON_AUTO_ADMIN_USERNAME`
|
||||
and the password of this account by the option :setting:`COMMON_AUTO_ADMIN_PASSWORD`.
|
||||
Previously the :setting:`COMMON_AUTO_ADMIN_PASSWORD` defaulted to 'admin' which
|
||||
option `COMMON_AUTO_CREATE_ADMIN`, the username of the account is
|
||||
specified with the configuration option `COMMON_AUTO_ADMIN_USERNAME`
|
||||
and the password of this account by the option `COMMON_AUTO_ADMIN_PASSWORD`.
|
||||
Previously the `COMMON_AUTO_ADMIN_PASSWORD` defaulted to 'admin' which
|
||||
created an administrator account of username 'admin' with a password of
|
||||
'admin'. The new default is to randomize an initial password and show this password
|
||||
at the login screen until the administrator password is changed.
|
||||
|
||||
@@ -60,7 +60,7 @@ ACL support
|
||||
Anonymous user support
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
Anonymous user support is a two tier function, first is the addition of
|
||||
the :setting:`COMMON_ALLOW_ANONYMOUS_ACCESS` configuration option that
|
||||
the `COMMON_ALLOW_ANONYMOUS_ACCESS` configuration option that
|
||||
allows non authenticated user to browse all the pages of a **Mayan EDMS** installation.
|
||||
The second part of this support is the ability to assign permissions
|
||||
or individual access to objects to anonymous users.
|
||||
@@ -88,7 +88,7 @@ the download of several documents in a single compressed file.
|
||||
|
||||
Customizable GPG home directory
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Addition of the :setting:`SIGNATURES_GPG_HOME` configuration option to let
|
||||
Addition of the `SIGNATURES_GPG_HOME` configuration option to let
|
||||
administrators set **Mayan EDMS**'s GPG instance home directory, used to
|
||||
store keyrings and other GPG configuration files.
|
||||
|
||||
@@ -116,7 +116,7 @@ These populated trees can also be mirrored on the physical filesystem and shared
|
||||
using Samba or another filesharing server giving users a structured view
|
||||
of the documents contained within **Mayan EDMS** from the ``Indexes`` tab
|
||||
or from a mirrored index shared via the network. A new configuration option
|
||||
has been added, :setting:`DOCUMENT_INDEXING_FILESYSTEM_SERVING`, which maps
|
||||
has been added, `DOCUMENT_INDEXING_FILESYSTEM_SERVING`, which maps
|
||||
the index internal name with the physical directory where such index will be
|
||||
mirrored on disk.
|
||||
|
||||
@@ -226,6 +226,6 @@ Stuff removed
|
||||
* Configuration options removed:
|
||||
|
||||
* OCR_CACHE_URI
|
||||
* DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_PATH - Use the newest :setting:`DOCUMENT_INDEXING_FILESYSTEM_SERVING`
|
||||
* DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_ENABLE - Use the newest :setting:`DOCUMENT_INDEXING_FILESYSTEM_SERVING`
|
||||
* DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_PATH - Use the newest `DOCUMENT_INDEXING_FILESYSTEM_SERVING`
|
||||
* DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_ENABLE - Use the newest `DOCUMENT_INDEXING_FILESYSTEM_SERVING`
|
||||
|
||||
|
||||
508
docs/releases/2.0.rst
Normal file
@@ -17,8 +17,15 @@ Final releases
|
||||
Below are release notes through **Mayan EDMS** |version| and its minor releases. Newer
|
||||
versions of the documentation contain the release notes for any later releases.
|
||||
|
||||
2.0 series
|
||||
----------
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
2.0
|
||||
|
||||
1.0 series
|
||||
-----------
|
||||
----------
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
|
||||
73
docs/topics/acls.rst
Normal file
@@ -0,0 +1,73 @@
|
||||
====================
|
||||
Access control lists
|
||||
====================
|
||||
|
||||
Besides the permissions system explained in :doc:`permissions`, **Mayan EDMS**
|
||||
provides per object permission granting. This feature is used to grant a
|
||||
permission to a role, but this permission can only be executed for a limited
|
||||
number of objects (documents, folders, tags) instead of being effective
|
||||
system-wide.
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
document [ label = 'Document' ];
|
||||
role [ label = 'Role' ];
|
||||
permission [ label = 'Permission' ];
|
||||
|
||||
role -> document <- permission;
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
document [ label = '2015 Payroll report.txt', width=200 ];
|
||||
role [ label = 'Accountants' ];
|
||||
permission [ label = 'View document' ];
|
||||
|
||||
role -> document <- permission;
|
||||
}
|
||||
|
||||
In this scenario only users in groups belonging to the ``Accountants`` role
|
||||
would be able to view the ``2015 Payroll report.txt`` document.
|
||||
|
||||
Inherited access control
|
||||
========================
|
||||
|
||||
It is also possible to grant a permission to a role for a specific document type (:doc:`document_types`).
|
||||
Under this scheme all users in groups belonging to that role will inherit that
|
||||
permission for all documents of that type.
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
document_type [ label = 'Document type' ];
|
||||
role [ label = 'Role' ];
|
||||
permission [ label = 'Permission' ];
|
||||
|
||||
role -> document_type <- permission;
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
document_type [ label = 'Payroll reports', width=200 ];
|
||||
role [ label = 'Accountants' ];
|
||||
permission [ label = 'View document' ];
|
||||
|
||||
role -> document_type <- permission;
|
||||
}
|
||||
|
||||
The role ``Accountants`` is given the permission ``document view`` for the
|
||||
document type ``Payroll reports``. Now all users in groups belonging to the
|
||||
``Accountants`` role can view all documents of the type ``Payroll reports``
|
||||
without needing to have that permissions granted for each particular
|
||||
``Payroll reports`` type document.
|
||||
|
||||
If access control for the ``Payroll reports`` documents needs to be updated it
|
||||
only needs to be done for the document type and not for each document of the type
|
||||
``Payroll reports``.
|
||||
143
docs/topics/app_creation.rst
Normal file
@@ -0,0 +1,143 @@
|
||||
============
|
||||
App creation
|
||||
============
|
||||
|
||||
**Mayan EDMS** apps are essentially Django app with some extra code to register
|
||||
navigation, permissions and other relationships.
|
||||
|
||||
|
||||
App modules
|
||||
===========
|
||||
|
||||
- __init__.py
|
||||
|
||||
Should be empty if possible. No initialization code should be here, use the
|
||||
ready() method of the MayanAppConfig class in the apps.py module.
|
||||
|
||||
- admin.py
|
||||
|
||||
Standard Django app module to define how models are to be presented in the
|
||||
admin interface.
|
||||
|
||||
- api_views.py
|
||||
|
||||
REST API views go here. **Mayan EDMS** uses Django REST Framework API view
|
||||
classes.
|
||||
|
||||
- apps.py
|
||||
|
||||
Contains the MayanAppConfig subclass as required by Django 1.7 and up. This
|
||||
is a place to define the app name and translatable verbose name as well as
|
||||
code to be execute when the modules of the app are ready.
|
||||
|
||||
- classes.py
|
||||
|
||||
Hold python classes to be used internally or externally. Any class defined by
|
||||
the app that is not a model.
|
||||
|
||||
- events.py
|
||||
|
||||
Define event class instances that are later committed to a log by custom
|
||||
code.
|
||||
|
||||
- exceptions.py
|
||||
|
||||
Custom exceptions defined by the app.
|
||||
|
||||
- fields.py
|
||||
|
||||
Place any custom form field classed you define here.
|
||||
|
||||
- forms.py
|
||||
|
||||
Standard Django app module that hold custom form classes.
|
||||
|
||||
- handlers.py
|
||||
|
||||
Contains the signal handlers, functions that will process a given signal
|
||||
emitted from this or other apps. Connect the handler functions to the
|
||||
corresponding signal in the ready() method of the MayanAppConfig subclass in
|
||||
apps.py
|
||||
|
||||
- links.py
|
||||
|
||||
Defines the links to be used by the app. Import only from the navigation app
|
||||
and the local permissions.py file.
|
||||
|
||||
- literals.py
|
||||
|
||||
Stores magic numbers, module choices (if static), settings defaults, and
|
||||
constants. Should contain all capital case variables. Must not import from
|
||||
any other module.
|
||||
|
||||
- managers.py
|
||||
|
||||
Standard Django app module that hold custom model managers. These act as
|
||||
model class method to performs actions in a series of model instances or
|
||||
utilitarian actions on external models instances.
|
||||
|
||||
- models.py
|
||||
|
||||
Standard Django app module that defines ORM persistent data schema.
|
||||
|
||||
- permissions.py
|
||||
|
||||
Defines the permissions to be used to validate user access by links and views.
|
||||
Imports only from the permissions app. Link or view conditions such as
|
||||
testing for is_staff or is_super_user flag are defined in this same module.
|
||||
|
||||
- runtime.py
|
||||
|
||||
Use this module when you need the same instance of a class for the entire app.
|
||||
This module acts as a shared memory space for the other modules of the app or
|
||||
other apps.
|
||||
|
||||
- serializers.py
|
||||
|
||||
Hold Django REST Framework serializers used by the api_views.py module.
|
||||
|
||||
- settings.py
|
||||
|
||||
Define the configuration settings instances that the app will use.
|
||||
|
||||
- signals.py
|
||||
|
||||
Any custom defined signal goes here.
|
||||
|
||||
- statistics.py
|
||||
|
||||
Provides functions that will compute any sort of statistical information on
|
||||
the app’s data.
|
||||
|
||||
- tasks.py
|
||||
|
||||
Code to be execute in the background or as an out-of-process action.
|
||||
|
||||
- tests/ directory
|
||||
|
||||
Hold test modules. There should be one test_*.py module for each aspect being
|
||||
tested, examples: test_api.py, test_views.py, test_parsers.py, test_permissions.py
|
||||
Any shared constant data used by the tests should be added to tests/literals.py
|
||||
|
||||
- utils.py
|
||||
|
||||
Holds utilitarian code that doesn't fit on any other app module or that is
|
||||
used by several modules in the app. Anything used internally by the app that
|
||||
is not a class or a literal (should be as little as possible)
|
||||
|
||||
- widgets.py
|
||||
|
||||
HTML widgets go here. This should be the only place with presentation
|
||||
directives in the app (aside the templates).
|
||||
|
||||
|
||||
Views
|
||||
=====
|
||||
|
||||
The module common.generics provides custom generic class based views to be used.
|
||||
The basic views used to create, edit, view and delete objects in **Mayan EDMS**
|
||||
are: SingleObjectCreateView, SingleObjectDetailView, SingleObjectEditView,
|
||||
and SingleObjectListView
|
||||
|
||||
These views handle aspects relating to view permissions, object permissions,
|
||||
post action redirection and template context generation.
|
||||
14
docs/topics/checkouts.rst
Normal file
@@ -0,0 +1,14 @@
|
||||
=========
|
||||
Checkouts
|
||||
=========
|
||||
|
||||
Checkouts are a way to block certain accesses or actions of a document for a
|
||||
period of time.
|
||||
|
||||
An user can choose to checkout a document to work on an update and block new
|
||||
versions of that document to be uploaded by other users. Document are checked
|
||||
out for a certain amount of time and if not manually checked in by the original
|
||||
user, will be checked in automatically by the system.
|
||||
|
||||
To be able to check in documents that were checked out by other users, the
|
||||
permission 'Forcefully check in documents' is required.
|
||||
@@ -12,11 +12,12 @@ Mailing list
|
||||
------------
|
||||
|
||||
Search for information in the `archives of the mayan-edms mailing list`_, or
|
||||
`post a question`_. If you prefer news servers, use the gateway provided by Gmane_.
|
||||
`post a question`_. If you prefer news servers, use the gateway provided by
|
||||
Gmane_.
|
||||
|
||||
**Mayan EDMS** community developers do their best to reply to basic questions.
|
||||
Be sure to check the list archives as it may already containt the answers to your
|
||||
questions.
|
||||
Be sure to check the list archives as it may already containt the answers to
|
||||
your questions.
|
||||
|
||||
Twitter
|
||||
-------
|
||||
@@ -34,5 +35,5 @@ Report bugs with **Mayan EDMS** or search existing ones using Github's `ticket t
|
||||
|
||||
.. _archives of the mayan-edms mailing list: http://groups.google.com/group/mayan-edms/
|
||||
.. _post a question: http://groups.google.com/group/mayan-edms
|
||||
.. _ticket tracker: https://github.com/mayan-edms/mayan-edms/issues
|
||||
.. _ticket tracker: https://gitlab.com/mayan-edms/mayan-edms/issues
|
||||
.. _Gmane: http://news.gmane.org/gmane.comp.python.django.mayan-edms
|
||||
|
||||
@@ -8,7 +8,8 @@ Contributors
|
||||
How to contribute?
|
||||
------------------
|
||||
|
||||
You can help further the development of **Mayan EDMS** by testing, reporting bugs, submitting documentation or code patches.
|
||||
You can help further the development of **Mayan EDMS** by testing, reporting
|
||||
bugs, submitting documentation or code patches.
|
||||
|
||||
Lead developer
|
||||
--------------
|
||||
@@ -20,8 +21,10 @@ Contributors (in alphabetical order)
|
||||
* Bertrand Bordage (https://github.com/BertrandBordage)
|
||||
* Brian E (brian@realize.org)
|
||||
* David Herring (https://github.com/abadger1406)
|
||||
* Emlyn Clay (https://github.com/EmlynC)
|
||||
* Jens Kadenbach (https://github.com/audax)
|
||||
* Kolmar Kafran
|
||||
* Helga Carrero
|
||||
* IHLeanne (https://github.com/IHLeanne)
|
||||
* Iliya Georgiev (ikgeorgiev@gmail.com)
|
||||
* Lars Kruse (devel@sumpfralle.de)
|
||||
|
||||
191
docs/topics/deploying.rst
Normal file
@@ -0,0 +1,191 @@
|
||||
=========
|
||||
Deploying
|
||||
=========
|
||||
|
||||
OS "bare metal"
|
||||
===============
|
||||
|
||||
Like other Django based projects **Mayan EDMS** can be deployed in a wide variety
|
||||
of ways. The method provided below is only a bare minimum example.
|
||||
These instructions are independent of the instructions mentioned in the
|
||||
:doc:`installation` chapter but assume you have already made a test install to
|
||||
test the compatibility of your operating system. These instruction are for
|
||||
Ubuntu 15.04.
|
||||
|
||||
Switch to superuser::
|
||||
|
||||
sudo -i
|
||||
|
||||
Install all system dependencies::
|
||||
|
||||
apt-get install nginx supervisor redis-server postgresql \
|
||||
libpq-dev libjpeg-dev libmagic1 libpng-dev libreoffice \
|
||||
libtiff-dev gcc ghostscript gpgv python-dev python-virtualenv \
|
||||
tesseract-ocr unpaper poppler-utils -y
|
||||
|
||||
Change the directory to where the project will be deployed::
|
||||
|
||||
cd /usr/share
|
||||
|
||||
Create the Python virtual environment for the installation::
|
||||
|
||||
virtualenv mayan-edms
|
||||
|
||||
Activate virtual env::
|
||||
|
||||
source mayan-edms/bin/activate
|
||||
|
||||
Install Mayan EDMS::
|
||||
|
||||
pip install mayan-edms
|
||||
|
||||
Install the Python client for PostgreSQL, Redis, and uWSGI::
|
||||
|
||||
pip install psycopg2 redis uwsgi
|
||||
|
||||
Create the database for installation::
|
||||
|
||||
sudo -u postgres createuser -P mayan (provide password)
|
||||
sudo -u postgres createdb -O mayan mayan
|
||||
|
||||
Create the directories for the logs::
|
||||
|
||||
mkdir /var/log/mayan
|
||||
|
||||
Change the current directory to be the one of the installation::
|
||||
|
||||
cd mayan-edms
|
||||
|
||||
Make a convenience symlink::
|
||||
|
||||
ln -s lib/python2.7/site-packages/mayan .
|
||||
|
||||
Create an initial settings file::
|
||||
|
||||
mayan-edms.py createsettings
|
||||
|
||||
Update the ``mayan/settings/local.py`` file::
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': 'mayan',
|
||||
'USER': 'mayan',
|
||||
'PASSWORD': '<password used when creating postgreSQL user>',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '5432',
|
||||
}
|
||||
}
|
||||
|
||||
BROKER_URL = 'redis://127.0.0.1:6379/0'
|
||||
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0'
|
||||
|
||||
Migrate the database or initialize the project::
|
||||
|
||||
mayan-edms.py initialsetup
|
||||
|
||||
Disable the default NGINX site::
|
||||
|
||||
rm /etc/nginx/sites-enabled/default
|
||||
|
||||
Create the NGINX site file for Mayan EDMS, ``/etc/nginx/site-available/mayan``::
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:/usr/share/mayan-edms/uwsgi.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/share/mayan-edms/mayan/media/static;
|
||||
expires 1h;
|
||||
}
|
||||
|
||||
location /favicon.ico {
|
||||
alias /usr/share/mayan-edms/mayan/media/static/appearance/images/favicon.ico;
|
||||
expires 1h;
|
||||
}
|
||||
}
|
||||
|
||||
Enable the NGINX site for Mayan EDMS::
|
||||
|
||||
ln -s /etc/nginx/sites-available/mayan /etc/nginx/sites-enabled/
|
||||
|
||||
Create the supervisor file for the uWSGI process, ``/etc/supervisor/conf.d/mayan-uwsgi.conf``::
|
||||
|
||||
[program:mayan-uwsgi]
|
||||
command = /usr/share/mayan-edms/bin/uwsgi --ini /usr/share/mayan-edms/uwsgi.ini
|
||||
user = root
|
||||
autostart = true
|
||||
autorestart = true
|
||||
redirect_stderr = true
|
||||
|
||||
Create the supervisor file for the Celery worker, ``/etc/supervisor/conf.d/mayan-celery.conf``::
|
||||
|
||||
[program:mayan-worker]
|
||||
command = /usr/share/mayan-edms/bin/python /usr/share/mayan-edms/bin/mayan-edms.py celery --settings=mayan.settings.production worker -Ofair -l ERROR
|
||||
directory = /usr/share/mayan-edms
|
||||
user = www-data
|
||||
stdout_logfile = /var/log/mayan/worker-stdout.log
|
||||
stderr_logfile = /var/log/mayan/worker-stderr.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
startsecs = 10
|
||||
stopwaitsecs = 10
|
||||
killasgroup = true
|
||||
priority = 998
|
||||
|
||||
[program:mayan-beat]
|
||||
command = /usr/share/mayan-edms/bin/python /usr/share/mayan-edms/bin/mayan-edms.py celery --settings=mayan.settings.production beat -l ERROR
|
||||
directory = /usr/share/mayan-edms
|
||||
user = www-data
|
||||
numprocs = 1
|
||||
stdout_logfile = /var/log/mayan/beat-stdout.log
|
||||
stderr_logfile = /var/log/mayan/beat-stderr.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
startsecs = 10
|
||||
stopwaitsecs = 1
|
||||
killasgroup = true
|
||||
priority = 998
|
||||
|
||||
Collect the static files::
|
||||
|
||||
mayan-edms.py collectstatic --noinput
|
||||
|
||||
Make the installation directory readable and writable by the webserver user::
|
||||
|
||||
chown www-data:www-data /usr/share/mayan-edms -R
|
||||
|
||||
Restart the services::
|
||||
|
||||
/etc/init.d/nginx restart
|
||||
/etc/init.d/supervisor restart
|
||||
|
||||
Docker
|
||||
======
|
||||
|
||||
Deploy the Mayan EDMS Docker image::
|
||||
|
||||
docker run --name postgres -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword -v /var/lib/postgresql/data -d postgres
|
||||
docker run --name redis -d redis
|
||||
docker run --name mayan-edms -p 80:80 --link postgres:postgres --link redis:redis -e POSTGRES_DB=mayan -e POSTGRES_USER=mayan -e POSTGRES_PASSWORD=mysecretpassword -v /usr/local/lib/python2.7/dist-packages/mayan/media -d mayanedms/monolithic
|
||||
|
||||
After the **Mayan EDMS** container finishes initializing (about 5 minutes), it will
|
||||
be available by browsing to http://127.0.0.1
|
||||
|
||||
Docker Compose
|
||||
==============
|
||||
|
||||
Launch the entire stack using::
|
||||
|
||||
docker-compose -f docker-compose.yaml up -d
|
||||
|
||||
After the **Mayan EDMS** container finishes initializing (about 5 minutes), it will
|
||||
be available by browsing to http://127.0.0.1
|
||||
@@ -6,31 +6,41 @@ Development
|
||||
**Mayan EDMS** is under active development, and contributions are welcome.
|
||||
|
||||
If you have a feature request, suggestion or bug report, please open a new
|
||||
issue on the `GitHub issue tracker`_. To submit patches, please send a pull
|
||||
request on GitHub_. Make sure to add yourself to the :ref:`contributors` file.
|
||||
issue on the `GitLab issue tracker`_. To submit patches, please send a pull
|
||||
request on GitLab_. Make sure to add yourself to the :ref:`contributors` file.
|
||||
|
||||
.. _GitHub: https://github.com/mayan-edms/mayan-edms/
|
||||
.. _`GitHub issue tracker`: https://github.com/mayan-edms/mayan-edms/issues
|
||||
.. _GitLab: https://gitlab.com/mayan-edms/mayan-edms/
|
||||
.. _`GitLab issue tracker`: https://gitlab.com/mayan-edms/mayan-edms/issues
|
||||
|
||||
|
||||
Project philosophies
|
||||
--------------------
|
||||
|
||||
How to think about **Mayan EDMS** when doing changes or adding new features, why things are the way they are in **Mayan EDMS**.
|
||||
How to think about **Mayan EDMS** when doing changes or adding new features,
|
||||
why things are the way they are in **Mayan EDMS**.
|
||||
|
||||
- Functionality must be as market/sector independent as possible, code for the 95% of use cases.
|
||||
- Each user must be able to configure and customize it to their needs after install.
|
||||
- Abstract as much as possible, each app must be an expert in just one thing, for other things they should use the API/classes/functions of other apps.
|
||||
- Assume as little as possible about anything outside the project (hardware, OS, storage).
|
||||
- Provide Python based abstraction so that a default install runs with a single step.
|
||||
- Functionality must be as market/sector independent as possible, code for the
|
||||
95% of use cases.
|
||||
- Each user must be able to configure and customize it to their needs after
|
||||
install.
|
||||
- Abstract as much as possible, each app must be an expert in just one thing,
|
||||
for other things they should use the API/classes/functions of other apps.
|
||||
- Assume as little as possible about anything outside the project
|
||||
(hardware, OS, storage).
|
||||
- Provide Python based abstraction so that a default install runs with a single
|
||||
step.
|
||||
- No hard dependencies on binaries unless there is no other choice.
|
||||
- Provide “drivers” or switchable backends to allow users to fine tune the installation.
|
||||
- Call to binaries only when there is no other choice or the Python choices are not viable/mature/efficient.
|
||||
- Each app is as independent and self contained as possible. Exceptions, the basic requirements: navigation, permissions, common, main.
|
||||
- If an app is meant to be used by more than one other app it should be as generic as possible in regard to the project and another app will bridge the functionality.
|
||||
- Provide “drivers” or switchable backends to allow users to fine tune the
|
||||
installation.
|
||||
- Call to binaries only when there is no other choice or the Python choices are
|
||||
not viable/mature/efficient.
|
||||
- Each app is as independent and self contained as possible. Exceptions, the
|
||||
basic requirements: navigation, permissions, common, main.
|
||||
- If an app is meant to be used by more than one other app it should be as
|
||||
generic as possible in regard to the project and another app will bridge the functionality.
|
||||
|
||||
- Example: the acls app is app agnostic, document_acls connects the acls app with the documents app.
|
||||
- Example: since indexing (document_indexing) only applies to documents, the app is specialized and dependant on the documents app.
|
||||
- Example: since indexing (document_indexing) only applies to documents, the
|
||||
app is specialized and depends on the documents app.
|
||||
|
||||
|
||||
Coding conventions
|
||||
@@ -93,7 +103,9 @@ Example:
|
||||
)
|
||||
from .models import Index, IndexInstanceNode, DocumentRenameCount
|
||||
|
||||
All local app module imports are in relative form, local app module name is to be referenced as little as possible, unless required by a specific feature, trick, restriction, ie: Runtime modification of the module's attributes.
|
||||
All local app module imports are in relative form, local app module name is to
|
||||
be referenced as little as possible, unless required by a specific feature,
|
||||
trick, restriction, ie: Runtime modification of the module's attributes.
|
||||
|
||||
Incorrect:
|
||||
|
||||
@@ -113,12 +125,18 @@ Correct:
|
||||
|
||||
Dependencies
|
||||
~~~~~~~~~~~~
|
||||
**Mayan EDMS** apps follow a hierarchical model of dependency. Apps import from their parents or siblings, never from their children. Think plugins. A parent app must never assume anything about a possible existing child app. The documents app and the Document model are the basic entities they must never import anything else. The common and main apps are the base apps.
|
||||
**Mayan EDMS** apps follow a hierarchical model of dependency. Apps import from
|
||||
their parents or siblings, never from their children. Think plugins. A parent
|
||||
app must never assume anything about a possible existing child app. The
|
||||
documents app and the Document model are the basic entities they must never
|
||||
import anything else. The common and main apps are the base apps.
|
||||
|
||||
|
||||
Variables
|
||||
~~~~~~~~~
|
||||
Naming of variables should follow a Major to Minor convention, usually including the purpose of the variable as the first piece of the name, using underscores as spaces. camelCase is not used in **Mayan EDMS**.
|
||||
Naming of variables should follow a Major to Minor convention, usually
|
||||
including the purpose of the variable as the first piece of the name, using
|
||||
underscores as spaces. camelCase is not used in **Mayan EDMS**.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -153,125 +171,46 @@ Classes:
|
||||
|
||||
Strings
|
||||
~~~~~~~
|
||||
Quotation character used in **Mayan EDMS** for strings is the single quote. Double quote is used for multiline comments or HTML markup.
|
||||
Quotation character used in **Mayan EDMS** for strings is the single quote.
|
||||
Double quote is used for multiple line comments or HTML markup.
|
||||
|
||||
Migrations
|
||||
~~~~~~~~~~
|
||||
Migrations should do only one thing (eg: either create a table, move data to a
|
||||
new table or remove an old table) to aid retrying on failure.
|
||||
|
||||
General
|
||||
~~~~~~~
|
||||
|
||||
Code should appear in their modules in alphabetic order or in their order of importance if it makes more sense for the specific application.
|
||||
This makes visual scanning easier on modules with a large number of imports, views or classes.
|
||||
Class methods that return a value should be prepended with a ``get_`` to differentiate from an object’s properties.
|
||||
When a variable refers to a file it should be named as follows:
|
||||
Code should appear in their modules in alphabetic order or in their order of
|
||||
importance if it makes more sense for the specific application. This makes
|
||||
visual scanning easier on modules with a large number of imports, views or
|
||||
classes. Class methods that return a value should be pretended with a
|
||||
``get_`` to differentiate from an object’s properties. When a variable refers
|
||||
to a file it should be named as follows:
|
||||
|
||||
- filename: The file’s name and extension only.
|
||||
- filepath: The entire path to the file including the filename.
|
||||
- path: A path to a directory.
|
||||
|
||||
Flash messages should end with a period as applicable for the language.
|
||||
Only exception is when the tail of the message contains an exceptions message as passed directly from the exception object.
|
||||
|
||||
App anatomy
|
||||
~~~~~~~~~~~
|
||||
|
||||
- __init__.py
|
||||
|
||||
- Generic initialization code (should be empty if possible)
|
||||
|
||||
- api.py
|
||||
|
||||
- File to hold functions that are meant to be used by external apps.
|
||||
- Interfaces meant to be used by other apps that are not models or classes.
|
||||
|
||||
- classes.py
|
||||
|
||||
- Hold python classes to be used internally or externally.
|
||||
- Any class defined by the app that is not a model.
|
||||
|
||||
- diagnostics.py
|
||||
|
||||
- Define functions that will return the state of the data of an app.
|
||||
- Does not fixes the problems only finds them.
|
||||
|
||||
- events.py
|
||||
|
||||
- Define history type events
|
||||
|
||||
- exceptions.py
|
||||
|
||||
- Exceptions defined by the app
|
||||
|
||||
- icons.py
|
||||
|
||||
- Defines the icons to be used by the links and views of the app.
|
||||
- Imports from the icons app only.
|
||||
|
||||
- links.py
|
||||
|
||||
- Defines the links to be used by the app.
|
||||
- Import only from the navigation app and the local icons.py file.
|
||||
|
||||
- literals.py
|
||||
|
||||
- Stores magic numbers, module choices (if static), settings defaults, and constants.
|
||||
- Should contain all capital case variables.
|
||||
- Must not import from any other module.
|
||||
|
||||
- maintenance.py
|
||||
|
||||
- Hold functions that the user may run periodically to fix errors in the app’s data.
|
||||
|
||||
- permissions.py
|
||||
|
||||
- Defines the permissions to be used by links and views to validate access.
|
||||
- Imports only from permissions app.
|
||||
- Link or view conditions such as testing for staff or super admin status are defined in the same file.
|
||||
|
||||
- statistics.py
|
||||
|
||||
- Provides functions that will computer any sort of statistical information on the app’s data.
|
||||
|
||||
- tasks.py
|
||||
|
||||
- Code to be execute as in the background or a as an process-of-process action.
|
||||
|
||||
- utils.py
|
||||
|
||||
- Hold utilitarian code that doesn't fit on any other app file or that is used by several files in the app.
|
||||
- Anything used internally by the app that is not a class or a literal (should be as little as possible)
|
||||
|
||||
Views behavior
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- Delete views:
|
||||
|
||||
- Redirect to object list view if one object is deleted.
|
||||
- Redirect to previous view if many are deleted.
|
||||
- Previous view equals:
|
||||
|
||||
- previous variable in POST or
|
||||
- previous variable in GET or
|
||||
- request.META.HTTP_REFERER or
|
||||
- object list view or
|
||||
- 'home' view
|
||||
- fallback to ‘/’
|
||||
- if previous equal same view then previous should equal object list view or ‘/’
|
||||
|
||||
Only exception is when the tail of the message contains an exceptions message
|
||||
as passed directly from the exception object.
|
||||
|
||||
Source Control
|
||||
--------------
|
||||
|
||||
**Mayan EDMS** source is controlled with Git_.
|
||||
|
||||
The project is publicly accessible, hosted and can be cloned from **GitHub** using::
|
||||
The project is publicly accessible, hosted and can be cloned from **GitLab** using::
|
||||
|
||||
$ git clone git://github.com/mayan-edms/mayan-edms.git
|
||||
git clone https://gitlab.com/mayan-edms/mayan-edms.git
|
||||
|
||||
|
||||
Git branch structure
|
||||
--------------------
|
||||
|
||||
**Mayan EDMS** follows the model layout by Vincent Driessen in his `Successful Git Branching Model`_ blog post. Git-flow_ is a great tool for managing the repository in this way.
|
||||
**Mayan EDMS** follows a simplified model layout based on Vincent Driessen's
|
||||
`Successful Git Branching Model`_ blog post.
|
||||
|
||||
``develop``
|
||||
The "next release" branch, likely unstable.
|
||||
@@ -283,46 +222,46 @@ Git branch structure
|
||||
Released versions.
|
||||
|
||||
|
||||
Each release is tagged and available for download on the Downloads_ section of the **Mayan EDMS** repository on GitHub_.
|
||||
Each release is tagged separately.
|
||||
|
||||
When submitting patches, please place your code in its own ``feature/`` branch prior to opening a pull request on GitHub_.
|
||||
When submitting patches, please place your code in its own ``feature/`` branch
|
||||
prior to opening a Merge Request on GitLab_.
|
||||
|
||||
.. _Git: http://git-scm.org
|
||||
.. _`Successful Git Branching Model`: http://nvie.com/posts/a-successful-git-branching-model/
|
||||
.. _git-flow: https://github.com/nvie/gitflow
|
||||
.. _Downloads: https://github.com/mayan-edms/mayan-edms/archives/master
|
||||
|
||||
|
||||
Steps to deploy a development version
|
||||
-------------------------------------
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://github.com/mayan-edms/mayan-edms.git
|
||||
$ cd mayan-edms
|
||||
$ git checkout development
|
||||
$ virtualenv venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install -r requirements.txt
|
||||
$ ./manage.py initialsetup
|
||||
$ ./manage.py runserver
|
||||
git clone https://gitlab.com/mayan-edms/mayan-edms.git
|
||||
cd mayan-edms
|
||||
git checkout development
|
||||
virtualenv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
./manage.py initialsetup
|
||||
./manage.py runserver
|
||||
|
||||
|
||||
Setting up a development version using Vagrant
|
||||
----------------------------------------------
|
||||
Make sure you have Vagrant and a provider properly installed as per https://docs.vagrantup.com/v2/installation/index.html
|
||||
Make sure you have Vagrant and a provider properly installed as per
|
||||
https://docs.vagrantup.com/v2/installation/index.html
|
||||
|
||||
Start and provision a machine using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ vagrant up
|
||||
vagrant up
|
||||
|
||||
To launch a standalone development server
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ vagrant ssh
|
||||
vagrant ssh
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ cd ~/mayan-edms/
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ source venv/bin/activate
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ ./manage.py runserver 0.0.0.0:8000
|
||||
@@ -332,7 +271,7 @@ To launch a development server with a celery worker and Redis as broker
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ vagrant ssh
|
||||
vagrant ssh
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ cd ~/mayan-edms/
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ source venv/bin/activate
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ ./manage.py runserver 0.0.0.0:8000 --settings=mayan.settings.celery_redis
|
||||
@@ -341,7 +280,7 @@ Then on a separate console launch a celery worker from the same provisioned Vagr
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ vagrant ssh
|
||||
vagrant ssh
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ cd ~/mayan-edms/
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ source venv/bin/activate
|
||||
vagrant@vagrant-ubuntu-trusty-32:~$ DJANGO_SETTINGS_MODULE='mayan.settings.celery_redis' celery -A mayan worker -l DEBUG -Q checkouts,mailing,uploads,converter,ocr,tools,indexing,metadata -Ofair -B
|
||||
@@ -349,22 +288,22 @@ Then on a separate console launch a celery worker from the same provisioned Vagr
|
||||
|
||||
Contributing changes
|
||||
--------------------
|
||||
Once your have created and committed some new code or feature, submit a Pull Request.
|
||||
Be sure to merge with mayan-edms/development before doing a pull request so that patches
|
||||
apply as cleanly as possible. If there are no conflicts, Pull Requests can be merged
|
||||
directly from Github otherwise a manual command line merge has to be done and
|
||||
your patches might take longer to get merged.
|
||||
|
||||
For more information on how to create Pull Request read: https://help.github.com/articles/using-pull-requests
|
||||
or the quick version: https://help.github.com/articles/creating-a-pull-request
|
||||
Once your have created and committed some new code or feature, submit a Pull
|
||||
Request. Be sure to merge with the development branch before doing a Pull
|
||||
Request so that patches apply as cleanly as possible. If there are no conflicts,
|
||||
Merge Requests can be merged directly from the website UI otherwise a manual
|
||||
command line merge has to be done and your patches might take longer to get
|
||||
merged.
|
||||
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
**Mayan EDMS** makes extensive use of Django's new `logging capabilities`_.
|
||||
To enable debug logging for the ``documents`` app for example add the following
|
||||
lines to your ``settings_local.py`` file::
|
||||
By default debug logging for all apps is turned on. If you wish to customize
|
||||
how logging is managed turn off automatic logging by setting
|
||||
`COMMON_AUTO_LOGGING` to ``False`` and add the following lines to your
|
||||
``settings/local.py`` file::
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
@@ -418,76 +357,69 @@ Likewise, to see the debug output of the ``tags`` app, just add the following in
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
**Mayan EDMS**'s documentation is written in `reStructured Text`_ format.
|
||||
The documentation is written in `reStructured Text`_ format, processed with
|
||||
Sphinx_, and resides in the ``docs`` directory. In order to build it, you will
|
||||
first need to install the documentation editing dependencies with::
|
||||
|
||||
The documentation lives in the ``docs`` directory. In order to build it, you will first need to install Sphinx_. ::
|
||||
pip install -r requirements/documentation.txt
|
||||
|
||||
$ pip install sphinx
|
||||
Then, to build an HTML version of the documentation, run the following command
|
||||
from the **docs** directory::
|
||||
|
||||
make livehtml
|
||||
|
||||
Then, to build an HTML version of the documentation, simply run the following from the **docs** directory::
|
||||
The generated documentation can be viewed by browsing to http://127.0.0.1:8000
|
||||
or by browsing to the ``docs/_build/html`` directory.
|
||||
|
||||
$ make html
|
||||
|
||||
Your ``docs/_build/html`` directory will then contain an HTML version of the documentation, ready for publication on most web servers.
|
||||
|
||||
You can also generate the documentation in formats other than HTML.
|
||||
You can also generate the documentation in formats other than HTML. Consult the
|
||||
Sphinx_ documentation for more details.
|
||||
|
||||
.. _`reStructured Text`: http://docutils.sourceforge.net/rst.html
|
||||
.. _Sphinx: http://sphinx.pocoo.org
|
||||
|
||||
|
||||
Translations
|
||||
------------
|
||||
|
||||
Translations are handled online via the **Transifex** website: https://www.transifex.com/projects/p/mayan-edms/.
|
||||
To create a translation team for a new language or contribute to an already
|
||||
existing language translation, create a **Transifex** account and contact
|
||||
the team coordinator of the respective language in which you are interested.
|
||||
|
||||
|
||||
Installable package
|
||||
-------------------
|
||||
|
||||
Source file package
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is the sequence of step I use to produce an installable package:
|
||||
This is the sequence of step used to produce an installable package:
|
||||
|
||||
1. Make sure there are no lingering packages from previous attempts::
|
||||
|
||||
$ rm dist -R
|
||||
rm dist -R
|
||||
|
||||
2. Generate the packaged version (will produce dist/mayan-edms-1.1.1.tar.gz)::
|
||||
2. Generate the packaged version (will produce dist/mayan-edms-x.y.z.tar.gz)::
|
||||
|
||||
$ python setup.py sdist
|
||||
python setup.py sdist
|
||||
|
||||
3. Do a test install::
|
||||
|
||||
$ cd /tmp
|
||||
$ virtualenv venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install <path of the Git repository>/dist/mayan-edms-1.1.1.tar.gz
|
||||
$ mayan-edms.py initialsetup
|
||||
$ mayan-edms.py runserver
|
||||
cd /tmp
|
||||
virtualenv venv
|
||||
source venv/bin/activate
|
||||
pip install <path of the Git repository>/dist/mayan-edms-x.y.z.tar.gz
|
||||
mayan-edms.py initialsetup
|
||||
mayan-edms.py runserver
|
||||
|
||||
|
||||
Wheel package
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
1. Install wheel::
|
||||
1. Install the development requirements::
|
||||
|
||||
$ pip install wheel
|
||||
$ pip install -r requirements/development.txt
|
||||
|
||||
2. Create wheel package using the source file package (Until issue #99 of wheel is fixed: https://bitbucket.org/pypa/wheel/issue/99/cannot-exclude-directory)::
|
||||
|
||||
$ pip wheel --no-index --no-deps --wheel-dir dist dist/mayan-edms-1.1.1.tar.gz
|
||||
$ pip wheel --no-index --no-deps --wheel-dir dist dist/mayan-edms-x.y.z.tar.gz
|
||||
|
||||
3. Do a test install::
|
||||
|
||||
$ cd /tmp
|
||||
$ virtualenv venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install <path of the Git repository>/dist/mayan_edms-1.1.1-py2-none-any.whl
|
||||
$ pip install <path of the Git repository>/dist/mayan_edms-x.y.z-py2-none-any.whl
|
||||
$ mayan-edms.py initialsetup
|
||||
$ mayan-edms.py runserver
|
||||
|
||||
17
docs/topics/document_types.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
==============
|
||||
Document types
|
||||
==============
|
||||
|
||||
The basic unit of data in **Mayan EDMS** is the ``document type``. A document
|
||||
type can be interpreted also as a document category, a document class, or a
|
||||
document template. Document types need to be created before documents can be
|
||||
uploaded. It is not possible to upload documents without assigning them a
|
||||
document type. Examples of document type: **invoices**, **blueprints**,
|
||||
**receipts**.
|
||||
|
||||
Settings and attributes are applied to document types and documents will
|
||||
inherit those settings and attributes based on the document type they were
|
||||
assigned when uploaded into **Mayan EDMS**. A document can only be of one
|
||||
type at a given moment, but if needed, the type of a document can be changed.
|
||||
Upon changing its type, the document will lose its previous settings and
|
||||
attributes, and will inherit the settings and attributes of its new type.
|
||||
@@ -4,7 +4,8 @@ Features
|
||||
|
||||
* :doc:`Document versioning <../topics/versioning>`.
|
||||
|
||||
* Store many versions of the same document, download or revert to a previous version.
|
||||
* Store many versions of the same document, download or revert to a previous
|
||||
version.
|
||||
|
||||
* :doc:`Electronic signature verification <../topics/signatures>`.
|
||||
|
||||
@@ -18,39 +19,48 @@ Features
|
||||
|
||||
* Office document format support.
|
||||
|
||||
* **Mayan EDMS** can detect the presence of Libre Office and use it to support word processing files, spreadsheets and presentations.
|
||||
* **Mayan EDMS** can detect the presence of Libre Office and use it to support
|
||||
word processing files, spreadsheets and presentations.
|
||||
|
||||
* User defined metadata fields.
|
||||
|
||||
* Several metadata fields can be matched to a document type as per technical, legal or structural requirements such as the `Dublin core`_.
|
||||
* Several metadata fields can be matched to a document type as per technical,
|
||||
legal or structural requirements such as the `Dublin core`_.
|
||||
|
||||
* Dynamic default values for metadata.
|
||||
|
||||
* Metadata fields can have an initial value, which can be static or determined by an user provided Python code snippet.
|
||||
* Metadata fields can have an initial value, which can be static or determined
|
||||
by an user provided template code snippet.
|
||||
|
||||
* Documents can be uploaded from different sources.
|
||||
|
||||
* Local file or server side file uploads, multifunctional copier, or even via email.
|
||||
* Local file or server side file uploads, multifunctional copier, or even via
|
||||
email.
|
||||
|
||||
* Batch upload many documents with the same metadata.
|
||||
|
||||
* Clone a document's metadata for speedier uploads and eliminate repetitive data entry.
|
||||
* Clone a document's metadata for speedier uploads and eliminate repetitive
|
||||
data entry.
|
||||
|
||||
* Previews for a great deal of image formats.
|
||||
* Previews for many file formats.
|
||||
|
||||
* **Mayan EDMS** provides different file conversion backends with different levels of functionality and requirements to adapt to different deployment environments.
|
||||
* **Mayan EDMS** provides image preview generation for many popular file
|
||||
formats.
|
||||
|
||||
* Full text searching.
|
||||
|
||||
* Documents can be searched by their text content, their metadata or any other file attribute such as name, extension, etc.
|
||||
* Documents can be searched by their text content, their metadata or any other
|
||||
file attribute such as name, extension, etc.
|
||||
|
||||
* Configurable document grouping.
|
||||
|
||||
* Automatic linking of documents based on metadata values or document properties.
|
||||
* Automatic linking of documents based on metadata values or document
|
||||
properties.
|
||||
|
||||
* :doc:`Roles support <../topics/permissions>`.
|
||||
|
||||
* It is possible to create an unlimited amount of different roles not being restricted to the traditional admin, operator, guest paradigm.
|
||||
* It is possible to create an unlimited amount of different roles not being
|
||||
restricted to the traditional admin, operator, guest paradigm.
|
||||
|
||||
* :doc:`Fine grained permissions system <../topics/permissions>`.
|
||||
|
||||
@@ -62,20 +72,25 @@ Features
|
||||
|
||||
* Automatic OCR processing.
|
||||
|
||||
* The task of transcribing text from documents via OCR can be distributed among several physical or virtual computers to decrease load and increase availability.
|
||||
* The task of transcribing text from documents via OCR can be distributed
|
||||
among several physical or virtual computers to decrease load and increase
|
||||
availability.
|
||||
|
||||
* Multilingual user interface.
|
||||
|
||||
* **Mayan EDMS** being written using the Django_ framework, can be translated to practically any language spoken in the world.
|
||||
For a list of translated languages have a look at Transifex_.
|
||||
* **Mayan EDMS** being written using the Django_ framework, can be translated
|
||||
to practically any language spoken in the world. For a list of translated
|
||||
languages have a look at the Transifex_ project location.
|
||||
|
||||
* Multilingual OCR support.
|
||||
|
||||
* Current language of the document is passed to the corresponding OCR engine to increase the rate of data vs. recognition errors.
|
||||
* The current language of the document is passed to the corresponding OCR
|
||||
engine to increase the text recognition rate.
|
||||
|
||||
* :doc:`Plugable storage backends <../topics/file_storage>`.
|
||||
|
||||
* Very easy to use 3rd party plugins such as the ones available for Amazon EC2.
|
||||
* It is very easy to use 3rd party plugins such as the ones available for
|
||||
Amazon EC2.
|
||||
|
||||
* Color coded tagging.
|
||||
|
||||
@@ -83,7 +98,8 @@ Features
|
||||
|
||||
* Workflows.
|
||||
|
||||
* Keep track of the state a document, along with the log of the previous state changes.
|
||||
* Keep track of the state of documents, along with the log of the previous
|
||||
state changes.
|
||||
|
||||
|
||||
.. _`Dublin core`: http://dublincore.org/metadata-basics/
|
||||
|
||||
@@ -3,15 +3,26 @@ File storage
|
||||
============
|
||||
|
||||
The files are stored and placed under **Mayan EDMS** "control" to avoid
|
||||
filename clashes (each file gets renamed to its UUID and without extension)
|
||||
and stored in a simple flat arrangement in a directory. This doesn't
|
||||
stop access to the files but it is not recommended because moving,
|
||||
renaming or updating the files directly would throw the database out
|
||||
filename clashes each file gets renamed to its ``UUID`` (Universally Unique ID),
|
||||
without extension, and stored in a simple flat arrangement in a directory.
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
file [ label = 'mayan_1-1.pdf', width=120];
|
||||
document [ label = 'mayan/media/document_storage/ab6c1cfe-8a8f-4a30-96c9-f54f606b9248', width=450];
|
||||
file -> document [label = "upload"];
|
||||
|
||||
file -> document;
|
||||
}
|
||||
|
||||
This doesn't stop access to the files but renaming, moving or updating
|
||||
directly them is not recommended because it would throw the database out
|
||||
of sync.
|
||||
|
||||
**Mayan EDMS** components are as decoupled from each other as possible,
|
||||
storage in this case is very decoupled and its behavior is controlled
|
||||
not by the project but by the Storage progamming class. Why this design?
|
||||
All the other parts don't make any assumptions about the actual file
|
||||
storage, files can be saved locally, over the network or even across the
|
||||
internet and everything will still operate exactly the same.
|
||||
Because **Mayan EDMS** components are as decoupled from each other as possible,
|
||||
storage in this case is decoupled and its behavior is controlled
|
||||
not by the project but by the ``Storage`` module class. All the other
|
||||
modules don't make any assumptions about how the actual document files are
|
||||
stored. This way files can be saved locally, over the network or even across
|
||||
the Internet and everything will still operate exactly the same.
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
===============
|
||||
Getting started
|
||||
===============
|
||||
|
||||
Before starting to use **Mayan EDMS**, two things need to be configured:
|
||||
|
||||
- At least one document source
|
||||
- At least one document type
|
||||
|
||||
Document sources
|
||||
----------------
|
||||
|
||||
Document sources define from where documents will be uploaded or gathered.
|
||||
To add a document source go to the ``Setup`` section, then to the ``Sources`` section.
|
||||
To obtain the fastest working setup, create a new source of type ``Web form``.
|
||||
``Web forms`` are just HTML forms with a ``Browse`` button that will open the file upload
|
||||
dialog when clicked. Name it something simple like ``Local documents`` and select whether or not
|
||||
compressed files uploaded from this source will be automatically decompressed and
|
||||
their content treated as individual documents.
|
||||
|
||||
Document types
|
||||
--------------
|
||||
|
||||
Examples of document types are: ``Legal documents``, ``Internal documents``, ``Medical records``, ``Designing specifications``, ``Permits``.
|
||||
A document type represent a class of documents which share some common property.
|
||||
A good indicator that can help you determine your document types is what kind of
|
||||
information or ``metadata`` is attached to those documents.
|
||||
|
||||
Once a document source and a document type have been created you have all the minimal
|
||||
elements required to start uploading documents.
|
||||
|
||||
Defining metadata
|
||||
-----------------
|
||||
|
||||
With your document types defined it should be much easier now to define the required
|
||||
``metadata`` for each of these document types. When creating ``metadata`` types,
|
||||
the first thing that will be needed is the internal name with which this metadata
|
||||
type will be referenced in other areas of **Mayan EDMS**. The internal name must not
|
||||
contain spaces or uppercase characters. After the internal name, enter the name that
|
||||
will be visible to you and your users, which usually will be similar or the same as the
|
||||
internal name, but with proper capitalization and spacing. The ``metadata types``
|
||||
can have default values to speed up data entry. They can be single number or a
|
||||
words enclosed in quotes, ie::
|
||||
|
||||
"Building A"
|
||||
|
||||
or::
|
||||
|
||||
"Storage room 1"
|
||||
|
||||
Default values can also be defined as ``Python`` statements or functions such as::
|
||||
|
||||
current_date()
|
||||
|
||||
If you want to restrict or standardize the values for a metadata type, use the ``Lookup`` field to
|
||||
define the list of options that are allowed. Define the lookup list using a ``Python``
|
||||
list of quoted values, for example::
|
||||
|
||||
["2000", "2001", "2002", "2003", "2004"].
|
||||
|
||||
Instead of a free entry text field, your users will get a dropdown list of years,
|
||||
this will ensure an unified data entry formatting. You can also use a
|
||||
``Python`` expression to generate the lookup list.
|
||||
|
||||
Metadata types can be assigned in two ways to a document type, by making it an
|
||||
optional or a required metadata type for a specific document. This method
|
||||
allows metadata very important for some types of documents (like Invoice
|
||||
numbers to Invoices) to be required for an Invoice to be able to be uploaded.
|
||||
Accordingly optional metadata types will be presented, but users are not required to
|
||||
enter a value to be able to upload a document.
|
||||
|
||||
Indexes
|
||||
-------
|
||||
|
||||
After defining all your metadata types you can also define indexes to
|
||||
let **Mayan EDMS** automatically categorize your documents based on their metadata values.
|
||||
To create an index to organize invoices by a year metadata field do the following:
|
||||
|
||||
- Create a year metadata type with the name ``year`` and the label ``Year``.
|
||||
- Create an invoice document type and assign it the ``year`` metadata type as a required metadata type.
|
||||
- Create a new index, give it the name ``invoices_per_year`` and the label ``Invoices per year``.
|
||||
- Edit the index's ``Tree template``, add a ``New child node``, and enter ``document.metadata_value_of.year`` as the ``Indexing expression``, check the ``Link documents`` checkbox and save.
|
||||
- Link this new index to the invoice document type using the ``Document types`` button of the index.
|
||||
|
||||
Now every time a new invoice upload or an existing invoice's ``year`` metadata value is changed, a new folder will be created in the ``Invoices`` index with the corresponding invoices for that year.
|
||||
@@ -1,16 +1,22 @@
|
||||
Concepts
|
||||
========
|
||||
|
||||
Introductions to all the key parts of Mayan EDMS you'll need to know:
|
||||
Introductions to all the key parts of **Mayan EDMS** you'll need to know:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
file_storage
|
||||
document_types
|
||||
metadata
|
||||
permissions
|
||||
sources
|
||||
acls
|
||||
transformations
|
||||
checkouts
|
||||
versioning
|
||||
signatures
|
||||
indexes
|
||||
smart_links
|
||||
tags
|
||||
file_storage
|
||||
screenshots
|
||||
|
||||
@@ -2,21 +2,92 @@
|
||||
Indexes
|
||||
=======
|
||||
|
||||
Indexes are an automatic method to hierarchically organize documents in relation to their properties.
|
||||
Indexes are an automatic method to hierarchically organize documents in
|
||||
relation to their properties (:doc:`metadata`, label, MIME type, etc). To use
|
||||
indexes you need to first create an index template. Once created, associate
|
||||
the index to one or more :doc:`document_types`.
|
||||
|
||||
Index templates
|
||||
===============
|
||||
Index are hierarchical models so a tree template needs to be specified for them.
|
||||
This tree template will contain references to document metadata or properties
|
||||
that will be replaced with the actual value for those metadata or properties.
|
||||
|
||||
Since multiple indexes can be defined, the first step is to create an empty index.
|
||||
Administrators then define the tree template showing how the index will be structured.
|
||||
Each branch can be a pseudo folder, which can hold other child 'folders' or
|
||||
a document container which will have all the links to the documents that
|
||||
matched the criteria of the document container.
|
||||
Example:
|
||||
|
||||
Index instances
|
||||
===============
|
||||
- Document type: ``Product sheet``
|
||||
- Metadata type: ``Product year``, associated as a required metadata for the document type ``Product sheet``.
|
||||
|
||||
The template is the skeleton from which an instance of the index is then
|
||||
auto-populated with links to the documents depending on the rules of each
|
||||
branch of the index evaluated against the metadata and properties of the documents.
|
||||
- Index: ``Product sheets per year``, and associated to the document type ``Product sheet``.
|
||||
- Index slug: ``product-sheets-per-year``. Slugs are internal unique identifiers that can be used by other **Mayan EDMS** modules to reference each index.
|
||||
- Index tree template as follows:
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
index [ label = 'Product sheets per year', width=180 ];
|
||||
root [ label = 'Root (Has document links? No)', width=450];
|
||||
level_2 [ label = '{{ document.metadata_value_of.product_year }} (Has document links? Yes)', width=450];
|
||||
|
||||
group {
|
||||
label = "Tree template";
|
||||
color = "#dddddd";
|
||||
style = dashed;
|
||||
root; level_2;
|
||||
}
|
||||
|
||||
index -> root
|
||||
root -> level_2 [folded];
|
||||
}
|
||||
|
||||
Now every time a new ``Product sheet`` is uploaded a hierarchical unit with the value
|
||||
of the metadata type ``Product year`` is created and a link to the uploaded ``Product sheet`` added to it.
|
||||
|
||||
Example:
|
||||
|
||||
Suppose three ``Product sheets`` are uploaded with the following values as their
|
||||
``Product year`` metadata: 2001, 2002, 2001 respectively. The result index
|
||||
that will be generate based on the tree template would be as follows:
|
||||
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
index [ label = 'Product sheets per year', width=180 ];
|
||||
year_1 [ label = '2001', width = 60 ];
|
||||
year_2 [ label = '2002', width = 60 ];
|
||||
document_1 [ label = 'Product A data sheet (2001)', width = 200 ];
|
||||
document_2 [ label = 'Product B data sheet (2002)', width = 200 ];
|
||||
document_3 [ label = 'Product C data sheet (2001)', width = 200 ];
|
||||
|
||||
group {
|
||||
label = "Index content";
|
||||
color = "#dddddd";
|
||||
style = dashed;
|
||||
year_1, year_2, document_1, document_2, document_3;
|
||||
}
|
||||
|
||||
index -> year_1;
|
||||
index -> year_2;
|
||||
year_1 -> document_1;
|
||||
year_2 -> document_2;
|
||||
year_1 -> document_3;
|
||||
|
||||
}
|
||||
|
||||
Mirroring
|
||||
=========
|
||||
|
||||
Indexes can be exported as `FUSE <https://en.wikipedia.org/wiki/Filesystem_in_Userspace>`_
|
||||
filesystems. Using the management command ``mountindex`` we could export the
|
||||
previous example index as follows::
|
||||
|
||||
mkdir -p ~/indexes/products
|
||||
mayan-edms.py mountindex product-sheets-per-year ~/indexes/products
|
||||
|
||||
The ``~/indexes/products`` directory will now have a directory and files structure
|
||||
identical to that of the index. Once indexes are mounted with this command, they
|
||||
behave like any other filesystem directory and can even be further shared
|
||||
via the network with network file system software like
|
||||
`Samba <https://www.samba.org/>`_ or
|
||||
`NFS <https://en.wikipedia.org/wiki/Network_File_System>`_.
|
||||
|
||||
Indexes and mirrored indexes are Read Only as they are generated as a result of
|
||||
prior activities like document uploads, metadata changes.
|
||||
|
||||
@@ -2,45 +2,33 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
**Mayan EDMS** should be deployed like any other Django_ project and preferably using virtualenv_.
|
||||
**Mayan EDMS** should be deployed like any other Django_ project and
|
||||
preferably using virtualenv_.
|
||||
|
||||
Being a Django_ and a Python_ project familiarity with these technologies is
|
||||
required to understand why **Mayan EDMS** does some of the things it does the way
|
||||
it does them.
|
||||
Being a Django_ and a Python_ project, familiarity with these technologies is
|
||||
recommended to better understand why **Mayan EDMS** does some of the things it
|
||||
does.
|
||||
|
||||
Before installing **Mayan EDMS**, the binary requirements must be installed first.
|
||||
Bellow are the step needed for a test install.
|
||||
|
||||
Binary dependencies
|
||||
===================
|
||||
|
||||
Ubuntu
|
||||
------
|
||||
|
||||
If using a Debian_ or Ubuntu_ based Linux distribution getting the executable requirements is as easy as::
|
||||
If using a Debian_ or Ubuntu_ based Linux distribution, get the executable
|
||||
requirements using::
|
||||
|
||||
$ sudo apt-get install libjpeg-dev libmagic1 libpng-dev libreoffice libtiff-dev gcc ghostscript gpgv python-dev python-virtualenv tesseract-ocr unpaper poppler-utils -y
|
||||
sudo apt-get install libjpeg-dev libmagic1 libpng-dev libreoffice libtiff-dev gcc ghostscript gpgv python-dev python-virtualenv tesseract-ocr unpaper poppler-utils -y
|
||||
|
||||
Initialize a ``virtualenv`` to deploy the project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ virtualenv venv
|
||||
$ source venv/bin/activate
|
||||
$ pip install mayan-edms
|
||||
|
||||
By default **Mayan EDMS** will create a single file SQLite_ database, which makes
|
||||
it very easy to start using **Mayan EDMS**. Populate the database with the project's schema doing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mayan-edms.py initialsetup
|
||||
$ mayan-edms.py runserver
|
||||
|
||||
Point your browser to http://127.0.0.1:8000. If everything was installed
|
||||
correctly you should see the login screen and panel showing a randomly generated admin password.
|
||||
|
||||
Mac OSX
|
||||
-------
|
||||
|
||||
**Mayan EDMS** is dependant on a number of binary packages and the recommended way is
|
||||
to use a package manager such as `MacPorts <https://www.macports.org/>`_ or `Homebrew <http://brew.sh/>`.
|
||||
**Mayan EDMS** is dependent on a number of binary packages and the recommended
|
||||
way is to use a package manager such as `MacPorts <https://www.macports.org/>`_
|
||||
or `Homebrew <http://brew.sh/>`_.
|
||||
|
||||
|
||||
Use MacPorts to install binary dependencies
|
||||
@@ -50,14 +38,9 @@ With MacPorts installed run the command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo port install python-dev gcc tesseract-ocr unpaper python-virtualenv ghostscript libjpeg-dev libpng-dev poppler-utils
|
||||
|
||||
**Mayan EDMS** can use either Pillow, ImageMagick or GraphicsMagick as the backend to
|
||||
convert images so in addition you can install GraphicsMagick ...
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo port install graphicsmagick
|
||||
sudo port install python-dev gcc tesseract-ocr unpaper \
|
||||
python-virtualenv ghostscript libjpeg-dev libpng-dev \
|
||||
poppler-utils
|
||||
|
||||
Set the Binary paths
|
||||
********************
|
||||
@@ -68,19 +51,12 @@ to /usr/bin/ with ...
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo ln -s /opt/local/bin/tesseract /usr/bin/tesseract && \
|
||||
sudo ln -s /opt/local/bin/identify /usr/bin/identify && \
|
||||
sudo ln -s /opt/local/bin/gs /usr/bin/gs
|
||||
sudo ln -s /opt/local/bin/tesseract /usr/bin/tesseract
|
||||
|
||||
... alternatively set the paths in the ``settings/locals.py``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# document converters
|
||||
CONVERTER_IM_CONVERT_PATH = '/opt/local/bin/convert'
|
||||
IM_IDENTIFY_PATH = '/opt/local/bin/identify'
|
||||
GRAPHICS_BACKEND = 'converter.backends.graphicsmagick.GraphicsMagick'
|
||||
GM_PATH = '/opt/local/bin/gm'
|
||||
LIBREOFFICE_PATH = '/Applications/LibreOffice.app/Contents/MacOS/soffice'
|
||||
|
||||
Or Use Homebrew
|
||||
@@ -90,7 +66,7 @@ With Homebrew installed run the command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
brew install python gcc tesseract unpaper poppler libpng graphicsmagick postgresql
|
||||
brew install python gcc tesseract unpaper poppler libpng postgresql
|
||||
|
||||
Set the Binary paths
|
||||
********************
|
||||
@@ -102,57 +78,52 @@ to /usr/bin/ with ...
|
||||
.. code-block:: bash
|
||||
|
||||
sudo ln -s /usr/local/bin/tesseract /usr/bin/tesseract && \
|
||||
sudo ln -s /usr/local/bin/identify /usr/bin/identify && \
|
||||
sudo ln -s /usr/local/bin/unpaper /usr/bin/unpaper && \
|
||||
sudo ln -s /usr/local/bin/pdftotext /usr/bin/pdftotext && \
|
||||
sudo ln -s /usr/local/bin/gs /usr/bin/gs && \
|
||||
sudo ln -s /usr/local/bin/gs /usr/bin/gs
|
||||
|
||||
... alternatively set the paths in the ``settings/locals.py``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# document converters
|
||||
CONVERTER_IM_CONVERT_PATH = '/usr/local/bin/convert'
|
||||
IM_IDENTIFY_PATH = '/usr/local/bin/identify'
|
||||
GRAPHICS_BACKEND = 'converter.backends.graphicsmagick.GraphicsMagick'
|
||||
GM_PATH = '/usr/local/bin/gm'
|
||||
LIBREOFFICE_PATH = '/Applications/LibreOffice.app/Contents/MacOS/soffice'
|
||||
|
||||
Testing the install
|
||||
-------------------
|
||||
Actual project installation
|
||||
===========================
|
||||
|
||||
To create a custom settings file for **Mayan EDMS**, create a Python (.py) file
|
||||
in the directory: venv/lib/python2.7/site-packages/mayan/settings/ with the following basic content::
|
||||
Initialize a ``virtualenv`` to deploy the project:
|
||||
|
||||
# venv/lib/python2.7/site-packages/mayan/settings/my_settings.py
|
||||
.. code-block:: bash
|
||||
|
||||
from __future__ import unicode_literals
|
||||
virtualenv venv
|
||||
source venv/bin/activate
|
||||
pip install mayan-edms
|
||||
|
||||
from .local import *
|
||||
By default **Mayan EDMS** will create a single file SQLite_ database, which makes
|
||||
it very easy to start using **Mayan EDMS**. Populate the database with the
|
||||
project's schema doing:
|
||||
|
||||
<Your customized settings>
|
||||
.. code-block:: bash
|
||||
|
||||
To test your settings launch **Mayan EDMS** using::
|
||||
mayan-edms.py initialsetup
|
||||
mayan-edms.py runserver
|
||||
|
||||
$ mayan-edms.py runserver --settings=mayan.settings.my_settings
|
||||
Point your browser to http://127.0.0.1:8000. If everything was installed
|
||||
correctly you should see the login screen and panel showing a randomly generated
|
||||
admin password.
|
||||
|
||||
Note: Background tasks and scheduled tasks will not run when using the test server.
|
||||
|
||||
|
||||
Production use
|
||||
--------------
|
||||
==============
|
||||
|
||||
After making sure everything is running correctly, stop the `runserver` command.
|
||||
Deploy **Mayan EDMS** using the webserver of your preference. For more information
|
||||
on deployment instructions and examples, checkout Django's official documentation
|
||||
on the topic https://docs.djangoproject.com/en/1.6/howto/deployment/
|
||||
|
||||
|
||||
Other database managers
|
||||
-----------------------
|
||||
|
||||
If you want to use a database manager other than SQLite_ install any
|
||||
corresponding python database drivers and add the corresponding database settings
|
||||
to your settings file (see above) as shown here: https://docs.djangoproject.com/en/1.6/ref/settings/#std:setting-DATABASES
|
||||
on the topic https://docs.djangoproject.com/en/1.7/howto/deployment/
|
||||
For a simple production deployment setup follow the instructions in the
|
||||
:doc:`deploying` chapter.
|
||||
|
||||
|
||||
.. _Debian: http://www.debian.org/
|
||||
|
||||
28
docs/topics/metadata.rst
Normal file
@@ -0,0 +1,28 @@
|
||||
========
|
||||
Metadata
|
||||
========
|
||||
|
||||
Metadata is the name of the attribute of a document. The concept of metadata is
|
||||
divided in two: **metadata types** (size, color, distance) and **metadata values** for
|
||||
those types. Metadata types are defined in the setup menu and associated with
|
||||
document types. Then when a document is uploaded, a value for that metadata
|
||||
can be entered. There are two kinds of metadata type to document type relations:
|
||||
optional and required. When a metadata type is optional for a document type,
|
||||
it can be left blank for a document being uploaded and the upload will still
|
||||
be successful. On the other hand required metadata type must be given a value
|
||||
or it will not be possible to upload the document at hand.
|
||||
|
||||
Examples of metadata type: Invoice number, color, employee id.
|
||||
|
||||
The data entry of metadata types can be set to allow any value to be provided
|
||||
(the default) or a list of possible values can be entered in the ``Lookup``
|
||||
configuration option and users will be presented with a drop down list of options
|
||||
instead of the default text entry box.
|
||||
|
||||
If metadata types are setup to allow any value to be entered a ``validation``
|
||||
option can be chosen to block the entry of invalid data. Metadata types also
|
||||
provide ``parsers`` which will not block the entry of data but are able to
|
||||
interpret and modify the value provided by the user to a conform to a specific
|
||||
format. An example of a provided parser is the date parser which will interpret
|
||||
and correct dates provided by users regardless of the format in which they are
|
||||
entered.
|
||||
@@ -2,46 +2,24 @@
|
||||
Permissions
|
||||
===========
|
||||
|
||||
**Mayan EDMS** provides finegrained control over which activities users can
|
||||
perform. This control is divided into two levels of operation:
|
||||
**Mayan EDMS** provides very fine control over which actions users can
|
||||
perform. Action control works by allowing ``roles``, that are composed of
|
||||
``groups`` of ``users`` to be granted a ``permission`` such that the holder of
|
||||
that permission can exercise it throughout the entire system.
|
||||
|
||||
2 tier permissions assignement
|
||||
==============================
|
||||
.. blockdiag::
|
||||
|
||||
This level of activity control works by allowing roles that are composed
|
||||
of users or groups, to be granted a permission such that the holder of that
|
||||
permission can exercise it throughout the entire collection of objects
|
||||
(document, folders, tags, etc). This method could be thought out as a global
|
||||
permission.
|
||||
blockdiag {
|
||||
user [ label = 'Users' ];
|
||||
group [ label = 'Groups' ];
|
||||
role [ label = 'Roles' ];
|
||||
permission [ label = 'Permissions' ];
|
||||
|
||||
3 tier access control
|
||||
=====================
|
||||
|
||||
When more control is desired over which objects actors
|
||||
(user, groups and roles) can exercise an action, this method should be
|
||||
used. Under this method, actors are granted a permission but only in relation
|
||||
to a selected object. Example: Granting user
|
||||
``Joe`` the ``Document view`` access control for document ``Payroll``, would
|
||||
allow him to view this document only.
|
||||
user -> group -> role <- permission;
|
||||
}
|
||||
|
||||
The permission system enforces inheritance by first checking, if the user
|
||||
has a global permission, is a member of a group or a role that has a global
|
||||
permission and if not, then checks to see if that user, a group or role to
|
||||
which he belongs, has been granted access to the specific object to which
|
||||
he is desiring to perform a given action.
|
||||
|
||||
Only when these checks fail the user is forbidden to perform the action and
|
||||
a generic message is displayed to avoid providing any information
|
||||
that could be used to sidetrack the permission system or obtain any kind of
|
||||
information about the object to which the user was not allowed access.
|
||||
|
||||
Default Access Control Lists (Default ACLs)
|
||||
-------------------------------------------
|
||||
|
||||
Default Access Control Lists allow assigment of an access control list to a
|
||||
type of object (Document, Tags, Folders) before it is created. It is the default
|
||||
permissions an object will have when it is created. With Default Access Control Lists
|
||||
specific permissions can be granted to the creator of a document for example.
|
||||
|
||||
Changes to the Default Access Control Lists (Default ACLs) only affect objects
|
||||
created after the change, they will not affect documents previously uploaded.
|
||||
In other words, users themselves can't hold a permission, permissions are
|
||||
granted only to roles. Users can't directly belong to a role, they can only
|
||||
belong to a group. Groups can be members of roles. Roles are system permission
|
||||
units and groups are business organizational units.
|
||||
|
||||
64
docs/topics/screenshots.rst
Normal file
@@ -0,0 +1,64 @@
|
||||
===========
|
||||
Screenshots
|
||||
===========
|
||||
|
||||
.. figure:: /_static/main.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: Home screen
|
||||
:align: left
|
||||
|
||||
Home screen
|
||||
|
||||
.. figure:: /_static/page_view.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: Page view
|
||||
:align: right
|
||||
|
||||
Page view
|
||||
|
||||
|
||||
.. figure:: /_static/document_view.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: Document view
|
||||
:align: left
|
||||
|
||||
Document view
|
||||
|
||||
|
||||
.. figure:: /_static/api.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: REST API
|
||||
:align: right
|
||||
|
||||
REST API
|
||||
|
||||
|
||||
.. figure:: /_static/tools.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: Tools
|
||||
:align: left
|
||||
|
||||
Tools
|
||||
|
||||
|
||||
.. figure:: /_static/setup.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: Setup
|
||||
:align: right
|
||||
|
||||
Setup
|
||||
|
||||
|
||||
.. figure:: /_static/statistics.png
|
||||
:figwidth: 40%
|
||||
:scale: 30 %
|
||||
:alt: Statistics
|
||||
:align: left
|
||||
|
||||
Statistics
|
||||
@@ -2,13 +2,31 @@
|
||||
Smart links
|
||||
===========
|
||||
|
||||
Smart links are a way to link documents without changing how they are organized
|
||||
in their respective indexes. Smart links are useful when two documents are
|
||||
related somehow but are of different type or different hierarchical units.
|
||||
|
||||
Smart links are usefull for navigation between documents. They are rule
|
||||
based, but don't create any organizational structure. They just show the documents
|
||||
that match the rules as evaluated against the metadata of the currently
|
||||
displayed document.
|
||||
Example: A patient record can be related to a prescription drug information
|
||||
document, but they each belong to their own :doc:`indexes`.
|
||||
|
||||
Smart links are usefull when a patient file in a patients index needs to be linked
|
||||
to the medical documentation of a prescription the patient is using, but that medical
|
||||
documentation is in it's own prescription index. Smart links can provide a reference
|
||||
between documents of different indexes without any change in the indexes' structures.
|
||||
Smart links are rule based, but don't create any organizational structure.
|
||||
Smart links just show the documents that match the rules as evaluated against
|
||||
the metadata or properties of the currently displayed document.
|
||||
|
||||
Indexes are automatic hierarchical units used to group documents, smart links
|
||||
are automatic references between documents.
|
||||
|
||||
Example:
|
||||
|
||||
- Document type: ``Patient records``
|
||||
- Metadata type: ``Prescription``, associated as an optional metadata for the document type ``Patient records``.
|
||||
|
||||
- Document type: ``Prescription information sheets``
|
||||
|
||||
A smart link with the following condition, will automatically links patient
|
||||
records to the prescription information sheets based on the value of the
|
||||
metadata type of the patient record.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
foreign label is equal to {{ document.metadata_value_of.prescription }}
|
||||
|
||||
27
docs/topics/sources.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
=======
|
||||
Sources
|
||||
=======
|
||||
|
||||
Document sources define places from which documents can be uploaded or gathered.
|
||||
|
||||
The current document sources supported are:
|
||||
|
||||
- Web - ``HTML`` forms with a ``Browse`` button that will open the file dialog
|
||||
when clicked to allow selection of files in the user's computer to be
|
||||
uploaded as documents.
|
||||
- Staging folder - Folder where networked attached scanned can save image
|
||||
files. The files in these staging folders are scanned and a preview is
|
||||
generated to help the process of upload.
|
||||
- POP3 email - Provide the email, server and credential of a ``POP3`` based
|
||||
email to be scanned periodically for email. The body of the email is uploaded
|
||||
as a document and the attachments of the email are uploaded as separate
|
||||
documents.
|
||||
- IMAP email - Same as the ``POP3`` email source but for email accounts using
|
||||
the ``IMAP`` protocol.
|
||||
- Watch folder - A filesystem folder that is scanned periodically for files.
|
||||
Any file in the watch folder is automatically uploaded.
|
||||
|
||||
Document source can be configure to allow document bundles to uploaded as
|
||||
compressed files which are decompressed and their content uploaded as separate
|
||||
documents. This feature is useful when migrating from another document
|
||||
manager system.
|
||||
@@ -2,8 +2,8 @@
|
||||
Tags
|
||||
====
|
||||
|
||||
Tags allow giving documents a toggable property. Documents can also be tagged
|
||||
with more than one tag. Once tagged, documents can be searched also by their tags
|
||||
and from the tags main menu a list of all the documents with a particular tag
|
||||
can be obtained easily. Aside from their texts, tags can be assigned a particular
|
||||
color.
|
||||
Tags allow giving documents a binary property. Documents can also be tagged
|
||||
with more than one tag. Once tagged, documents can be searched also by their
|
||||
tags and from the tags main menu a list of all the documents with a particular
|
||||
tag can be obtained easily. Aside from their texts, tags can be assigned a
|
||||
particular color.
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
=========================
|
||||
What are transformations?
|
||||
=========================
|
||||
===============
|
||||
Transformations
|
||||
===============
|
||||
|
||||
Transformation are useful to manipulate the preview of the stored documents
|
||||
in a persistent manner, for example some scanning equipment only produce
|
||||
landscape PDFs, in this case a default transformation for that document
|
||||
source would be "rotation: 270 degress". This way whenever a document is
|
||||
uploaded from that scanner it appears in portrait orientation.
|
||||
The transformation remains attached to the document, the file being
|
||||
preserved in it's original state (a requirement in legal environments) and
|
||||
only the representation being transformed.
|
||||
Transformation are persistent manipulations to the previews of the stored
|
||||
documents. For example: a scanning equipment may only produce landscape PDFs.
|
||||
In this case an useful transformation for that document source would be to
|
||||
rotate all documents scanned by 270 degrees after being uploaded, this way
|
||||
whenever a document is uploaded from that scanner it will appear in portrait
|
||||
orientation. Transformations do not physically modify the document file but
|
||||
are just associated with the document's temporary graphical representation.
|
||||
|
||||
17
docs/topics/translations.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
============
|
||||
Translations
|
||||
============
|
||||
|
||||
Translations are handled online via the **Transifex** website:
|
||||
https://www.transifex.com/projects/p/mayan-edms/. To create a translation team
|
||||
for a new language or contribute to an already existing language translation,
|
||||
create a **Transifex** account and contact the team coordinator of the
|
||||
respective language in which you are interested.
|
||||
|
||||
Feel free to open translation issues inside **Transifex** itself if you have a
|
||||
question about the usage or meaning of a source text string. If you open a
|
||||
translation issue, it will be your responsibility to close it after you get an
|
||||
answers that satisfies your question. Administrator will not close new issues
|
||||
as they have no way to determine if your question has been properly answered.
|
||||
However to avoid clutter, answered questions will be scanned periodically and
|
||||
closed if no activity is observed from the original poster in a period of time.
|
||||
@@ -5,10 +5,8 @@ Document versioning
|
||||
**Mayan EDMS** has the ability to store different versions of the same
|
||||
document. A comment field is provided to allow users to summarize the new
|
||||
version changes in comparison with the previous one. If a new version was
|
||||
uploded by mistake or such new version is no longer necessary the option to
|
||||
uploaded by mistake or such new version is no longer necessary the option to
|
||||
revert to a previous version of the document is provided.
|
||||
|
||||
To upload a new document version, select an existing document, click on the
|
||||
version tab of the document, and click on the 'upload new version' on the
|
||||
side bar. A new view very similar to the new document upload view will
|
||||
appear, showing the same interactive document sources that have been defined.
|
||||
Only the interactive document sources (:doc:`sources`) (``Web`` and ``Staging folders``) are
|
||||
available to upload new document versions.
|
||||
|
||||
3
environment
Normal file
@@ -0,0 +1,3 @@
|
||||
POSTGRES_DB=mayan
|
||||
POSTGRES_PASSWORD=mayanpassword
|
||||
POSTGRES_USER=mayan
|
||||
@@ -8,4 +8,3 @@ if __name__ == "__main__":
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
13
mayan/LICENSE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2011-2015 Roberto Rosario
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,8 +1,10 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__title__ = 'Mayan EDMS'
|
||||
__version__ = '1.1.1'
|
||||
__build__ = 0x010101
|
||||
__version__ = '2.0.0'
|
||||
__build__ = 0x020000
|
||||
__author__ = 'Roberto Rosario'
|
||||
__author_email__ = 'roberto.rosario@mayan-edms.com'
|
||||
__description__ = 'Free Open Source Electronic Document Management System'
|
||||
__license__ = 'Apache 2.0'
|
||||
__copyright__ = 'Copyright 2011-2015 Roberto Rosario'
|
||||
|
||||
@@ -1,33 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.dispatch import receiver
|
||||
from .classes import ModelPermission # NOQA
|
||||
|
||||
from south.signals import post_migrate
|
||||
|
||||
from navigation.api import register_links
|
||||
from project_setup.api import register_setup
|
||||
|
||||
from .classes import (
|
||||
AccessHolder, AccessObject, AccessObjectClass, ClassAccessHolder
|
||||
)
|
||||
from .links import (
|
||||
acl_class_acl_detail, acl_class_acl_list, acl_class_grant, acl_class_list,
|
||||
acl_class_new_holder_for, acl_class_revoke, acl_detail, acl_grant,
|
||||
acl_holder_new, acl_revoke, acl_setup_valid_classes
|
||||
)
|
||||
from .models import CreatorSingleton
|
||||
|
||||
register_links([AccessObject], [acl_holder_new], menu_name='sidebar')
|
||||
register_links(AccessObjectClass, [acl_class_acl_list, acl_class_new_holder_for])
|
||||
register_links(AccessHolder, [acl_detail])
|
||||
register_links(['acls:acl_setup_valid_classes', 'acls:acl_class_acl_list', 'acls:acl_class_new_holder_for', 'acls:acl_class_acl_detail', 'acls:acl_class_multiple_grant', 'acls:acl_class_multiple_revoke'], [acl_class_list], menu_name='secondary_menu')
|
||||
register_links(ClassAccessHolder, [acl_class_acl_detail])
|
||||
register_links(['acls:acl_detail'], [acl_grant, acl_revoke], menu_name='multi_item_links')
|
||||
register_links(['acls:acl_class_acl_detail'], [acl_class_grant, acl_class_revoke], menu_name='multi_item_links')
|
||||
register_setup(acl_setup_valid_classes)
|
||||
|
||||
|
||||
@receiver(post_migrate, dispatch_uid='create_creator_user')
|
||||
def create_creator_user(sender, **kwargs):
|
||||
if kwargs['app'] == 'acls':
|
||||
CreatorSingleton.objects.get_or_create()
|
||||
default_app_config = 'acls.apps.ACLsApp'
|
||||
|
||||
@@ -2,15 +2,15 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import AccessEntry
|
||||
from .models import AccessControlList
|
||||
|
||||
|
||||
class AccessEntryAdmin(admin.ModelAdmin):
|
||||
model = AccessEntry
|
||||
list_display = ('pk', 'holder_object', 'permission', 'content_object')
|
||||
@admin.register(AccessControlList)
|
||||
class AccessControlListAdmin(admin.ModelAdmin):
|
||||
filter_horizontal = ('permissions',)
|
||||
list_display = ('pk', 'role', 'content_type', 'content_object')
|
||||
list_display_links = ('pk',)
|
||||
list_filter = ('content_type',)
|
||||
related_lookup_fields = {
|
||||
'generic': [['holder_type', 'holder_id'], ['content_type', 'object_id']],
|
||||
'generic': (('content_type', 'object_id'),),
|
||||
}
|
||||
|
||||
admin.site.register(AccessEntry, AccessEntryAdmin)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
_class_permissions = {}
|
||||
|
||||
|
||||
def class_permissions(cls, permission_list):
|
||||
"""
|
||||
Associate a permissions list to a class
|
||||
"""
|
||||
stored_permissions = _class_permissions.setdefault(cls, [])
|
||||
stored_permissions.extend(permission_list)
|
||||
|
||||
|
||||
def get_class_permissions_for(obj):
|
||||
"""
|
||||
Return a list of permissions associated with a content type
|
||||
"""
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
return _class_permissions.get(content_type.model_class(), [])
|
||||
|
||||
|
||||
def get_classes():
|
||||
"""
|
||||
Return a list of encapsulated classes that have been registered
|
||||
"""
|
||||
return _class_permissions.keys()
|
||||
34
mayan/apps/acls/apps.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common import MayanAppConfig, menu_object, menu_sidebar
|
||||
from navigation import SourceColumn
|
||||
|
||||
from .links import link_acl_new, link_acl_delete, link_acl_permissions
|
||||
from .models import AccessControlList
|
||||
|
||||
|
||||
class ACLsApp(MayanAppConfig):
|
||||
name = 'acls'
|
||||
test = True
|
||||
verbose_name = _('ACLs')
|
||||
|
||||
def ready(self):
|
||||
super(ACLsApp, self).ready()
|
||||
|
||||
SourceColumn(
|
||||
source=AccessControlList, label=_('Permissions'),
|
||||
attribute='get_permission_titles'
|
||||
)
|
||||
SourceColumn(
|
||||
source=AccessControlList, label=_('Role'), attribute='role'
|
||||
)
|
||||
|
||||
menu_object.bind_links(
|
||||
links=(link_acl_permissions, link_acl_delete),
|
||||
sources=(AccessControlList,)
|
||||
)
|
||||
menu_sidebar.bind_links(
|
||||
links=(link_acl_new,), sources=('acls:acl_list',)
|
||||
)
|
||||
@@ -1,153 +1,44 @@
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import types
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models.base import ModelBase
|
||||
|
||||
from common.models import AnonymousUserSingleton
|
||||
from permissions.models import StoredPermission
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_cache = {}
|
||||
|
||||
|
||||
def get_source_object(obj):
|
||||
if isinstance(obj, EncapsulatedObject):
|
||||
return obj.source_object
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
class EncapsulatedObject(object):
|
||||
source_object_name = 'source_object'
|
||||
class ModelPermission(object):
|
||||
_registry = {}
|
||||
_proxies = {}
|
||||
_inheritances = {}
|
||||
|
||||
@classmethod
|
||||
def object_key(cls, app_label=None, model=None, pk=None):
|
||||
if pk:
|
||||
return '%s.%s.%s.%s' % (cls.__name__, app_label, model, pk)
|
||||
else:
|
||||
return '%s.%s.%s' % (cls.__name__, app_label, model)
|
||||
def register(cls, model, permissions):
|
||||
cls._registry.setdefault(model, [])
|
||||
for permission in permissions:
|
||||
cls._registry[model].append(permission)
|
||||
|
||||
@classmethod
|
||||
def add_to_class(cls, name, value):
|
||||
if hasattr(value, 'contribute_to_class'):
|
||||
value.contribute_to_class(cls, name)
|
||||
else:
|
||||
setattr(cls, name, value)
|
||||
|
||||
@classmethod
|
||||
def set_source_object_name(cls, new_name):
|
||||
cls.source_object_name = new_name
|
||||
|
||||
# @classmethod
|
||||
# def encapsulate_list(cls, source_object=None, app_label=None, model=None, pk=None):
|
||||
|
||||
@classmethod
|
||||
def encapsulate(cls, source_object):
|
||||
source_object = AnonymousUserSingleton.objects.passthru_check(source_object)
|
||||
content_type = ContentType.objects.get_for_model(source_object)
|
||||
|
||||
if hasattr(source_object, 'pk'):
|
||||
# Object
|
||||
object_key = cls.object_key(content_type.app_label, content_type.model, source_object.pk)
|
||||
else:
|
||||
# Class
|
||||
object_key = cls.object_key(content_type.app_label, content_type.model)
|
||||
|
||||
def get_for_instance(cls, instance):
|
||||
try:
|
||||
return _cache[object_key]
|
||||
except KeyError:
|
||||
encapsulated_object = cls(source_object)
|
||||
_cache[object_key] = encapsulated_object
|
||||
return encapsulated_object
|
||||
|
||||
@classmethod
|
||||
def get(cls, gid):
|
||||
elements = gid.split('.')
|
||||
if len(elements) == 3:
|
||||
app_label, model, pk = elements[0], elements[1], elements[2]
|
||||
elif len(elements) == 2:
|
||||
app_label, model = elements[0], elements[1]
|
||||
pk = None
|
||||
|
||||
object_key = cls.object_key(*elements)
|
||||
|
||||
try:
|
||||
return _cache[object_key]
|
||||
permissions = cls._registry[type(instance)]
|
||||
except KeyError:
|
||||
try:
|
||||
content_type = ContentType.objects.get(app_label=app_label, model=model)
|
||||
except ContentType.DoesNotExist:
|
||||
raise ObjectDoesNotExist('%s matching query does not exist.' % ContentType._meta.object_name)
|
||||
else:
|
||||
source_object_model_class = content_type.model_class()
|
||||
if pk:
|
||||
try:
|
||||
source_object = content_type.get_object_for_this_type(pk=pk)
|
||||
except source_object_model_class.DoesNotExist:
|
||||
raise ObjectDoesNotExist('%s matching query does not exist.' % source_object_model_class._meta.object_name)
|
||||
else:
|
||||
source_object = source_object_model_class
|
||||
permissions = cls._registry[cls._proxies[type(instance)]]
|
||||
except KeyError:
|
||||
permissions = ()
|
||||
|
||||
return cls.encapsulate(source_object)
|
||||
pks = [permission.stored_permission.pk for permission in permissions]
|
||||
return StoredPermission.objects.filter(pk__in=pks)
|
||||
|
||||
def __init__(self, source_object):
|
||||
self.content_type = ContentType.objects.get_for_model(source_object)
|
||||
self.ct_fullname = '%s.%s' % (self.content_type.app_label, self.content_type.model)
|
||||
@classmethod
|
||||
def register_proxy(cls, source, model):
|
||||
cls._proxies[model] = source
|
||||
|
||||
if isinstance(source_object, ModelBase):
|
||||
# Class
|
||||
self.gid = '%s.%s' % (self.content_type.app_label, self.content_type.model)
|
||||
else:
|
||||
# Object
|
||||
self.gid = '%s.%s.%s' % (self.content_type.app_label, self.content_type.model, source_object.pk)
|
||||
@classmethod
|
||||
def register_inheritance(cls, model, related):
|
||||
cls._inheritances[model] = related
|
||||
|
||||
setattr(self, self.__class__.source_object_name, source_object)
|
||||
|
||||
def __unicode__(self):
|
||||
if isinstance(self.source_object, ModelBase):
|
||||
return unicode(self.source_object._meta.verbose_name_plural)
|
||||
elif self.ct_fullname == 'auth.user':
|
||||
return '%s %s' % (self.source_object._meta.verbose_name, self.source_object.get_full_name())
|
||||
elif self.ct_fullname == 'common.anonymoususersingleton':
|
||||
return unicode(self.source_object)
|
||||
elif self.ct_fullname == 'acls.creatorsingleton':
|
||||
return unicode(self.source_object)
|
||||
else:
|
||||
return '%s %s' % (self.source_object._meta.verbose_name, self.source_object)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__unicode__()
|
||||
|
||||
@property
|
||||
def source_object(self):
|
||||
return getattr(self, self.__class__.source_object_name, None)
|
||||
|
||||
|
||||
class AccessHolder(EncapsulatedObject):
|
||||
source_object_name = 'holder_object'
|
||||
|
||||
|
||||
class AccessObject(EncapsulatedObject):
|
||||
source_object_name = 'obj'
|
||||
|
||||
|
||||
class AccessObjectClass(EncapsulatedObject):
|
||||
source_object_name = 'cls'
|
||||
|
||||
|
||||
class ClassAccessHolder(EncapsulatedObject):
|
||||
source_object_name = 'class_holder'
|
||||
|
||||
|
||||
if sys.version_info < (2, 5):
|
||||
# Prior to Python 2.5, Exception was an old-style class
|
||||
def subclass_exception(name, parents, unused):
|
||||
return types.ClassType(name, parents, {})
|
||||
else:
|
||||
def subclass_exception(name, parents, module):
|
||||
return type(name, parents, {'__module__': module})
|
||||
@classmethod
|
||||
def get_inheritance(cls, model):
|
||||
return cls._inheritances[model]
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
|
||||
from common.models import AnonymousUserSingleton
|
||||
from common.utils import get_object_name
|
||||
from permissions.models import Role
|
||||
|
||||
from .classes import AccessHolder
|
||||
from .models import CreatorSingleton
|
||||
|
||||
anonymous_singleton = SimpleLazyObject(lambda: AnonymousUserSingleton.objects.get())
|
||||
creator_singleton = SimpleLazyObject(lambda: CreatorSingleton.objects.get())
|
||||
|
||||
|
||||
def _as_choice_list(holders):
|
||||
return sorted([(AccessHolder.encapsulate(holder).gid, get_object_name(holder, display_object_type=False)) for holder in holders], key=lambda x: x[1])
|
||||
|
||||
|
||||
class BaseHolderSelectionForm(forms.Form):
|
||||
holder_gid = forms.ChoiceField(
|
||||
label=_('New holder')
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
current_holders = kwargs.pop('current_holders', [])
|
||||
if current_holders:
|
||||
current_holders = [holder.source_object for holder in current_holders]
|
||||
|
||||
staff_users = User.objects.filter(is_staff=True)
|
||||
super_users = User.objects.filter(is_superuser=True)
|
||||
users = set(User.objects.filter(is_active=True)) - set(staff_users) - set(super_users) - set(current_holders)
|
||||
roles = set(Role.objects.all()) - set(current_holders)
|
||||
groups = set(Group.objects.all()) - set(current_holders)
|
||||
special = set(self.special_holders) - set(current_holders)
|
||||
|
||||
non_holder_list = []
|
||||
if users:
|
||||
non_holder_list.append((_('Users'), _as_choice_list(list(users))))
|
||||
|
||||
if groups:
|
||||
non_holder_list.append((_('Groups'), _as_choice_list(list(groups))))
|
||||
|
||||
if roles:
|
||||
non_holder_list.append((_('Roles'), _as_choice_list(list(roles))))
|
||||
|
||||
if special:
|
||||
non_holder_list.append((_('Special'), _as_choice_list(list(special))))
|
||||
|
||||
super(BaseHolderSelectionForm, self).__init__(*args, **kwargs)
|
||||
self.fields['holder_gid'].choices = non_holder_list
|
||||
|
||||
|
||||
class HolderSelectionForm(BaseHolderSelectionForm):
|
||||
special_holders = [anonymous_singleton]
|
||||
|
||||
|
||||
class ClassHolderSelectionForm(BaseHolderSelectionForm):
|
||||
special_holders = [anonymous_singleton, creator_singleton]
|
||||
@@ -1,21 +1,40 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .permissions import (
|
||||
ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL, ACLS_EDIT_ACL, ACLS_VIEW_ACL
|
||||
from navigation import Link
|
||||
|
||||
from .permissions import permission_acl_view, permission_acl_edit
|
||||
|
||||
|
||||
def get_kwargs_factory(variable_name):
|
||||
def get_kwargs(context):
|
||||
content_type = ContentType.objects.get_for_model(
|
||||
context[variable_name]
|
||||
)
|
||||
return {
|
||||
'app_label': '"{}"'.format(content_type.app_label),
|
||||
'model': '"{}"'.format(content_type.model),
|
||||
'object_id': '{}.pk'.format(variable_name)
|
||||
}
|
||||
|
||||
return get_kwargs
|
||||
|
||||
|
||||
link_acl_delete = Link(
|
||||
permissions=(permission_acl_edit,), tags='dangerous', text=_('Delete'),
|
||||
view='acls:acl_delete', args='resolved_object.pk'
|
||||
)
|
||||
link_acl_list = Link(
|
||||
permissions=(permission_acl_view,), text=_('ACLs'), view='acls:acl_list',
|
||||
kwargs=get_kwargs_factory('resolved_object')
|
||||
)
|
||||
link_acl_new = Link(
|
||||
permissions=(permission_acl_edit,), text=_('New ACL'),
|
||||
view='acls:acl_new', kwargs=get_kwargs_factory('resolved_object')
|
||||
)
|
||||
link_acl_permissions = Link(
|
||||
permissions=(permission_acl_edit,), text=_('Permissions'),
|
||||
view='acls:acl_permissions', args='resolved_object.pk'
|
||||
)
|
||||
|
||||
acl_list = {'text': _('ACLs'), 'view': 'acls:acl_list', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
|
||||
acl_detail = {'text': _('Details'), 'view': 'acls:acl_detail', 'args': ['access_object.gid', 'object.gid'], 'famfam': 'key_go', 'permissions': [ACLS_VIEW_ACL]}
|
||||
acl_grant = {'text': _('Grant'), 'view': 'acls:acl_multiple_grant', 'famfam': 'key_add', 'permissions': [ACLS_EDIT_ACL]}
|
||||
acl_revoke = {'text': _('Revoke'), 'view': 'acls:acl_multiple_revoke', 'famfam': 'key_delete', 'permissions': [ACLS_EDIT_ACL]}
|
||||
acl_holder_new = {'text': _('New holder'), 'view': 'acls:acl_holder_new', 'args': 'access_object.gid', 'famfam': 'user', 'permissions': [ACLS_EDIT_ACL]}
|
||||
|
||||
acl_setup_valid_classes = {'text': _('Default ACLs'), 'view': 'acls:acl_setup_valid_classes', 'icon': 'main/icons/lock.png', 'permissions': [ACLS_CLASS_VIEW_ACL]}
|
||||
acl_class_list = {'text': _('Classes'), 'view': 'acls:acl_setup_valid_classes', 'famfam': 'package', 'permissions': [ACLS_CLASS_VIEW_ACL]}
|
||||
acl_class_acl_list = {'text': _('ACLs for class'), 'view': 'acls:acl_class_acl_list', 'args': 'object.gid', 'famfam': 'lock_go', 'permissions': [ACLS_CLASS_VIEW_ACL]}
|
||||
acl_class_acl_detail = {'text': _('Details'), 'view': 'acls:acl_class_acl_detail', 'args': ['access_object_class.gid', 'object.gid'], 'famfam': 'key_go', 'permissions': [ACLS_CLASS_VIEW_ACL]}
|
||||
acl_class_new_holder_for = {'text': _('New holder'), 'view': 'acls:acl_class_new_holder_for', 'args': 'object.gid', 'famfam': 'user', 'permissions': [ACLS_CLASS_EDIT_ACL]}
|
||||
acl_class_grant = {'text': _('Grant'), 'view': 'acls:acl_class_multiple_grant', 'famfam': 'key_add', 'permissions': [ACLS_CLASS_EDIT_ACL]}
|
||||
acl_class_revoke = {'text': _('Revoke'), 'view': 'acls:acl_class_multiple_revoke', 'famfam': 'key_delete', 'permissions': [ACLS_CLASS_EDIT_ACL]}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# Content type <-> fam fam icon mapping
|
||||
CONTENT_TYPE_ICON_MAP = {
|
||||
'auth.user': 'user',
|
||||
'auth.group': 'group',
|
||||
'documents.document': 'page',
|
||||
'permissions.role': 'medal_gold_1',
|
||||
'folders.folder': 'folder',
|
||||
'tags.tag': 'tag_blue',
|
||||
'linking.smartlink': 'page_link',
|
||||
'common.anonymoususersingleton': 'user',
|
||||
'acls.creatorsingleton': 'user',
|
||||
}
|
||||
@@ -4,235 +4,217 @@
|
||||
#
|
||||
# Translators:
|
||||
# Translators:
|
||||
# Mohammed ALDOUB <voulnet@gmail.com>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-05-15 18:59-0400\n"
|
||||
"PO-Revision-Date: 2014-10-25 06:47+0000\n"
|
||||
"POT-Creation-Date: 2015-09-24 16:24-0400\n"
|
||||
"PO-Revision-Date: 2015-09-24 05:15+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/mayan-edms/language/ar/)\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/rosarior/mayan-edms/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ar\n"
|
||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||
|
||||
#: forms.py:25 links.py:13 links.py:19
|
||||
msgid "New holder"
|
||||
msgstr "New holder"
|
||||
|
||||
#: forms.py:42
|
||||
msgid "Users"
|
||||
msgstr "Users"
|
||||
|
||||
#: forms.py:45
|
||||
msgid "Groups"
|
||||
msgstr "Groups"
|
||||
|
||||
#: forms.py:48
|
||||
msgid "Roles"
|
||||
msgstr "Roles"
|
||||
|
||||
#: forms.py:51
|
||||
msgid "Special"
|
||||
msgstr "Special"
|
||||
|
||||
#: links.py:9
|
||||
#: apps.py:14 links.py:30
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: links.py:10 links.py:18
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:11 links.py:20
|
||||
msgid "Grant"
|
||||
#: apps.py:20 links.py:38 models.py:36
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:12 links.py:21
|
||||
msgid "Revoke"
|
||||
#: apps.py:24 models.py:38
|
||||
#| msgid "Roles"
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15
|
||||
msgid "Default ACLs"
|
||||
msgstr "Default ACLs"
|
||||
|
||||
#: links.py:16 views.py:379
|
||||
msgid "Classes"
|
||||
#: links.py:26
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACLs for class"
|
||||
#: links.py:34
|
||||
#| msgid "View ACLs"
|
||||
msgid "New ACL"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:118 managers.py:130
|
||||
#: managers.py:72
|
||||
msgid "Insufficient access."
|
||||
msgstr "Insufficient access."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "Permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
#: models.py:44
|
||||
msgid "Access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
#: models.py:45
|
||||
msgid "Access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "Default access entry"
|
||||
#: models.py:60
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "Default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108 models.py:111 models.py:112
|
||||
msgid "Creator"
|
||||
msgstr "Creator"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Edit ACLs"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Edit class default ACLs"
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "View class default ACLs"
|
||||
|
||||
#: views.py:48
|
||||
#: views.py:61
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:402
|
||||
msgid "Holder"
|
||||
#: views.py:107
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:51 views.py:403
|
||||
msgid "Permissions"
|
||||
#: views.py:132
|
||||
#, python-format
|
||||
#| msgid "Default ACLs"
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:98
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
#: views.py:147
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:434
|
||||
msgid "Namespace"
|
||||
#: views.py:148
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:106 views.py:435
|
||||
msgid "Label"
|
||||
#: views.py:187
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:108 views.py:437
|
||||
msgid "Has permission"
|
||||
#: views.py:218
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: views.py:181 views.py:272 views.py:516 views.py:593
|
||||
msgid ", "
|
||||
msgstr ", "
|
||||
#~ msgid "New holder"
|
||||
#~ msgstr "New holder"
|
||||
|
||||
#: views.py:182 views.py:273 views.py:517 views.py:594
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr " for %s"
|
||||
#~ msgid "Users"
|
||||
#~ msgstr "Users"
|
||||
|
||||
#: views.py:183 views.py:518
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr " to %s"
|
||||
#~ msgid "Groups"
|
||||
#~ msgstr "Groups"
|
||||
|
||||
#: views.py:186 views.py:521
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
#~ msgid "Special"
|
||||
#~ msgstr "Special"
|
||||
|
||||
#: views.py:188 views.py:523
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
#~ msgid "Details"
|
||||
#~ msgstr "details"
|
||||
|
||||
#: views.py:195 views.py:530
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
#~ msgid "Grant"
|
||||
#~ msgstr "grant"
|
||||
|
||||
#: views.py:201 views.py:536
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr "%(actor)s, already had the permission \"%(permission)s\" granted for %(object)s."
|
||||
#~ msgid "Revoke"
|
||||
#~ msgstr "revoke"
|
||||
|
||||
#: views.py:274 views.py:595
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr " from %s"
|
||||
#~ msgid "Classes"
|
||||
#~ msgstr "classes"
|
||||
|
||||
#: views.py:277 views.py:598
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
#~ msgid "ACLs for class"
|
||||
#~ msgstr "ACLs for class"
|
||||
|
||||
#: views.py:279 views.py:600
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
#~ msgid "Permission"
|
||||
#~ msgstr "permissions"
|
||||
|
||||
#: views.py:286 views.py:607
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
#~ msgid "Default access entry"
|
||||
#~ msgstr "default access entry"
|
||||
|
||||
#: views.py:292 views.py:613
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
#~ msgid "Default access entries"
|
||||
#~ msgstr "default access entries"
|
||||
|
||||
#: views.py:346
|
||||
#, python-format
|
||||
msgid "Add new holder for: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Creator"
|
||||
#~ msgstr "Creator"
|
||||
|
||||
#: views.py:347 views.py:477
|
||||
msgid "Select"
|
||||
msgstr "Select"
|
||||
#~ msgid "Edit class default ACLs"
|
||||
#~ msgstr "Edit class default ACLs"
|
||||
|
||||
#: views.py:381
|
||||
msgid "Class"
|
||||
msgstr ""
|
||||
#~ msgid "View class default ACLs"
|
||||
#~ msgstr "View class default ACLs"
|
||||
|
||||
#: views.py:400
|
||||
#, python-format
|
||||
msgid "Default access control lists for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Holder"
|
||||
#~ msgstr "holder"
|
||||
|
||||
#: views.py:428
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
#~ msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for %(obj)s"
|
||||
|
||||
#: views.py:475
|
||||
#, python-format
|
||||
msgid "Add new holder for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Namespace"
|
||||
#~ msgstr "namespace"
|
||||
|
||||
#~ msgid "Label"
|
||||
#~ msgstr "label"
|
||||
|
||||
#~ msgid ", "
|
||||
#~ msgstr ", "
|
||||
|
||||
#~ msgid " for %s"
|
||||
#~ msgstr " for %s"
|
||||
|
||||
#~ msgid " to %s"
|
||||
#~ msgstr " to %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
#~ msgstr ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
|
||||
#~ msgid " from %s"
|
||||
#~ msgstr " from %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
#~ msgstr "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
|
||||
#~ msgid "Add new holder for: %s"
|
||||
#~ msgstr "add new holder for: %s"
|
||||
|
||||
#~ msgid "Select"
|
||||
#~ msgstr "Select"
|
||||
|
||||
#~ msgid "Class"
|
||||
#~ msgstr "class"
|
||||
|
||||
#~ msgid "Default access control lists for class: %s"
|
||||
#~ msgstr "default access control lists for class: %s"
|
||||
|
||||
#~ msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for class %(class)s"
|
||||
|
||||
#~ msgid "Add new holder for class: %s"
|
||||
#~ msgstr "add new holder for class: %s"
|
||||
|
||||
#~ msgid "List of classes"
|
||||
#~ msgstr "List of classes"
|
||||
|
||||
@@ -4,237 +4,217 @@
|
||||
#
|
||||
# Translators:
|
||||
# Translators:
|
||||
# Iliya Georgiev <ikgeorgiev@gmail.com>, 2012
|
||||
# Pavlin Koldamov <pkoldamov@gmail.com>, 2012
|
||||
# Pavlin Koldamov <pkoldamov@gmail.com>, 2012
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-05-15 18:59-0400\n"
|
||||
"PO-Revision-Date: 2014-10-25 06:47+0000\n"
|
||||
"POT-Creation-Date: 2015-09-24 16:24-0400\n"
|
||||
"PO-Revision-Date: 2015-09-24 05:15+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/projects/p/mayan-edms/language/bg/)\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/rosarior/mayan-edms/language/bg/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: bg\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:25 links.py:13 links.py:19
|
||||
msgid "New holder"
|
||||
msgstr "Нов притежател"
|
||||
|
||||
#: forms.py:42
|
||||
msgid "Users"
|
||||
msgstr "Потребители"
|
||||
|
||||
#: forms.py:45
|
||||
msgid "Groups"
|
||||
msgstr "Групи"
|
||||
|
||||
#: forms.py:48
|
||||
msgid "Roles"
|
||||
msgstr "Роли"
|
||||
|
||||
#: forms.py:51
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:9
|
||||
#: apps.py:14 links.py:30
|
||||
msgid "ACLs"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
|
||||
#: links.py:10 links.py:18
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:11 links.py:20
|
||||
msgid "Grant"
|
||||
#: apps.py:20 links.py:38 models.py:36
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:12 links.py:21
|
||||
msgid "Revoke"
|
||||
#: apps.py:24 models.py:38
|
||||
#| msgid "Roles"
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15
|
||||
msgid "Default ACLs"
|
||||
msgstr "Контролни списъци за достъп по подразбиране"
|
||||
|
||||
#: links.py:16 views.py:379
|
||||
msgid "Classes"
|
||||
#: links.py:26
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17
|
||||
msgid "ACLs for class"
|
||||
msgstr "Контролни списъци за клас"
|
||||
#: links.py:34
|
||||
#| msgid "View ACLs"
|
||||
msgid "New ACL"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:118 managers.py:130
|
||||
#: managers.py:72
|
||||
msgid "Insufficient access."
|
||||
msgstr "Недостатъчен достъп."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "Permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
#: models.py:44
|
||||
msgid "Access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
#: models.py:45
|
||||
msgid "Access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "Default access entry"
|
||||
#: models.py:60
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "Default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108 models.py:111 models.py:112
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
#: permissions.py:13
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:48
|
||||
#: views.py:61
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:402
|
||||
msgid "Holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:51 views.py:403
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:98
|
||||
#: views.py:107
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:434
|
||||
msgid "Namespace"
|
||||
#: views.py:132
|
||||
#, python-format
|
||||
#| msgid "Default ACLs"
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:106 views.py:435
|
||||
msgid "Label"
|
||||
#: views.py:147
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:108 views.py:437
|
||||
msgid "Has permission"
|
||||
#: views.py:148
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:181 views.py:272 views.py:516 views.py:593
|
||||
msgid ", "
|
||||
#: views.py:187
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:182 views.py:273 views.py:517 views.py:594
|
||||
#: views.py:218
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr " за %s"
|
||||
|
||||
#: views.py:183 views.py:518
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr " към %s"
|
||||
|
||||
#: views.py:186 views.py:521
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Сигурни ли сте, че искате да дадете разрешение за %(title_suffix)s?"
|
||||
|
||||
#: views.py:188 views.py:523
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Сигурни ли сте, че искате да дадете разрешения за %(title_suffix)s?"
|
||||
|
||||
#: views.py:195 views.py:530
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: views.py:201 views.py:536
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "New holder"
|
||||
#~ msgstr "New holder"
|
||||
|
||||
#: views.py:274 views.py:595
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr " от %s"
|
||||
#~ msgid "Users"
|
||||
#~ msgstr "Users"
|
||||
|
||||
#: views.py:277 views.py:598
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Сигурни ли сте, че искате да отнемете разрешението за %(title_suffix)s?"
|
||||
#~ msgid "Groups"
|
||||
#~ msgstr "Groups"
|
||||
|
||||
#: views.py:279 views.py:600
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "Сигурни ли сте, че искате да отнемете разрешенията за %(title_suffix)s?"
|
||||
#~ msgid "Special"
|
||||
#~ msgstr "Special"
|
||||
|
||||
#: views.py:286 views.py:607
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "Details"
|
||||
#~ msgstr "details"
|
||||
|
||||
#: views.py:292 views.py:613
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "Grant"
|
||||
#~ msgstr "grant"
|
||||
|
||||
#: views.py:346
|
||||
#, python-format
|
||||
msgid "Add new holder for: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Revoke"
|
||||
#~ msgstr "revoke"
|
||||
|
||||
#: views.py:347 views.py:477
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
#~ msgid "Classes"
|
||||
#~ msgstr "classes"
|
||||
|
||||
#: views.py:381
|
||||
msgid "Class"
|
||||
msgstr ""
|
||||
#~ msgid "ACLs for class"
|
||||
#~ msgstr "ACLs for class"
|
||||
|
||||
#: views.py:400
|
||||
#, python-format
|
||||
msgid "Default access control lists for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Permission"
|
||||
#~ msgstr "permissions"
|
||||
|
||||
#: views.py:428
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
#~ msgid "Default access entry"
|
||||
#~ msgstr "default access entry"
|
||||
|
||||
#: views.py:475
|
||||
#, python-format
|
||||
msgid "Add new holder for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Default access entries"
|
||||
#~ msgstr "default access entries"
|
||||
|
||||
#~ msgid "Creator"
|
||||
#~ msgstr "Creator"
|
||||
|
||||
#~ msgid "Edit class default ACLs"
|
||||
#~ msgstr "Edit class default ACLs"
|
||||
|
||||
#~ msgid "View class default ACLs"
|
||||
#~ msgstr "View class default ACLs"
|
||||
|
||||
#~ msgid "Holder"
|
||||
#~ msgstr "holder"
|
||||
|
||||
#~ msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for %(obj)s"
|
||||
|
||||
#~ msgid "Namespace"
|
||||
#~ msgstr "namespace"
|
||||
|
||||
#~ msgid "Label"
|
||||
#~ msgstr "label"
|
||||
|
||||
#~ msgid ", "
|
||||
#~ msgstr ", "
|
||||
|
||||
#~ msgid " for %s"
|
||||
#~ msgstr " for %s"
|
||||
|
||||
#~ msgid " to %s"
|
||||
#~ msgstr " to %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
#~ msgstr ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
|
||||
#~ msgid " from %s"
|
||||
#~ msgstr " from %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
#~ msgstr "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
|
||||
#~ msgid "Add new holder for: %s"
|
||||
#~ msgstr "add new holder for: %s"
|
||||
|
||||
#~ msgid "Select"
|
||||
#~ msgstr "Select"
|
||||
|
||||
#~ msgid "Class"
|
||||
#~ msgstr "class"
|
||||
|
||||
#~ msgid "Default access control lists for class: %s"
|
||||
#~ msgstr "default access control lists for class: %s"
|
||||
|
||||
#~ msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for class %(class)s"
|
||||
|
||||
#~ msgid "Add new holder for class: %s"
|
||||
#~ msgstr "add new holder for class: %s"
|
||||
|
||||
#~ msgid "List of classes"
|
||||
#~ msgstr "List of classes"
|
||||
|
||||
@@ -4,235 +4,217 @@
|
||||
#
|
||||
# Translators:
|
||||
# Translators:
|
||||
# www.ping.ba <jomer@ping.ba>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-05-15 18:59-0400\n"
|
||||
"PO-Revision-Date: 2014-10-25 06:47+0000\n"
|
||||
"POT-Creation-Date: 2015-09-24 16:24-0400\n"
|
||||
"PO-Revision-Date: 2015-09-24 05:15+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Bosnian (Bosnia and Herzegovina) (http://www.transifex.com/projects/p/mayan-edms/language/bs_BA/)\n"
|
||||
"Language-Team: Bosnian (Bosnia and Herzegovina) (http://www.transifex.com/rosarior/mayan-edms/language/bs_BA/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: bs_BA\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: forms.py:25 links.py:13 links.py:19
|
||||
msgid "New holder"
|
||||
msgstr "Novi posjednik"
|
||||
|
||||
#: forms.py:42
|
||||
msgid "Users"
|
||||
msgstr "Korisnici"
|
||||
|
||||
#: forms.py:45
|
||||
msgid "Groups"
|
||||
msgstr "Grupe"
|
||||
|
||||
#: forms.py:48
|
||||
msgid "Roles"
|
||||
msgstr "Role"
|
||||
|
||||
#: forms.py:51
|
||||
msgid "Special"
|
||||
msgstr "Posebno"
|
||||
|
||||
#: links.py:9
|
||||
#: apps.py:14 links.py:30
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: links.py:10 links.py:18
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:11 links.py:20
|
||||
msgid "Grant"
|
||||
#: apps.py:20 links.py:38 models.py:36
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:12 links.py:21
|
||||
msgid "Revoke"
|
||||
#: apps.py:24 models.py:38
|
||||
#| msgid "Roles"
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15
|
||||
msgid "Default ACLs"
|
||||
msgstr "Difoltne ACLs"
|
||||
|
||||
#: links.py:16 views.py:379
|
||||
msgid "Classes"
|
||||
#: links.py:26
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACLs za klasu"
|
||||
#: links.py:34
|
||||
#| msgid "View ACLs"
|
||||
msgid "New ACL"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:118 managers.py:130
|
||||
#: managers.py:72
|
||||
msgid "Insufficient access."
|
||||
msgstr "Nedovoljne dozvole."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "Permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
#: models.py:44
|
||||
msgid "Access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
#: models.py:45
|
||||
msgid "Access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "Default access entry"
|
||||
#: models.py:60
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "Default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108 models.py:111 models.py:112
|
||||
msgid "Creator"
|
||||
msgstr "Kreator"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Liste kontrole pristupa (ACLs)"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Izmjeniti ACLs"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "Pregledati ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Izmjeniti difoltne ACLs klase"
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Pregledati difoltne ACLs klase"
|
||||
|
||||
#: views.py:48
|
||||
#: views.py:61
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:402
|
||||
msgid "Holder"
|
||||
#: views.py:107
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:51 views.py:403
|
||||
msgid "Permissions"
|
||||
#: views.py:132
|
||||
#, python-format
|
||||
#| msgid "Default ACLs"
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:98
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
#: views.py:147
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:434
|
||||
msgid "Namespace"
|
||||
#: views.py:148
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:106 views.py:435
|
||||
msgid "Label"
|
||||
#: views.py:187
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:108 views.py:437
|
||||
msgid "Has permission"
|
||||
#: views.py:218
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: views.py:181 views.py:272 views.py:516 views.py:593
|
||||
msgid ", "
|
||||
msgstr ", "
|
||||
#~ msgid "New holder"
|
||||
#~ msgstr "New holder"
|
||||
|
||||
#: views.py:182 views.py:273 views.py:517 views.py:594
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr " za %s"
|
||||
#~ msgid "Users"
|
||||
#~ msgstr "Users"
|
||||
|
||||
#: views.py:183 views.py:518
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr " prema %s"
|
||||
#~ msgid "Groups"
|
||||
#~ msgstr "Groups"
|
||||
|
||||
#: views.py:186 views.py:521
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Jeste li sigurni da želite odobriti dozvolu %(title_suffix)s?"
|
||||
#~ msgid "Special"
|
||||
#~ msgstr "Special"
|
||||
|
||||
#: views.py:188 views.py:523
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Jeste li sigurni da želite odobriti dozvole %(title_suffix)s?"
|
||||
#~ msgid "Details"
|
||||
#~ msgstr "details"
|
||||
|
||||
#: views.py:195 views.py:530
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Dozvola \"%(permission)s\" odobrena za %(actor)s prema %(object)s."
|
||||
#~ msgid "Grant"
|
||||
#~ msgstr "grant"
|
||||
|
||||
#: views.py:201 views.py:536
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr "%(actor)s, već ima dozvolu \"%(permission)s\" prema %(object)s."
|
||||
#~ msgid "Revoke"
|
||||
#~ msgstr "revoke"
|
||||
|
||||
#: views.py:274 views.py:595
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr " od %s"
|
||||
#~ msgid "Classes"
|
||||
#~ msgstr "classes"
|
||||
|
||||
#: views.py:277 views.py:598
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Jeste li sigurni da želite ukinuti dozvolu %(title_suffix)s?"
|
||||
#~ msgid "ACLs for class"
|
||||
#~ msgstr "ACLs for class"
|
||||
|
||||
#: views.py:279 views.py:600
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "Jeste li sigurni da želite ukinuti dozvole %(title_suffix)s?"
|
||||
#~ msgid "Permission"
|
||||
#~ msgstr "permissions"
|
||||
|
||||
#: views.py:286 views.py:607
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr "Dozvola \"%(permission)s\" povučena za %(actor)s prema %(object)s."
|
||||
#~ msgid "Default access entry"
|
||||
#~ msgstr "default access entry"
|
||||
|
||||
#: views.py:292 views.py:613
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s, nije imao/la dozvolu \"%(permission)s\" prema %(object)s."
|
||||
#~ msgid "Default access entries"
|
||||
#~ msgstr "default access entries"
|
||||
|
||||
#: views.py:346
|
||||
#, python-format
|
||||
msgid "Add new holder for: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Creator"
|
||||
#~ msgstr "Creator"
|
||||
|
||||
#: views.py:347 views.py:477
|
||||
msgid "Select"
|
||||
msgstr "Odabrati"
|
||||
#~ msgid "Edit class default ACLs"
|
||||
#~ msgstr "Edit class default ACLs"
|
||||
|
||||
#: views.py:381
|
||||
msgid "Class"
|
||||
msgstr ""
|
||||
#~ msgid "View class default ACLs"
|
||||
#~ msgstr "View class default ACLs"
|
||||
|
||||
#: views.py:400
|
||||
#, python-format
|
||||
msgid "Default access control lists for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Holder"
|
||||
#~ msgstr "holder"
|
||||
|
||||
#: views.py:428
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
#~ msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for %(obj)s"
|
||||
|
||||
#: views.py:475
|
||||
#, python-format
|
||||
msgid "Add new holder for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Namespace"
|
||||
#~ msgstr "namespace"
|
||||
|
||||
#~ msgid "Label"
|
||||
#~ msgstr "label"
|
||||
|
||||
#~ msgid ", "
|
||||
#~ msgstr ", "
|
||||
|
||||
#~ msgid " for %s"
|
||||
#~ msgstr " for %s"
|
||||
|
||||
#~ msgid " to %s"
|
||||
#~ msgstr " to %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
#~ msgstr ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
|
||||
#~ msgid " from %s"
|
||||
#~ msgstr " from %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
#~ msgstr "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
|
||||
#~ msgid "Add new holder for: %s"
|
||||
#~ msgstr "add new holder for: %s"
|
||||
|
||||
#~ msgid "Select"
|
||||
#~ msgstr "Select"
|
||||
|
||||
#~ msgid "Class"
|
||||
#~ msgstr "class"
|
||||
|
||||
#~ msgid "Default access control lists for class: %s"
|
||||
#~ msgstr "default access control lists for class: %s"
|
||||
|
||||
#~ msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for class %(class)s"
|
||||
|
||||
#~ msgid "Add new holder for class: %s"
|
||||
#~ msgstr "add new holder for class: %s"
|
||||
|
||||
#~ msgid "List of classes"
|
||||
#~ msgstr "List of classes"
|
||||
|
||||
@@ -8,93 +8,55 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-05-15 18:59-0400\n"
|
||||
"PO-Revision-Date: 2014-10-25 06:47+0000\n"
|
||||
"POT-Creation-Date: 2015-09-24 16:24-0400\n"
|
||||
"PO-Revision-Date: 2015-09-24 05:15+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Danish (http://www.transifex.com/projects/p/mayan-edms/language/da/)\n"
|
||||
"Language-Team: Danish (http://www.transifex.com/rosarior/mayan-edms/language/da/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: da\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:25 links.py:13 links.py:19
|
||||
msgid "New holder"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:42
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:45
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:48
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:51
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:9
|
||||
#: apps.py:14 links.py:30
|
||||
msgid "ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:10 links.py:18
|
||||
msgid "Details"
|
||||
#: apps.py:20 links.py:38 models.py:36
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:11 links.py:20
|
||||
msgid "Grant"
|
||||
#: apps.py:24 models.py:38
|
||||
#| msgid "Roles"
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:12 links.py:21
|
||||
msgid "Revoke"
|
||||
#: links.py:26
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15
|
||||
msgid "Default ACLs"
|
||||
#: links.py:34
|
||||
#| msgid "View ACLs"
|
||||
msgid "New ACL"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:16 views.py:379
|
||||
msgid "Classes"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17
|
||||
msgid "ACLs for class"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:118 managers.py:130
|
||||
#: managers.py:72
|
||||
msgid "Insufficient access."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "Permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
#: models.py:44
|
||||
msgid "Access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
#: models.py:45
|
||||
msgid "Access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "Default access entry"
|
||||
#: models.py:60
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "Default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108 models.py:111 models.py:112
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
@@ -102,136 +64,157 @@ msgstr ""
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
#: permissions.py:13
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:48
|
||||
#: views.py:61
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:402
|
||||
msgid "Holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:51 views.py:403
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:98
|
||||
#: views.py:107
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:434
|
||||
msgid "Namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:106 views.py:435
|
||||
msgid "Label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:108 views.py:437
|
||||
msgid "Has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:181 views.py:272 views.py:516 views.py:593
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:182 views.py:273 views.py:517 views.py:594
|
||||
#: views.py:132
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
#| msgid "Default ACLs"
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:183 views.py:518
|
||||
#: views.py:147
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:148
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:187
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:218
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: views.py:186 views.py:521
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
#~ msgid "New holder"
|
||||
#~ msgstr "New holder"
|
||||
|
||||
#: views.py:188 views.py:523
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
#~ msgid "Users"
|
||||
#~ msgstr "Users"
|
||||
|
||||
#: views.py:195 views.py:530
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "Groups"
|
||||
#~ msgstr "Groups"
|
||||
|
||||
#: views.py:201 views.py:536
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "Special"
|
||||
#~ msgstr "Special"
|
||||
|
||||
#: views.py:274 views.py:595
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr ""
|
||||
#~ msgid "Details"
|
||||
#~ msgstr "details"
|
||||
|
||||
#: views.py:277 views.py:598
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
#~ msgid "Grant"
|
||||
#~ msgstr "grant"
|
||||
|
||||
#: views.py:279 views.py:600
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
#~ msgid "Revoke"
|
||||
#~ msgstr "revoke"
|
||||
|
||||
#: views.py:286 views.py:607
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "Classes"
|
||||
#~ msgstr "classes"
|
||||
|
||||
#: views.py:292 views.py:613
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
#~ msgid "ACLs for class"
|
||||
#~ msgstr "ACLs for class"
|
||||
|
||||
#: views.py:346
|
||||
#, python-format
|
||||
msgid "Add new holder for: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Permission"
|
||||
#~ msgstr "permissions"
|
||||
|
||||
#: views.py:347 views.py:477
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
#~ msgid "Default access entry"
|
||||
#~ msgstr "default access entry"
|
||||
|
||||
#: views.py:381
|
||||
msgid "Class"
|
||||
msgstr ""
|
||||
#~ msgid "Default access entries"
|
||||
#~ msgstr "default access entries"
|
||||
|
||||
#: views.py:400
|
||||
#, python-format
|
||||
msgid "Default access control lists for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "Creator"
|
||||
#~ msgstr "Creator"
|
||||
|
||||
#: views.py:428
|
||||
#, python-format
|
||||
msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
#~ msgid "Edit class default ACLs"
|
||||
#~ msgstr "Edit class default ACLs"
|
||||
|
||||
#: views.py:475
|
||||
#, python-format
|
||||
msgid "Add new holder for class: %s"
|
||||
msgstr ""
|
||||
#~ msgid "View class default ACLs"
|
||||
#~ msgstr "View class default ACLs"
|
||||
|
||||
#~ msgid "Holder"
|
||||
#~ msgstr "holder"
|
||||
|
||||
#~ msgid "Permissions available to: %(actor)s for %(obj)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for %(obj)s"
|
||||
|
||||
#~ msgid "Namespace"
|
||||
#~ msgstr "namespace"
|
||||
|
||||
#~ msgid "Label"
|
||||
#~ msgstr "label"
|
||||
|
||||
#~ msgid ", "
|
||||
#~ msgstr ", "
|
||||
|
||||
#~ msgid " for %s"
|
||||
#~ msgstr " for %s"
|
||||
|
||||
#~ msgid " to %s"
|
||||
#~ msgstr " to %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
#~ msgstr ""
|
||||
#~ "%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
#~ "%(object)s."
|
||||
|
||||
#~ msgid " from %s"
|
||||
#~ msgstr " from %s"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
#~ msgstr "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
|
||||
#~ msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
#~ msgstr "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
|
||||
#~ msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
#~ msgstr "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
|
||||
#~ msgid "Add new holder for: %s"
|
||||
#~ msgstr "add new holder for: %s"
|
||||
|
||||
#~ msgid "Select"
|
||||
#~ msgstr "Select"
|
||||
|
||||
#~ msgid "Class"
|
||||
#~ msgstr "class"
|
||||
|
||||
#~ msgid "Default access control lists for class: %s"
|
||||
#~ msgstr "default access control lists for class: %s"
|
||||
|
||||
#~ msgid "Permissions available to: %(actor)s for class %(class)s"
|
||||
#~ msgstr "permissions available to: %(actor)s for class %(class)s"
|
||||
|
||||
#~ msgid "Add new holder for class: %s"
|
||||
#~ msgstr "add new holder for class: %s"
|
||||
|
||||
#~ msgid "List of classes"
|
||||
#~ msgstr "List of classes"
|
||||
|
||||