Compare commits
526 Commits
feature/er
...
features/f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
757cf3d869 | ||
|
|
5ea0b02964 | ||
|
|
3346a88f81 | ||
|
|
56c8e2741b | ||
|
|
6a2e039a83 | ||
|
|
d4a7592467 | ||
|
|
9edb9fff0a | ||
|
|
07e7b55686 | ||
|
|
268fce138d | ||
|
|
916ba688b1 | ||
|
|
4baeb6ce7e | ||
|
|
fbe0e14b82 | ||
|
|
410e6a4a55 | ||
|
|
38a34cc98c | ||
|
|
90393e043e | ||
|
|
9e3e0d9e64 | ||
|
|
818cf97d5b | ||
|
|
f649a77b2f | ||
|
|
2ee2b2f5e0 | ||
|
|
5619a6014e | ||
|
|
4851c9f6d7 | ||
|
|
f002d8b38e | ||
|
|
484f09db75 | ||
|
|
5b45769423 | ||
|
|
54c007b149 | ||
|
|
3b518998c9 | ||
|
|
0a21748b0c | ||
|
|
edd6f4eb76 | ||
|
|
f8258c078a | ||
|
|
b2cefa79a5 | ||
|
|
ab5028887c | ||
|
|
4a03e2a47f | ||
|
|
c9809becba | ||
|
|
a1fa6aadfb | ||
|
|
c3991c3798 | ||
|
|
66ac9eebee | ||
|
|
4f9c2314fa | ||
|
|
b2ddf0c6bb | ||
|
|
ebc7886c81 | ||
|
|
fbbc6bace9 | ||
|
|
811c8075ca | ||
|
|
de7a7448ae | ||
|
|
7d725f8170 | ||
|
|
8e32c5adae | ||
|
|
7339eb2a09 | ||
|
|
e5daea674f | ||
|
|
170434e71b | ||
|
|
54acf0f254 | ||
|
|
76f320faf5 | ||
|
|
21e1a3c4ad | ||
|
|
0a9c01cb0f | ||
|
|
a5ab9f3ea6 | ||
|
|
8586bd1909 | ||
|
|
62f49e390a | ||
|
|
dfb368e6dc | ||
|
|
7971b081a9 | ||
|
|
290dc847c4 | ||
|
|
1982c9920f | ||
|
|
1ae1804f5d | ||
|
|
e68928901e | ||
|
|
febc7cf4f7 | ||
|
|
ab97c95bab | ||
|
|
b28bdf5475 | ||
|
|
f041ae9966 | ||
|
|
2e632f658d | ||
|
|
6ef9b04d57 | ||
|
|
b687a7f519 | ||
|
|
ebf8cbdd62 | ||
|
|
d338da5491 | ||
|
|
2e2797bba5 | ||
|
|
2b43aa8d40 | ||
|
|
c59f35225c | ||
|
|
3a623ee416 | ||
|
|
4e5c513529 | ||
|
|
8b073c3151 | ||
|
|
60c0c131ae | ||
|
|
f561eb2f57 | ||
|
|
a0b4d38d19 | ||
|
|
a69e74ac90 | ||
|
|
d41fe1b701 | ||
|
|
2f998ab4ce | ||
|
|
92e12f3ec5 | ||
|
|
78b0abf50c | ||
|
|
d003818cae | ||
|
|
98157b7083 | ||
|
|
d4130cd393 | ||
|
|
f3a849c031 | ||
|
|
a38426d823 | ||
|
|
501acbfb0f | ||
|
|
082981e25f | ||
|
|
03f128ff23 | ||
|
|
f76b9e4f3f | ||
|
|
1acc352801 | ||
|
|
17030472f1 | ||
|
|
c7e9a4dc99 | ||
|
|
0d53e74238 | ||
|
|
4617afafb2 | ||
|
|
2d819e64c9 | ||
|
|
545366a477 | ||
|
|
74ec939779 | ||
|
|
aa94247c3d | ||
|
|
c3594651d2 | ||
|
|
578c1b2f07 | ||
|
|
7cf8cd2f28 | ||
|
|
f6696771f9 | ||
|
|
eb79ebf6bb | ||
|
|
e89367f827 | ||
|
|
40035ea39a | ||
|
|
8aa97c7fd7 | ||
|
|
45ca7ea480 | ||
|
|
bbf3ede2e6 | ||
|
|
c1612c8182 | ||
|
|
76b75af1c2 | ||
|
|
680a7b6ae1 | ||
|
|
f73179a600 | ||
|
|
cbd51c5f26 | ||
|
|
fffcf4d3da | ||
|
|
72cdfe58c5 | ||
|
|
f55979b1a6 | ||
|
|
f5aaff9ab1 | ||
|
|
e6ccfb4b59 | ||
|
|
f6afec031d | ||
|
|
33a2ca97ec | ||
|
|
7b69c2f76e | ||
|
|
6cc23fbfd0 | ||
|
|
648fcc32a9 | ||
|
|
de581cde5f | ||
|
|
1beb44d85d | ||
|
|
e5c1aa5606 | ||
|
|
0b68463ed5 | ||
|
|
d533e48f46 | ||
|
|
8e5b60e1c0 | ||
|
|
28114264c1 | ||
|
|
6330e40036 | ||
|
|
f69fcbcc82 | ||
|
|
5e4518211f | ||
|
|
ddbb0d496a | ||
|
|
e1e2454e2a | ||
|
|
264e90a7d7 | ||
|
|
4507f75711 | ||
|
|
a0d2000419 | ||
|
|
ebc68d3c36 | ||
|
|
7a4a4818fe | ||
|
|
b6e7a462b0 | ||
|
|
0d6409512a | ||
|
|
988b4dcb37 | ||
|
|
9e2891216b | ||
|
|
0e6f34d0ee | ||
|
|
00d4406b1f | ||
|
|
4a7540f8b2 | ||
|
|
95a1df8072 | ||
|
|
7181852c2d | ||
|
|
547ffe0e0d | ||
|
|
5e2a1e997b | ||
|
|
ca3a48f92d | ||
|
|
251b4bac40 | ||
|
|
ce70701b7e | ||
|
|
3c0316dae6 | ||
|
|
030b7d5d91 | ||
|
|
99b180f269 | ||
|
|
c9b5d2794e | ||
|
|
d7db8468ac | ||
|
|
3d240a7f42 | ||
|
|
9c92b9a59e | ||
|
|
b67bfa8ec4 | ||
|
|
8e731d6280 | ||
|
|
d271f1503d | ||
|
|
5f89d228dc | ||
|
|
73546bd99f | ||
|
|
8320ca814c | ||
|
|
48a7a25212 | ||
|
|
a3ea854e73 | ||
|
|
bd9c75cdaa | ||
|
|
ea3b513ae3 | ||
|
|
11e13cea1d | ||
|
|
3faefd653c | ||
|
|
80a9b9ef9d | ||
|
|
8084b59e6e | ||
|
|
8b2f5eaf69 | ||
|
|
98e51079a3 | ||
|
|
a2e718361e | ||
|
|
e042c5275b | ||
|
|
b4227a608b | ||
|
|
fda0dd4eaf | ||
|
|
66d5016407 | ||
|
|
77d897ab1f | ||
|
|
68a4b72c37 | ||
|
|
8b447a7050 | ||
|
|
e36eb5421d | ||
|
|
d0a452d838 | ||
|
|
825af3152f | ||
|
|
efff750f06 | ||
|
|
ae595dd359 | ||
|
|
136434c973 | ||
|
|
b1e464f52f | ||
|
|
6a8b062be7 | ||
|
|
2e670254e5 | ||
|
|
d2ab2ec91f | ||
|
|
cfe623e093 | ||
|
|
aee3645c7a | ||
|
|
bd1e8d9e31 | ||
|
|
713e644599 | ||
|
|
a544924c08 | ||
|
|
ae8a444e42 | ||
|
|
e01017ffe5 | ||
|
|
85deaf3327 | ||
|
|
f057d7f81f | ||
|
|
e916e73ead | ||
|
|
5c07c61b69 | ||
|
|
395c360784 | ||
|
|
959cdc56e5 | ||
|
|
7a4c9f3ad2 | ||
|
|
5a736d83bc | ||
|
|
33056dec04 | ||
|
|
dda0f0d2af | ||
|
|
8374a66011 | ||
|
|
873055c4d5 | ||
|
|
4963a9689f | ||
|
|
1a91640047 | ||
|
|
2e9b5454a7 | ||
|
|
6069c67342 | ||
|
|
95123e0078 | ||
|
|
8bbd83ea76 | ||
|
|
4f92bde7d7 | ||
|
|
041464fc1c | ||
|
|
086a1e5168 | ||
|
|
32cf0a0595 | ||
|
|
e5aa4553be | ||
|
|
dcde4b1968 | ||
|
|
84c88f9173 | ||
|
|
799d47054e | ||
|
|
3fa08debe9 | ||
|
|
cd5bc8ba4b | ||
|
|
89bc78bd55 | ||
|
|
ebaa18f552 | ||
|
|
e80f602974 | ||
|
|
cd24eef107 | ||
|
|
e6ad202ee9 | ||
|
|
dd81d8e237 | ||
|
|
6e91ebe5f4 | ||
|
|
f9866e846a | ||
|
|
fba0c40bef | ||
|
|
74c97314d7 | ||
|
|
20acc24c7f | ||
|
|
1c5681c79d | ||
|
|
4b4629ce2b | ||
|
|
fb1f5dbfe3 | ||
|
|
510cdf894c | ||
|
|
2f8cd26d0f | ||
|
|
1a71e02aab | ||
|
|
b3b92e8cda | ||
|
|
5574aaec9e | ||
|
|
3f9421fc75 | ||
|
|
2aadb203eb | ||
|
|
f5ec2e9b22 | ||
|
|
46d0e5562b | ||
|
|
52f734ee9f | ||
|
|
a556f2a1ba | ||
|
|
fa076df89e | ||
|
|
2330bb9da2 | ||
|
|
c2d287c262 | ||
|
|
fcfadb0caa | ||
|
|
575b2bc61c | ||
|
|
21c1dc36d8 | ||
|
|
5cde7de29b | ||
|
|
4d99590dad | ||
|
|
296c580a5e | ||
|
|
2619777d41 | ||
|
|
a5f3937228 | ||
|
|
2e8e4588c0 | ||
|
|
120896001f | ||
|
|
9a706ac09f | ||
|
|
a97c2ec662 | ||
|
|
6ad306b3cf | ||
|
|
b766f85995 | ||
|
|
25ad5c1420 | ||
|
|
a1c733807a | ||
|
|
720115e122 | ||
|
|
e75b5ea2ff | ||
|
|
2300ab52de | ||
|
|
d790efdef5 | ||
|
|
47a8355c79 | ||
|
|
d297d734d2 | ||
|
|
3789d5cfcf | ||
|
|
87b0be65d4 | ||
|
|
ff5d35832a | ||
|
|
4ffd25c570 | ||
|
|
cd00c6abf0 | ||
|
|
c1d2c8baf3 | ||
|
|
0dbb6cc6ea | ||
|
|
6f57d3c650 | ||
|
|
d48665c595 | ||
|
|
b44e4141a4 | ||
|
|
41c1326498 | ||
|
|
3d8cf3e235 | ||
|
|
ddf96120de | ||
|
|
a6d474eaa5 | ||
|
|
9f723c95ac | ||
|
|
4b3d94017a | ||
|
|
48249b977d | ||
|
|
26792d3c5a | ||
|
|
042745e0ca | ||
|
|
1a79b4192e | ||
|
|
fddd8a56c2 | ||
|
|
4fed1111f4 | ||
|
|
e609e89e0e | ||
|
|
3043f22de8 | ||
|
|
1265c16161 | ||
|
|
0865975f2e | ||
|
|
18dbb0cfe6 | ||
|
|
ef26296dc6 | ||
|
|
0a39eac419 | ||
|
|
9aa9840231 | ||
|
|
1acf67a91c | ||
|
|
d66cf089ee | ||
|
|
fb04d75376 | ||
|
|
966641c447 | ||
|
|
e12098abe4 | ||
|
|
724f15c006 | ||
|
|
fb6d7b5668 | ||
|
|
eccc2d74a3 | ||
|
|
3437d8b471 | ||
|
|
7f0377a8c5 | ||
|
|
ce0a6368f2 | ||
|
|
66e0d9f357 | ||
|
|
bc08ada938 | ||
|
|
eadcf7382b | ||
|
|
75ed93c35b | ||
|
|
1e37ca8315 | ||
|
|
d410e1ef6c | ||
|
|
a3e8b53f01 | ||
|
|
9ebace4014 | ||
|
|
c04063838b | ||
|
|
8c5c324a09 | ||
|
|
655e2b3469 | ||
|
|
02187ab5a5 | ||
|
|
c9bd2ab9a5 | ||
|
|
90b3d01171 | ||
|
|
5cfc5dda92 | ||
|
|
64cd0c232d | ||
|
|
d7a5db711b | ||
|
|
102e3ccde3 | ||
|
|
6b76d62fda | ||
|
|
caad463e8a | ||
|
|
fa441149e4 | ||
|
|
ba73a9b55e | ||
|
|
0267c79b07 | ||
|
|
bfcad278aa | ||
|
|
33d073e7a0 | ||
|
|
54020a8813 | ||
|
|
97a9d21ac4 | ||
|
|
f176f6ae4f | ||
|
|
313311d008 | ||
|
|
0e1fe3968d | ||
|
|
4c0b3e9134 | ||
|
|
0d1daeaedf | ||
|
|
6bd8206236 | ||
|
|
156c008eee | ||
|
|
b829f0a20a | ||
|
|
4b625025ee | ||
|
|
b3da28e915 | ||
|
|
2f5a0d071f | ||
|
|
0cdba79738 | ||
|
|
030ee8efe3 | ||
|
|
7be25df7d0 | ||
|
|
847bfb721b | ||
|
|
50be0ad889 | ||
|
|
58813310b7 | ||
|
|
811a752efb | ||
|
|
29f81b2087 | ||
|
|
5071eb6fda | ||
|
|
29b41a7638 | ||
|
|
b6976210a5 | ||
|
|
0d2a827413 | ||
|
|
cdb55ab5dd | ||
|
|
0d69274bb4 | ||
|
|
cb102ed115 | ||
|
|
78517971ed | ||
|
|
5ef73d992c | ||
|
|
0d05589206 | ||
|
|
afc65eed32 | ||
|
|
acffe8a721 | ||
|
|
6411433b24 | ||
|
|
5127712711 | ||
|
|
33f84ec327 | ||
|
|
3bcadd047b | ||
|
|
c34ec5ddab | ||
|
|
4f772bbecf | ||
|
|
18faaa69bd | ||
|
|
24304636d9 | ||
|
|
9b2633e6c7 | ||
|
|
7752ca0f03 | ||
|
|
421d91bb0f | ||
|
|
9e262220e5 | ||
|
|
2a780cb4b0 | ||
|
|
94b9db7f27 | ||
|
|
c0f51103d2 | ||
|
|
334f0cd03f | ||
|
|
655c1fd09f | ||
|
|
663eb1b360 | ||
|
|
0015ad4abe | ||
|
|
e2b5817d18 | ||
|
|
f6089e689e | ||
|
|
f3413b4283 | ||
|
|
0d4ab4f2cf | ||
|
|
d42b9bbdf4 | ||
|
|
72311c73b5 | ||
|
|
93c4814a89 | ||
|
|
7823c80710 | ||
|
|
2d9cdbe8b0 | ||
|
|
fdacbb94c3 | ||
|
|
3f1caf8da0 | ||
|
|
f8d5332786 | ||
|
|
1ccc631bd4 | ||
|
|
86183b873e | ||
|
|
56adf598ae | ||
|
|
fe1337fa8d | ||
|
|
16915b6480 | ||
|
|
15c8459a15 | ||
|
|
feb9d9e714 | ||
|
|
a8fd2a1136 | ||
|
|
9c571b222e | ||
|
|
37840f3b6c | ||
|
|
927d77cfd7 | ||
|
|
265bcd7b65 | ||
|
|
c69127f37c | ||
|
|
45ae821f5c | ||
|
|
1f8879df92 | ||
|
|
7093ac54a3 | ||
|
|
5118cad9a2 | ||
|
|
2b0b9675fd | ||
|
|
40c9436071 | ||
|
|
b976f8d0ed | ||
|
|
a54e17caeb | ||
|
|
0416ac4064 | ||
|
|
1fa91f0ef7 | ||
|
|
fab94319bb | ||
|
|
5ff15895b6 | ||
|
|
0188afcd54 | ||
|
|
ae814a18c5 | ||
|
|
1f5dffa0e5 | ||
|
|
4d91d82515 | ||
|
|
4c8e647415 | ||
|
|
14e71ce42f | ||
|
|
f6f9287e33 | ||
|
|
456c322c19 | ||
|
|
a12c90268f | ||
|
|
a10f2330fd | ||
|
|
03ba13e5cb | ||
|
|
335c21488e | ||
|
|
d26279275d | ||
|
|
4f66129a7c | ||
|
|
7d756de3de | ||
|
|
69bd6c116e | ||
|
|
0065edfae9 | ||
|
|
9ec021241c | ||
|
|
3a60155bfa | ||
|
|
f6a0a421a5 | ||
|
|
7ed26f4d4c | ||
|
|
daca9dd539 | ||
|
|
8c1a9c8798 | ||
|
|
966d8498bc | ||
|
|
36a51eeb73 | ||
|
|
382173351a | ||
|
|
d35323aa65 | ||
|
|
9b21275b7e | ||
|
|
d493ec34b2 | ||
|
|
51ea493a26 | ||
|
|
49403978b1 | ||
|
|
8c770d5ba3 | ||
|
|
b01e8707a3 | ||
|
|
8896f58d6f | ||
|
|
3afb74224d | ||
|
|
3a4f97c5c2 | ||
|
|
8419facb8a | ||
|
|
3cbc6435a2 | ||
|
|
e7627a723e | ||
|
|
e77afeee37 | ||
|
|
6a5a2350bb | ||
|
|
912675bf99 | ||
|
|
a56e3ca111 | ||
|
|
5f877cdc22 | ||
|
|
d5efd53b5b | ||
|
|
c156c02376 | ||
|
|
a196205593 | ||
|
|
26cf7fb97c | ||
|
|
863892f909 | ||
|
|
5a64a3e833 | ||
|
|
45786005ab | ||
|
|
f45384e399 | ||
|
|
33a542b9d5 | ||
|
|
00d07214b1 | ||
|
|
1e8030a722 | ||
|
|
f6404fbd4b | ||
|
|
b59c39261f | ||
|
|
a5b513f986 | ||
|
|
45a688749c | ||
|
|
15473620c4 | ||
|
|
7cd0e16cc2 | ||
|
|
caab7b3b59 | ||
|
|
47d850e164 | ||
|
|
b27e160d15 | ||
|
|
3eb4a70fbf | ||
|
|
d4df7e69d7 | ||
|
|
0055429703 | ||
|
|
eafdfd8177 | ||
|
|
a8e52126f5 | ||
|
|
70facb96f0 | ||
|
|
f583e24c47 | ||
|
|
7db27aa9fe | ||
|
|
f5bc055a11 | ||
|
|
965160b7a2 | ||
|
|
85b3164592 | ||
|
|
7634d9e5da | ||
|
|
48253f3f85 | ||
|
|
dd2c64d453 | ||
|
|
517c05a9c2 | ||
|
|
99bbe7d47c | ||
|
|
586d41eeff | ||
|
|
7fb18b14eb | ||
|
|
68398e2ce6 | ||
|
|
d23f5eb540 | ||
|
|
4bbd5dab70 | ||
|
|
c4b9ae596e | ||
|
|
5c9ff90d28 | ||
|
|
f5d2f34e30 |
@@ -4,8 +4,7 @@ HISTORY.md
|
||||
mayan/media
|
||||
db.sqlite*
|
||||
docker
|
||||
!docker/etc
|
||||
!docker/entrypoint.sh
|
||||
!docker/version
|
||||
!docker/rootfs
|
||||
./.*
|
||||
docs
|
||||
|
||||
|
||||
3
.flake8
3
.flake8
@@ -1,2 +1,3 @@
|
||||
[flake8]
|
||||
ignore = E501
|
||||
exclude = node_modules,static,templates
|
||||
ignore = E501, N801, N802, N804, N805, N806
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@
|
||||
.coverage
|
||||
.coverage.tox*
|
||||
.idea/
|
||||
*.swp
|
||||
.tox/
|
||||
.vagrant
|
||||
_build/
|
||||
|
||||
@@ -119,7 +119,7 @@ job_build_python:
|
||||
- update-locale LANG=en_US.UTF-8
|
||||
- export LC_ALL=en_US.UTF-8
|
||||
- pip install -r requirements/build.txt
|
||||
- make wheel
|
||||
- make python-wheel
|
||||
only:
|
||||
- releases/all
|
||||
- releases/python
|
||||
@@ -140,7 +140,7 @@ job_push_python:
|
||||
|
||||
.test_base: &test_base
|
||||
stage: test
|
||||
image: ubuntu:16.04
|
||||
image: ubuntu:18.04
|
||||
cache:
|
||||
paths:
|
||||
- ~/.cache/pip/
|
||||
@@ -152,8 +152,8 @@ job_push_python:
|
||||
- locale-gen en_US.UTF-8
|
||||
- update-locale LANG=en_US.UTF-8
|
||||
- export LC_ALL=en_US.UTF-8
|
||||
- apt-get install -qq curl gcc ghostscript gpgv gnupg graphviz libfuse2 libjpeg-dev libmagic1 libpng-dev libtiff-dev poppler-utils libreoffice poppler-utils python-dev python-pip tesseract-ocr tesseract-ocr-deu
|
||||
- pip install -r requirements/testing.txt
|
||||
- apt-get install -qq curl exiftool gcc ghostscript gnupg1 graphviz libfuse2 libjpeg-dev libmagic1 libpng-dev libtiff-dev poppler-utils libreoffice poppler-utils python-dev python-pip tesseract-ocr tesseract-ocr-deu
|
||||
- pip install -r requirements.txt -r requirements/testing-base.txt
|
||||
only:
|
||||
- releases/all
|
||||
- releases/docker
|
||||
@@ -171,7 +171,7 @@ test-mysql:
|
||||
- mysql:8.0.3
|
||||
script:
|
||||
- apt-get install -qq libmysqlclient-dev mysql-client
|
||||
- pip install mysql-python
|
||||
- pip install mysqlclient
|
||||
- mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD" -e "set global character_set_server=utf8mb4;"
|
||||
- python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci.db_mysql --nomigrations
|
||||
tags:
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[settings]
|
||||
default_section = THIRDPARTY
|
||||
known_first_party = mayan
|
||||
known_django = django
|
||||
multi_line_output = 5
|
||||
sections = FUTURE,STDLIB,DJANGO,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
|
||||
30
.tx/config
30
.tx/config
@@ -55,18 +55,18 @@ source_lang = en
|
||||
source_file = mayan/apps/dashboards/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.dependencies-3-0]
|
||||
file_filter = mayan/apps/dependencies/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/dependencies/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[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.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.document_comments-2-0]
|
||||
file_filter = mayan/apps/document_comments/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
@@ -97,6 +97,12 @@ source_lang = en
|
||||
source_file = mayan/apps/document_states/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[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.dynamic_search-2-0]
|
||||
file_filter = mayan/apps/dynamic_search/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
@@ -109,10 +115,10 @@ source_lang = en
|
||||
source_file = mayan/apps/events/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.file_caching-2-0]
|
||||
file_filter = mayan/apps/file_caching/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.file_metadata-3-0]
|
||||
file_filter = mayan/apps/file_metadata/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/file_caching/locale/en/LC_MESSAGES/django.po
|
||||
source_file = mayan/apps/file_metadata/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.linking-2-0]
|
||||
@@ -163,6 +169,12 @@ source_lang = en
|
||||
source_file = mayan/apps/permissions/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.platform-2-0]
|
||||
file_filter = mayan/apps/platform/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/platform/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.rest_api-2-0]
|
||||
file_filter = mayan/apps/rest_api/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
|
||||
@@ -23,7 +23,7 @@ with deployments, webservers, cloud providers, etc.
|
||||
Code
|
||||
----
|
||||
|
||||
1. Complete and mail, or scan and email the corresponding Contributor Assignment Agreement: [Mayan EDMS Individual Contributor Assignment Agreement](https://docs.mayan-edms.com/topics/caa_individual.rst) or [Mayan EDMS Entity Contributor Assignment Agreement](https://docs.mayan-edms.com/topics/topics/caa_entity.rst).
|
||||
1. Complete and mail, or scan and email the corresponding Contributor Assignment Agreement: [Mayan EDMS Individual Contributor Assignment Agreement](https://gitlab.com/mayan-edms/mayan-edms/blob/master/docs/chapters/caa_individual.rst) or [Mayan EDMS Entity Contributor Assignment Agreement](https://gitlab.com/mayan-edms/mayan-edms/blob/master/docs/chapters/caa_entity.rst).
|
||||
1. Fork [the repository](http://gitlab.com/mayan-edms/mayan-edms).
|
||||
1. Choose the version for which you want to develop. The code is divided in the
|
||||
following branches:
|
||||
|
||||
711
HISTORY.rst
711
HISTORY.rst
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,6 @@
|
||||
include README.md LICENSE HISTORY.rst mayan/LICENSE
|
||||
recursive-include mayan/apps *.txt *.html *.css *.ico *.png *.jpg *.js *.po *.mo *.ttf *.woff *.woff2 *.gif *.eot *.svg *.doc *.pdf *.tiff *.sig *.asc *.gpg *.zip *.tar *.gz *.bz2 package.json
|
||||
global-exclude mayan/settings/local.py mayan/settings/travis/* mayan/media/*
|
||||
recursive-include mayan/apps *.txt *.html *.css *.ico *.png *.jpg *.js *.mo *.ttf *.woff *.woff2 *.gif *.eot *.svg *.doc *.pdf *.tiff *.sig *.asc *.gpg *.zip *.tar *.gz *.bz2 *.tmpl
|
||||
global-exclude mayan/settings/local.py *.po
|
||||
prune mayan/apps/*/static/*/node_modules/*
|
||||
prune mayan/settings/travis/*
|
||||
prune mayan/media/*
|
||||
|
||||
175
Makefile
175
Makefile
@@ -1,64 +1,20 @@
|
||||
.PHONY: clean-pyc clean-build
|
||||
|
||||
help: docker-help
|
||||
@echo
|
||||
@echo "**** Main makefile ****"
|
||||
@echo "clean-build - Remove build artifacts."
|
||||
@echo "clean-pyc - Remove Python artifacts."
|
||||
@echo "clean - Remove Python and build artifacts."
|
||||
@echo "generate-setup - Create and updated setup.py"
|
||||
@echo "check-readme - Checks validity of the README.rst file for PyPI publication."
|
||||
@echo "check-missing_migrations - Make sure all models have proper migrations."
|
||||
|
||||
@echo "test-all - Run all tests."
|
||||
@echo "test MODULE=<python module name> - Run tests for a single app, module or test class."
|
||||
@echo "test-with-postgres-all - Run all tests against a Postgres database container."
|
||||
@echo "test-postgres MODULE=<python module name> - Run tests for a single app, module or test class against a Postgres database container."
|
||||
@echo "test-with-mysql-all - Run all tests against a MySQL database container."
|
||||
@echo "test-mysql MODULE=<python module name> - Run tests for a single app, module or test class against a MySQL database container."
|
||||
@echo "test-with-oracle-all - Run all tests against a Oracle database container."
|
||||
@echo "test-oracle MODULE=<python module name> - Run tests for a single app, module or test class against a Oracle database container."
|
||||
|
||||
@echo "docs-serve - Run the livehtml documentation generator."
|
||||
|
||||
@echo "translations-make - Refresh all translation files."
|
||||
@echo "translations-compile - Compile all translation files."
|
||||
@echo "translations-push - Upload all translation files to Transifex."
|
||||
@echo "translations-pull - Download all translation files from Transifex."
|
||||
|
||||
@echo "sdist - Build the source distribution package."
|
||||
@echo "wheel - Build the wheel distribution package."
|
||||
@echo "release - Package (sdist and wheel) and upload a release."
|
||||
@echo "test-release - Package (sdist and wheel) and upload to the PyPI test server."
|
||||
@echo "release-test-via-docker-ubuntu - Package (sdist and wheel) and upload to the PyPI test server using an Ubuntu Docker builder."
|
||||
@echo "release-via-docker-ubuntu - Package (sdist and wheel) and upload to PyPI using an Ubuntu Docker builder."
|
||||
@echo "test-sdist-via-docker-ubuntu - Make an sdist packange and test it using an Ubuntu Docker container."
|
||||
@echo "test-wheel-via-docker-ubuntu - Make a wheel package and test it using an Ubuntu Docker container."
|
||||
@echo "runserver - Run the development server."
|
||||
@echo "runserver_plus - Run the Django extension's development server."
|
||||
@echo "shell_plus - Run the shell_plus command."
|
||||
|
||||
@echo "test-with-docker-services-on - Launch and initialize production-like services using Docker (Postgres and Redis)."
|
||||
@echo "test-with-docker-services-off - Stop and delete the Docker production-like services."
|
||||
@echo "test-with-docker-frontend - Launch a front end instance that uses the production-like services."
|
||||
@echo "test-with-docker-worker - Launch a worker instance that uses the production-like services."
|
||||
@echo "docker-mysql-on - Launch and initialize a MySQL Docker container."
|
||||
@echo "docker-mysql-off - Stop and delete the MySQL Docker container."
|
||||
@echo "docker-postgres-on - Launch and initialize a PostgreSQL Docker container."
|
||||
@echo "docker-postgres-off - Stop and delete the PostgreSQL Docker container."
|
||||
|
||||
@echo "safety-check - Run a package safety check."
|
||||
help:
|
||||
@echo "Usage: make <target>\n"
|
||||
@awk 'BEGIN {FS = ":.*##"} /^[a-zA-Z_-]+:.*?## / { printf " * %-40s -%s\n", $$1, $$2 }' $(MAKEFILE_LIST)|sort
|
||||
|
||||
# Cleaning
|
||||
|
||||
clean: ## Remove Python and build artifacts.
|
||||
clean: clean-build clean-pyc
|
||||
|
||||
clean-build:
|
||||
clean-build: ## Remove build artifacts.
|
||||
rm -fr build/
|
||||
rm -fr dist/
|
||||
rm -fr *.egg-info
|
||||
|
||||
clean-pyc:
|
||||
clean-pyc: ## Remove Python artifacts.
|
||||
find . -name '*.pyc' -exec rm -f {} +
|
||||
find . -name '*.pyo' -exec rm -f {} +
|
||||
find . -name '*~' -exec rm -f {} +
|
||||
@@ -66,25 +22,29 @@ clean-pyc:
|
||||
|
||||
# Testing
|
||||
|
||||
test:
|
||||
./manage.py test $(MODULE) --settings=mayan.settings.testing.development --nomigrations
|
||||
test: clean-pyc
|
||||
test: ## MODULE=<python module name> - Run tests for a single app, module or test class.
|
||||
./manage.py test $(MODULE) --settings=mayan.settings.testing.development --nomigrations $(ARGUMENTS)
|
||||
|
||||
test-all:
|
||||
./manage.py test --mayan-apps --settings=mayan.settings.testing.development --nomigrations
|
||||
test-all: ## Run all tests.
|
||||
test-all: clean-pyc
|
||||
./manage.py test --mayan-apps --settings=mayan.settings.testing.development --nomigrations $(ARGUMENTS)
|
||||
|
||||
test-launch-postgres:
|
||||
@docker rm -f test-postgres || true
|
||||
@docker volume rm test-postgres || true
|
||||
docker run -d --name test-postgres -p 5432:5432 -v test-postgres:/var/lib/postgresql/data healthcheck/postgres
|
||||
sudo apt-get install -qq libpq-dev
|
||||
sudo apt-get install -q libpq-dev
|
||||
pip install psycopg2
|
||||
while ! docker inspect --format='{{json .State.Health}}' test-postgres|grep 'Status":"healthy"'; do sleep 1; done
|
||||
|
||||
test-with-postgres: ## MODULE=<python module name> - Run tests for a single app, module or test class against a Postgres database container.
|
||||
test-with-postgres: test-launch-postgres
|
||||
./manage.py test $(MODULE) --settings=mayan.settings.testing.docker.db_postgres --nomigrations
|
||||
@docker rm -f test-postgres || true
|
||||
@docker volume rm test-postgres || true
|
||||
|
||||
test-with-postgres-all: ## Run all tests against a Postgres database container.
|
||||
test-with-postgres-all: test-launch-postgres
|
||||
./manage.py test --mayan-apps --settings=mayan.settings.testing.docker.db_postgres --nomigrations
|
||||
@docker rm -f test-postgres || true
|
||||
@@ -94,16 +54,19 @@ test-launch-mysql:
|
||||
@docker rm -f test-mysql || true
|
||||
@docker volume rm test-mysql || true
|
||||
docker run -d --name test-mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=True -e MYSQL_DATABASE=mayan -v test-mysql:/var/lib/mysql healthcheck/mysql
|
||||
sudo apt-get install -qq libmysqlclient-dev mysql-client
|
||||
pip install mysql-python
|
||||
sudo apt-get install -q libmysqlclient-dev mysql-client
|
||||
pip install mysqlclient
|
||||
while ! docker inspect --format='{{json .State.Health}}' test-mysql|grep 'Status":"healthy"'; do sleep 1; done
|
||||
mysql -h 127.0.0.1 -P 3306 -uroot -e "set global character_set_server=utf8mb4;"
|
||||
|
||||
test-with-mysql: ## MODULE=<python module name> - Run tests for a single app, module or test class against a MySQL database container.
|
||||
test-with-mysql: test-launch-mysql
|
||||
./manage.py test $(MODULE) --settings=mayan.settings.testing.docker.db_mysql --nomigrations
|
||||
@docker rm -f test-mysql || true
|
||||
@docker volume rm test-mysql || true
|
||||
|
||||
|
||||
test-with-mysql-all: ## Run all tests against a MySQL database container.
|
||||
test-with-mysql-all: test-launch-mysql
|
||||
./manage.py test --mayan-apps --settings=mayan.settings.testing.docker.db_mysql --nomigrations
|
||||
@docker rm -f test-mysql || true
|
||||
@@ -118,11 +81,13 @@ test-launch-oracle:
|
||||
while ! nc -z 127.0.0.1 49161; do sleep 1; done
|
||||
sleep 10
|
||||
|
||||
test-with-oracle: ## MODULE=<python module name> - Run tests for a single app, module or test class against a Oracle database container.
|
||||
test-with-oracle: test-launch-oracle
|
||||
./manage.py test $(MODULE) --settings=mayan.settings.testing.docker.db_oracle --nomigrations
|
||||
@docker rm -f test-oracle || true
|
||||
@docker volume rm test-oracle || true
|
||||
|
||||
test-with-oracle-all: ## Run all tests against a Oracle database container.
|
||||
test-with-oracle-all: test-launch-oracle
|
||||
./manage.py test --mayan-apps --settings=mayan.settings.testing.docker.db_oracle --nomigrations
|
||||
@docker rm -f test-oracle || true
|
||||
@@ -130,58 +95,56 @@ test-with-oracle-all: test-launch-oracle
|
||||
|
||||
# Documentation
|
||||
|
||||
docs-serve:
|
||||
docs-serve: ## Run the livehtml documentation generator.
|
||||
cd docs;make livehtml
|
||||
|
||||
docs-spellcheck:
|
||||
|
||||
docs-spellcheck: ## Spellcheck the documentation.
|
||||
sphinx-build -b spelling -d docs/_build/ docs docs/_build/spelling
|
||||
|
||||
# Translations
|
||||
|
||||
translations-make:
|
||||
translations-make: ## Refresh all translation files.
|
||||
contrib/scripts/process_messages.py -m
|
||||
|
||||
translations-compile:
|
||||
translations-compile: ## Compile all translation files.
|
||||
contrib/scripts/process_messages.py -c
|
||||
|
||||
translations-push:
|
||||
translations-push: ## Upload all translation files to Transifex.
|
||||
tx push -s
|
||||
|
||||
translations-pull:
|
||||
translations-pull: ## Download all translation files from Transifex.
|
||||
tx pull -f
|
||||
|
||||
|
||||
generate-setup:
|
||||
@./generate_setup.py
|
||||
@echo "Complete."
|
||||
|
||||
# Releases
|
||||
|
||||
increase-version:
|
||||
increase-version: ## Increase the version number of the entire project's files.
|
||||
@VERSION=`grep "__version__ =" mayan/__init__.py| cut -d\' -f 2|./increase_version.py - $(PART)`; \
|
||||
BUILD=`echo $$VERSION|awk '{split($$VERSION,a,"."); printf("0x%02d%02d%02d\n", a[1],a[2], a[3])}'`; \
|
||||
sed -i -e "s/__build__ = 0x[0-9]*/__build__ = $${BUILD}/g" mayan/__init__.py; \
|
||||
sed -i -e "s/__version__ = '[0-9\.]*'/__version__ = '$${VERSION}'/g" mayan/__init__.py; \
|
||||
echo $$VERSION > docker/version
|
||||
echo $$VERSION > docker/rootfs/version
|
||||
make generate-setup
|
||||
|
||||
test-release: clean wheel
|
||||
python-test-release: ## Package (sdist and wheel) and upload to the PyPI test server.
|
||||
python-test-release: clean wheel
|
||||
twine upload dist/* -r testpypi
|
||||
@echo "Test with: pip install -i https://testpypi.python.org/pypi mayan-edms"
|
||||
|
||||
release: clean wheel
|
||||
python-release: ## Package (sdist and wheel) and upload a release.
|
||||
python-release: clean python-wheel
|
||||
twine upload dist/* -r pypi
|
||||
|
||||
sdist: clean
|
||||
python-sdist: ## Build the source distribution package.
|
||||
python-sdist: clean
|
||||
python setup.py sdist
|
||||
ls -l dist
|
||||
|
||||
wheel: clean sdist
|
||||
python-wheel: ## Build the wheel distribution package.
|
||||
python-wheel: clean python-sdist
|
||||
pip wheel --no-index --no-deps --wheel-dir dist dist/*.tar.gz
|
||||
ls -l dist
|
||||
|
||||
release-test-via-docker-ubuntu:
|
||||
python-release-test-via-docker-ubuntu: ## Package (sdist and wheel) and upload to the PyPI test server using an Ubuntu Docker builder.
|
||||
docker run --rm --name mayan_release -v $(HOME):/host_home:ro -v `pwd`:/host_source -w /source ubuntu:16.04 /bin/bash -c "\
|
||||
echo "LC_ALL=\"en_US.UTF-8\"" >> /etc/default/locale && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
@@ -194,7 +157,7 @@ release-test-via-docker-ubuntu:
|
||||
cp -r /host_home/.pypirc ~/.pypirc && \
|
||||
make test-release"
|
||||
|
||||
release-via-docker-ubuntu:
|
||||
python-release-via-docker-ubuntu: ## Package (sdist and wheel) and upload to PyPI using an Ubuntu Docker builder.
|
||||
docker run --rm --name mayan_release -v $(HOME):/host_home:ro -v `pwd`:/host_source -w /source ubuntu:16.04 /bin/bash -c "\
|
||||
apt-get update && \
|
||||
apt-get -y install locales && \
|
||||
@@ -208,7 +171,7 @@ release-via-docker-ubuntu:
|
||||
cp -r /host_home/.pypirc ~/.pypirc && \
|
||||
make release"
|
||||
|
||||
test-sdist-via-docker-ubuntu:
|
||||
test-sdist-via-docker-ubuntu: ## Make an sdist package and test it using an Ubuntu Docker container.
|
||||
docker run --rm --name mayan_sdist_test -v $(HOME):/host_home:ro -v `pwd`:/host_source -w /source ubuntu:16.04 /bin/bash -c "\
|
||||
cp -r /host_source/* . && \
|
||||
echo "LC_ALL=\"en_US.UTF-8\"" >> /etc/default/locale && \
|
||||
@@ -221,7 +184,7 @@ test-sdist-via-docker-ubuntu:
|
||||
make sdist-test-suit \
|
||||
"
|
||||
|
||||
test-wheel-via-docker-ubuntu:
|
||||
test-wheel-via-docker-ubuntu: ## Make a wheel package and test it using an Ubuntu Docker container.
|
||||
docker run --rm --name mayan_wheel_test -v $(HOME):/host_home:ro -v `pwd`:/host_source -w /source ubuntu:16.04 /bin/bash -c "\
|
||||
cp -r /host_source/* . && \
|
||||
echo "LC_ALL=\"en_US.UTF-8\"" >> /etc/default/locale && \
|
||||
@@ -234,7 +197,7 @@ test-wheel-via-docker-ubuntu:
|
||||
make wheel-test-suit \
|
||||
"
|
||||
|
||||
sdist-test-suit: sdist
|
||||
python-sdist-test-suit: sdist
|
||||
rm -f -R _virtualenv
|
||||
virtualenv _virtualenv
|
||||
sh -c '\
|
||||
@@ -245,7 +208,7 @@ sdist-test-suit: sdist
|
||||
_virtualenv/bin/mayan-edms.py test --mayan-apps \
|
||||
'
|
||||
|
||||
wheel-test-suit: wheel
|
||||
python-wheel-test-suit: wheel
|
||||
rm -f -R _virtualenv
|
||||
virtualenv _virtualenv
|
||||
sh -c '\
|
||||
@@ -256,18 +219,30 @@ wheel-test-suit: wheel
|
||||
_virtualenv/bin/mayan-edms.py test --mayan-apps \
|
||||
'
|
||||
|
||||
generate-setup: ## Create and update the setup.py file.
|
||||
generate-setup: generate-requirements
|
||||
@./generate_setup.py
|
||||
@echo "Complete."
|
||||
|
||||
generate-requirements: ## Generate all requirements files from the project depedency declarations.
|
||||
@./manage.py generaterequirements build > requirements/build.txt
|
||||
@./manage.py generaterequirements development > requirements/development.txt
|
||||
@./manage.py generaterequirements testing > requirements/testing-base.txt
|
||||
@./manage.py generaterequirements production --exclude=django > requirements/base.txt
|
||||
@./manage.py generaterequirements production --only=django > requirements/common.txt
|
||||
|
||||
# Dev server
|
||||
|
||||
runserver:
|
||||
runserver: ## Run the development server.
|
||||
./manage.py runserver --settings=mayan.settings.development $(ADDRPORT)
|
||||
|
||||
runserver_plus:
|
||||
runserver_plus: ## Run the Django extension's development server.
|
||||
./manage.py runserver_plus --settings=mayan.settings.development $(ADDRPORT)
|
||||
|
||||
shell_plus:
|
||||
shell_plus: ## Run the shell_plus command.
|
||||
./manage.py shell_plus --settings=mayan.settings.development
|
||||
|
||||
test-with-docker-services-on:
|
||||
test-with-docker-services-on: ## Launch and initialize production-like services using Docker (Postgres and Redis).
|
||||
docker run -d --name redis -p 6379:6379 redis
|
||||
docker run -d --name postgres -p 5432:5432 postgres
|
||||
while ! nc -z 127.0.0.1 6379; do sleep 1; done
|
||||
@@ -275,45 +250,45 @@ test-with-docker-services-on:
|
||||
sleep 4
|
||||
./manage.py initialsetup --settings=mayan.settings.staging.docker
|
||||
|
||||
test-with-docker-services-off:
|
||||
test-with-docker-services-off: ## Stop and delete the Docker production-like services.
|
||||
docker stop postgres redis
|
||||
docker rm postgres redis
|
||||
|
||||
test-with-docker-frontend:
|
||||
test-with-docker-frontend: ## Launch a front end instance that uses the production-like services.
|
||||
./manage.py runserver --settings=mayan.settings.staging.docker
|
||||
|
||||
test-with-docker-worker:
|
||||
./manage.py celery worker --settings=mayan.settings.staging.docker -B -l INFO
|
||||
test-with-docker-worker: ## Launch a worker instance that uses the production-like services.
|
||||
./manage.py celery worker --settings=mayan.settings.staging.docker -B -l INFO -O fair
|
||||
|
||||
docker-mysql-on:
|
||||
docker-mysql-on: ## Launch and initialize a MySQL Docker container.
|
||||
docker run -d --name mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=True -e MYSQL_DATABASE=mayan_edms mysql
|
||||
while ! nc -z 127.0.0.1 3306; do sleep 1; done
|
||||
|
||||
docker-mysql-off:
|
||||
docker-mysql-off: ## Stop and delete the MySQL Docker container.
|
||||
docker stop mysql
|
||||
docker rm mysql
|
||||
|
||||
docker-postgres-on:
|
||||
docker-postgres-on: ## Launch and initialize a PostgreSQL Docker container.
|
||||
docker run -d --name postgres -p 5432:5432 postgres
|
||||
while ! nc -z 127.0.0.1 5432; do sleep 1; done
|
||||
|
||||
docker-postgres-off:
|
||||
docker-postgres-off: ## Stop and delete the PostgreSQL Docker container.
|
||||
docker stop postgres
|
||||
docker rm postgres
|
||||
|
||||
|
||||
# Security
|
||||
|
||||
safety-check:
|
||||
safety-check: ## Run a package safety check.
|
||||
safety check
|
||||
|
||||
|
||||
# Other
|
||||
find-gitignores:
|
||||
find-gitignores: ## Find stray .gitignore files.
|
||||
@export FIND_GITIGNORES=`find -name '.gitignore'| wc -l`; \
|
||||
if [ $${FIND_GITIGNORES} -gt 1 ] ;then echo "More than one .gitignore found."; fi
|
||||
|
||||
build:
|
||||
python-build:
|
||||
docker rm -f mayan-edms-build || true && \
|
||||
docker run --rm --name mayan-edms-build -v $(HOME):/host_home:ro -v `pwd`:/host_source -w /source python:2-slim sh -c "\
|
||||
rm /host_source/dist -R || true && \
|
||||
@@ -326,11 +301,13 @@ build:
|
||||
make wheel && \
|
||||
cp dist/* /host_source/dist/"
|
||||
|
||||
check-readme:
|
||||
check-readme: ## Checks validity of the README.rst file for PyPI publication.
|
||||
python setup.py check -r -s
|
||||
|
||||
check-missing-migrations:
|
||||
check-missing-migrations: ## Make sure all models have proper migrations.
|
||||
./manage.py makemigrations --dry-run --noinput --check
|
||||
|
||||
setup-dev-environment: ## Bootstrap a virtualenv by install all dependencies to start developing.
|
||||
pip install -r requirements.txt -r requirements/development.txt -r requirements/testing-base.txt -r requirements/documentation.txt -r requirements/build.txt
|
||||
|
||||
include docker/Makefile
|
||||
-include docker/Makefile
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends tesseract-ocr-deu
|
||||
|
||||
$MAYAN_PIP_BIN install -r $DOCKER_ROOT/requirements-testing.txt
|
||||
$MAYAN_PIP_BIN install -r ${MAYAN_INSTALL_DIR}/requirements-testing.txt
|
||||
|
||||
$MAYAN_BIN test --mayan-apps --settings=mayan.settings.testing
|
||||
|
||||
@@ -18,7 +18,7 @@ sudo apt-get -qq update
|
||||
sudo apt-get -y upgrade
|
||||
|
||||
echo -e "\n -> Installing core binaries \n"
|
||||
sudo apt-get -y install exiftool git-core python-virtualenv gcc python-dev libjpeg-dev libpng-dev libtiff-dev tesseract-ocr poppler-utils libreoffice
|
||||
sudo apt-get -y install git-core python-virtualenv gcc python-dev libjpeg-dev libpng-dev libtiff-dev tesseract-ocr poppler-utils libreoffice
|
||||
|
||||
echo -e "\n -> Cloning development branch of repository \n"
|
||||
git clone /mayan-edms-repository/ $INSTALLATION_DIRECTORY
|
||||
|
||||
@@ -1445,15 +1445,15 @@ sudo -u mayan \
|
||||
dialog --infobox "Preparing static files" 3 70
|
||||
sudo -u mayan \
|
||||
MAYAN_MEDIA_ROOT=$MAYAN_MEDIA_ROOT \
|
||||
$MAYAN_BIN collectstatic --noinput > /dev/null
|
||||
$MAYAN_BIN preparestatic --noinput > /dev/null
|
||||
|
||||
# Create supervisor file for gunicorn (frontend), 3 background workers, and the scheduler for periodic tasks
|
||||
cat > /etc/supervisor/conf.d/mayan.conf <<EOF
|
||||
[supervisord]
|
||||
environment=
|
||||
MAYAN_ALLOWED_HOSTS="*", # Allow access to other network hosts other than localhost
|
||||
MAYAN_CELERY_BROKER_URL="redis://127.0.0.1:6379/0",
|
||||
MAYAN_CELERY_RESULT_BACKEND="redis://127.0.0.1:6379/0",
|
||||
MAYAN_BROKER_URL="redis://127.0.0.1:6379/0",
|
||||
PYTHONPATH=${MAYAN_INSTALLATION_FOLDER}/lib/python2.7/site-packages:$MAYAN_MEDIA_ROOT,
|
||||
MAYAN_DATABASE_ENGINE=django.db.backends.postgresql,
|
||||
MAYAN_DATABASE_HOST=127.0.0.1,
|
||||
@@ -1473,7 +1473,7 @@ user = mayan
|
||||
[program:mayan-worker-fast]
|
||||
autorestart = true
|
||||
autostart = true
|
||||
command = nice -n 1 ${MAYAN_BIN} celery worker -l ERROR -Q converter -n mayan-worker-fast.%%h --concurrency=1
|
||||
command = nice -n 1 ${MAYAN_BIN} celery worker -Ofair -l ERROR -Q converter -n mayan-worker-fast.%%h --concurrency=1
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
@@ -1484,7 +1484,7 @@ user = mayan
|
||||
[program:mayan-worker-medium]
|
||||
autorestart = true
|
||||
autostart = true
|
||||
command = nice -n 18 ${MAYAN_BIN} celery worker -l ERROR -Q checkouts_periodic,documents_periodic,indexing,metadata,sources,sources_periodic,uploads,documents -n mayan-worker-medium.%%h --concurrency=1
|
||||
command = nice -n 18 ${MAYAN_BIN} celery worker -Ofair -l ERROR -Q checkouts_periodic,documents_periodic,indexing,metadata,sources,sources_periodic,uploads,documents -n mayan-worker-medium.%%h --concurrency=1
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
@@ -1495,7 +1495,7 @@ user = mayan
|
||||
[program:mayan-worker-slow]
|
||||
autorestart = true
|
||||
autostart = true
|
||||
command = nice -n 19 ${MAYAN_BIN} celery worker -l ERROR -Q mailing,tools,statistics,parsing,ocr -n mayan-worker-slow.%%h --concurrency=1
|
||||
command = nice -n 19 ${MAYAN_BIN} celery worker -Ofair -l ERROR -Q mailing,tools,statistics,parsing,ocr -n mayan-worker-slow.%%h --concurrency=1
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
|
||||
@@ -16,7 +16,7 @@ set -e
|
||||
: ${DATABASE_USER:=mayan}
|
||||
: ${DATABASE_NAME:=mayan}
|
||||
: ${DATABASE_PASSWORD:=mayanuserpass}
|
||||
: ${DOCKER_POSTGRES_IMAGE:=postgres:9.5}
|
||||
: ${DOCKER_POSTGRES_IMAGE:=postgres:9.6}
|
||||
: ${DOCKER_POSTGRES_CONTAINER:=mayan-edms-postgres}
|
||||
: ${DOCKER_POSTGRES_VOLUME:=/docker-volumes/mayan-edms/postgres}
|
||||
: ${DOCKER_POSTGRES_PORT:=5432}
|
||||
@@ -121,7 +121,7 @@ docker run -d \
|
||||
-e MAYAN_DATABASE_PASSWORD=$DATABASE_PASSWORD \
|
||||
-e MAYAN_DATABASE_USER=$DATABASE_USER \
|
||||
-e MAYAN_DATABASE_PORT=$DOCKER_POSTGRES_PORT \
|
||||
-e MAYAN_DATABASE_CONN_MAX_AGE=60 \
|
||||
-e MAYAN_DATABASE_CONN_MAX_AGE=0 \
|
||||
-v $DOCKER_MAYAN_VOLUME:/var/lib/mayan \
|
||||
$DOCKER_MAYAN_IMAGE >/dev/null
|
||||
echo "Done"
|
||||
|
||||
@@ -20,7 +20,7 @@ apt-get -qq update
|
||||
apt-get -y upgrade
|
||||
|
||||
echo -e "\n -> Installing core binaries \n"
|
||||
apt-get install exiftool nginx supervisor redis-server postgresql libpq-dev libjpeg-dev libmagic1 libpng-dev libreoffice libtiff-dev gcc ghostscript gpgv python-dev python-virtualenv tesseract-ocr poppler-utils -y
|
||||
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 poppler-utils -y
|
||||
|
||||
echo -e "\n -> Setting up virtualenv \n"
|
||||
rm -f ${INSTALLATION_DIRECTORY}
|
||||
@@ -133,7 +133,7 @@ EOF
|
||||
echo -e "\n -> Creating the supervisor file for the Celery worker, /etc/supervisor/conf.d/mayan-celery.conf \n"
|
||||
cat > /etc/supervisor/conf.d/mayan-celery.conf << EOF
|
||||
[program:mayan-worker]
|
||||
command = ${INSTALLATION_DIRECTORY}bin/python ${INSTALLATION_DIRECTORY}bin/mayan-edms.py celery --settings=mayan.settings.production worker -l ERROR
|
||||
command = ${INSTALLATION_DIRECTORY}bin/python ${INSTALLATION_DIRECTORY}bin/mayan-edms.py celery --settings=mayan.settings.production worker -Ofair -l ERROR
|
||||
directory = ${INSTALLATION_DIRECTORY}
|
||||
user = www-data
|
||||
stdout_logfile = /var/log/mayan/worker-stdout.log
|
||||
@@ -161,7 +161,7 @@ priority = 998
|
||||
EOF
|
||||
|
||||
echo -e "\n -> Collecting the static files \n"
|
||||
mayan-edms.py collectstatic --noinput
|
||||
mayan-edms.py preparestatic --noinput
|
||||
|
||||
echo -e "\n -> Making the installation directory readable and writable by the webserver user \n"
|
||||
chown www-data:www-data ${INSTALLATION_DIRECTORY} -R
|
||||
|
||||
@@ -10,19 +10,20 @@ import sh
|
||||
|
||||
APP_LIST = (
|
||||
'acls', 'appearance', 'authentication', 'autoadmin', 'cabinets',
|
||||
'checkouts', 'common', 'converter', 'dashboards', 'django_gpg',
|
||||
'document_comments', 'document_indexing', 'document_parsing',
|
||||
'document_signatures', 'document_states', 'documents', 'dynamic_search',
|
||||
'events', 'file_caching', 'linking', 'lock_manager', 'mayan_statistics',
|
||||
'mailer', 'metadata', 'mirroring', 'motd', 'navigation', 'ocr',
|
||||
'permissions', 'rest_api', 'smart_settings', 'sources', 'storage',
|
||||
'tags', 'task_manager', 'user_management'
|
||||
'checkouts', 'common', 'converter', 'dashboards', 'dependencies',
|
||||
'django_gpg', 'document_comments', 'document_indexing',
|
||||
'document_parsing', 'document_signatures', 'document_states',
|
||||
'documents', 'dynamic_search', 'events', 'file_metadata', 'linking',
|
||||
'lock_manager', 'mayan_statistics', 'mailer', 'metadata', 'mirroring',
|
||||
'motd', 'navigation', 'ocr', 'permissions', 'platform', 'rest_api',
|
||||
'smart_settings', 'sources', 'storage', 'tags', 'task_manager',
|
||||
'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', 'tr_TR',
|
||||
'vi_VN', 'zh_CN',
|
||||
'ar', 'bg', 'bs_BA', 'cs', 'da_DK', 'de_DE', 'en', 'es', 'el', 'fa', 'fr',
|
||||
'hu', 'id', 'it', 'nl_NL', 'pl', 'pt', 'pt_BR', 'ro_RO', 'ru', 'sl_SI',
|
||||
'tr_TR', 'vi_VN', 'zh',
|
||||
)
|
||||
|
||||
makemessages = sh.Command('django-admin.py')
|
||||
|
||||
@@ -1,165 +1,157 @@
|
||||
# vim:set ft=dockerfile:
|
||||
|
||||
####################
|
||||
# Base image start #
|
||||
####################
|
||||
####
|
||||
# BASE_IMAGE - Bare bones image with the base packages needed to run Mayan EDMS
|
||||
####
|
||||
|
||||
FROM debian:9.4-slim as BASE_IMAGE
|
||||
FROM debian:9.8-slim as BASE_IMAGE
|
||||
|
||||
MAINTAINER Roberto Rosario "roberto.rosario@mayan-edms.com"
|
||||
LABEL maintainer="Roberto Rosario roberto.rosario@mayan-edms.com"
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV LC_ALL C.UTF-8
|
||||
ENV PROJECT_INSTALL_DIR=/opt/mayan-edms
|
||||
ENV PYTHON_PIP=${PROJECT_INSTALL_DIR}/bin/pip
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
PROJECT_INSTALL_DIR=/opt/mayan-edms
|
||||
|
||||
# Debian package caching
|
||||
ARG APT_PROXY
|
||||
# Package caching
|
||||
RUN if [ "${APT_PROXY}" ]; then echo "Acquire::http { Proxy \"http://${APT_PROXY}\"; };" > /etc/apt/apt.conf.d/01proxy; fi
|
||||
|
||||
# Install base Ubuntu libraries
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
exiftool \
|
||||
g++ \
|
||||
gcc \
|
||||
ghostscript \
|
||||
gpgv \
|
||||
gnupg1 \
|
||||
graphviz \
|
||||
libffi-dev \
|
||||
libfuse2 \
|
||||
libjpeg-dev \
|
||||
libmagic1 \
|
||||
default-libmysqlclient-dev \
|
||||
libpng-dev \
|
||||
libpq-dev \
|
||||
libreoffice \
|
||||
libtiff-dev \
|
||||
poppler-utils \
|
||||
python-dev \
|
||||
python-setuptools \
|
||||
python-virtualenv \
|
||||
python-wheel \
|
||||
redis-server \
|
||||
sane-utils \
|
||||
sudo \
|
||||
supervisor \
|
||||
tesseract-ocr \
|
||||
zlib1g-dev \
|
||||
&& \
|
||||
apt-get clean autoclean && \
|
||||
apt-get autoremove --purge -y && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm -f /var/cache/apt/archives/*.deb
|
||||
|
||||
# Install apt-get-install
|
||||
ADD https://raw.githubusercontent.com/guilhem/apt-get-install/master/apt-get-install /usr/bin/
|
||||
RUN chmod +x /usr/bin/apt-get-install
|
||||
|
||||
RUN adduser mayan --disabled-password --disabled-login --no-create-home --gecos ""
|
||||
|
||||
RUN set -x \
|
||||
&& if [ "${APT_PROXY}" ]; \
|
||||
then echo "Acquire::http { Proxy \"http://${APT_PROXY}\"; };" > /etc/apt/apt.conf.d/01proxy \
|
||||
; fi \
|
||||
# Install base OS packages to run Mayan EDMS
|
||||
&& DEBIAN_FRONTEND=noninteractive \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
exiftool \
|
||||
ghostscript \
|
||||
gpgv \
|
||||
gnupg1 \
|
||||
graphviz \
|
||||
libfuse2 \
|
||||
libmagic1 \
|
||||
libmariadbclient18 \
|
||||
libreoffice \
|
||||
libpq5 \
|
||||
poppler-utils \
|
||||
redis-server \
|
||||
sane-utils \
|
||||
sudo \
|
||||
supervisor \
|
||||
tesseract-ocr \
|
||||
# Remove make and build dependencies
|
||||
&& apt-get remove make libproxy-tools libreoffice-avmedia-backend-vlc libvlc-bin libvlc5 libvlccore9 adwaita-icon-theme gsettings-desktop-schemas libgstreamer-plugins-base1.0-0 -y \
|
||||
&& apt-get autoremove -y --purge \
|
||||
# Add mayan user
|
||||
&& adduser mayan --disabled-password --disabled-login --no-create-home --gecos "" \
|
||||
# Pillow can't find zlib or libjpeg on aarch64 (ODROID C2)
|
||||
RUN if [ "$(uname -m)" = "aarch64" ]; then \
|
||||
ln -s /usr/lib/aarch64-linux-gnu/libz.so /usr/lib/ && \
|
||||
ln -s /usr/lib/aarch64-linux-gnu/libjpeg.so /usr/lib/ \
|
||||
; fi
|
||||
|
||||
&& if [ "$(uname -m)" = "aarch64" ]; then \
|
||||
ln -s /usr/lib/aarch64-linux-gnu/libz.so /usr/lib/ \
|
||||
&& ln -s /usr/lib/aarch64-linux-gnu/libjpeg.so /usr/lib/ \
|
||||
; fi \
|
||||
# Pillow can't find zlib or libjpeg on armv7l (ODROID HC1)
|
||||
RUN if [ "$(uname -m)" = "armv7l" ]; then \
|
||||
apt-get install libssl-dev -y && \
|
||||
ln -s /usr/lib/arm-linux-gnueabihf/libz.so /usr/lib/ && \
|
||||
ln -s /usr/lib/arm-linux-gnueabihf/libjpeg.so /usr/lib/ \
|
||||
; fi
|
||||
|
||||
&& if [ "$(uname -m)" = "armv7l" ]; then \
|
||||
ln -s /usr/lib/arm-linux-gnueabihf/libz.so /usr/lib/ \
|
||||
&& ln -s /usr/lib/arm-linux-gnueabihf/libjpeg.so /usr/lib/ \
|
||||
; fi \
|
||||
# Discard data when Redis runs out of memory
|
||||
RUN echo "maxmemory-policy allkeys-lru" >> /etc/redis/redis.conf
|
||||
|
||||
&& echo "maxmemory-policy allkeys-lru" >> /etc/redis/redis.conf \
|
||||
# Disable saving the Redis database
|
||||
RUN echo "save \"\"" >> /etc/redis/redis.conf
|
||||
|
||||
echo "save \"\"" >> /etc/redis/redis.conf \
|
||||
# Only provision 1 database
|
||||
RUN echo "databases 1" >> /etc/redis/redis.conf
|
||||
&& echo "databases 1" >> /etc/redis/redis.conf
|
||||
|
||||
#####################
|
||||
# Build image start #
|
||||
#####################
|
||||
|
||||
FROM debian:9.4-slim as BUILDER_IMAGE
|
||||
####
|
||||
# BUILDER_IMAGE - This image buildS the Python package and is discarded afterwards
|
||||
####
|
||||
|
||||
ARG APT_PROXY
|
||||
# Package caching
|
||||
RUN if [ "${APT_PROXY}" ]; then echo "Acquire::http { Proxy \"http://${APT_PROXY}\"; };" > /etc/apt/apt.conf.d/01proxy; fi
|
||||
# Reuse image
|
||||
FROM BASE_IMAGE as BUILDER_IMAGE
|
||||
|
||||
WORKDIR /code
|
||||
WORKDIR /src
|
||||
|
||||
COPY . /code
|
||||
# Copy the source files needed to build the Python package
|
||||
COPY --chown=mayan:mayan requirements /src/requirements
|
||||
COPY --chown=mayan:mayan \
|
||||
HISTORY.rst \
|
||||
LICENSE \
|
||||
MANIFEST.in \
|
||||
README.md \
|
||||
README.rst \
|
||||
setup.py \
|
||||
/src/
|
||||
|
||||
RUN apt-get update && apt-get install make python-dev python-pip -y
|
||||
COPY --chown=mayan:mayan mayan /src/mayan
|
||||
|
||||
RUN pip install -r requirements/build.txt
|
||||
# Install development packages needed to build the Python packages
|
||||
RUN DEBIAN_FRONTEND=noninteractive \
|
||||
apt-get install -y --no-install-recommends \
|
||||
default-libmysqlclient-dev \
|
||||
libffi-dev \
|
||||
libjpeg-dev \
|
||||
libpng-dev \
|
||||
libpq-dev \
|
||||
libtiff-dev \
|
||||
zlib1g-dev \
|
||||
libssl-dev \
|
||||
g++ \
|
||||
gcc \
|
||||
python-dev \
|
||||
python-virtualenv \
|
||||
&& mkdir -p "${PROJECT_INSTALL_DIR}" \
|
||||
&& chown -R mayan:mayan "${PROJECT_INSTALL_DIR}" \
|
||||
&& chown -R mayan:mayan /src
|
||||
|
||||
ENV LC_ALL C.UTF-8
|
||||
USER mayan
|
||||
RUN python -m virtualenv "${PROJECT_INSTALL_DIR}" \
|
||||
&& . "${PROJECT_INSTALL_DIR}/bin/activate" \
|
||||
&& pip install --no-cache-dir --no-use-pep517 \
|
||||
librabbitmq==1.6.1 \
|
||||
mysql-python==1.2.5 \
|
||||
psycopg2==2.7.3.2 \
|
||||
redis==2.10.6 \
|
||||
# psutil is needed by ARM builds otherwise gevent and gunicorn fail to start
|
||||
&& UNAME=`uname -m` && if [ "${UNAME#*arm}" != $UNAME ]; then \
|
||||
pip install --no-cache-dir --no-use-pep517 \
|
||||
psutil==5.6.2 \
|
||||
; fi \
|
||||
# Install the Python packages needed to build Mayan EDMS
|
||||
&& pip install --no-cache-dir --no-use-pep517 -r /src/requirements/build.txt \
|
||||
# Build Mayan EDMS
|
||||
&& python setup.py sdist \
|
||||
# Install the built Mayan EDMS package
|
||||
&& pip install --no-cache-dir --no-use-pep517 dist/mayan* \
|
||||
# Install the static content
|
||||
&& mayan-edms.py installjavascript \
|
||||
&& MAYAN_STATIC_ROOT=${PROJECT_INSTALL_DIR}/static mayan-edms.py preparestatic --link --noinput
|
||||
|
||||
RUN touch docker/Makefile
|
||||
COPY --chown=mayan:mayan requirements/testing-base.txt "${PROJECT_INSTALL_DIR}"
|
||||
|
||||
RUN make wheel
|
||||
|
||||
RUN chmod 777 dist -R
|
||||
|
||||
#####################
|
||||
# Final image start #
|
||||
#####################
|
||||
####
|
||||
# Final image - BASE_IMAGE + Mayan install directory from the builder image
|
||||
####
|
||||
|
||||
FROM BASE_IMAGE
|
||||
|
||||
RUN mkdir -p /opt
|
||||
COPY --from=BUILDER_IMAGE --chown=mayan:mayan "${PROJECT_INSTALL_DIR}/" "${PROJECT_INSTALL_DIR}/"
|
||||
|
||||
RUN python /usr/lib/python2.7/dist-packages/virtualenv.py $PROJECT_INSTALL_DIR
|
||||
USER root
|
||||
|
||||
WORKDIR $PROJECT_INSTALL_DIR
|
||||
COPY docker/rootfs /
|
||||
|
||||
COPY --from=BUILDER_IMAGE /code/dist/*.whl .
|
||||
|
||||
COPY --from=BUILDER_IMAGE /code/contrib/scripts/docker/run-tests.sh .
|
||||
|
||||
COPY --from=BUILDER_IMAGE /code/requirements/testing-base.txt requirements-testing.txt
|
||||
|
||||
COPY --from=BUILDER_IMAGE /code/docker/version .
|
||||
|
||||
# Fix ownership
|
||||
RUN chown -R mayan:mayan $PROJECT_INSTALL_DIR
|
||||
|
||||
# Install build Mayan EDMS
|
||||
RUN sudo -u mayan $PYTHON_PIP install --no-cache-dir *.whl && \
|
||||
rm *.whl
|
||||
|
||||
# Install Python clients for librabbitmq, MySQL, PostgreSQL, REDIS
|
||||
RUN sudo -u mayan $PYTHON_PIP install --no-cache-dir librabbitmq==1.6.1 mysql-python==1.2.5 psycopg2==2.7.3.2 redis==2.10.6
|
||||
|
||||
# Setup supervisor
|
||||
COPY docker/etc/supervisor/mayan.conf /etc/supervisor/conf.d
|
||||
|
||||
RUN mkdir /var/lib/mayan
|
||||
VOLUME ["/var/lib/mayan"]
|
||||
|
||||
COPY docker/entrypoint.sh /usr/local/bin/
|
||||
RUN ln -s usr/local/bin/entrypoint.sh / # backwards compat
|
||||
ENTRYPOINT ["entrypoint.sh"]
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["mayan"]
|
||||
|
||||
RUN rm /root/.cache -R
|
||||
RUN rm -rf /tmp/*
|
||||
|
||||
RUN apt-get -y autoremove --purge && apt-get -y autoclean && apt-get -y clean
|
||||
|
||||
RUN rm -rf /usr/share/man/*
|
||||
RUN rm -rf /usr/share/doc/*
|
||||
|
||||
RUN find /var/lib/apt -type f | xargs rm -f
|
||||
RUN find /var/cache -type f -exec rm -rf {} \;
|
||||
|
||||
RUN find /var/log -type f | while read f; do echo -ne '' > $f; done;
|
||||
RUN ${PROJECT_INSTALL_DIR}/bin/mayan-edms.py platformtemplate supervisord_docker > /etc/supervisor/conf.d/mayan.conf \
|
||||
&& apt-get clean autoclean \
|
||||
&& apt-get autoremove --purge -y \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -f /var/cache/apt/archives/*.deb \
|
||||
# Remove temporary files owned by root from the platformtemplate step
|
||||
&& rm /tmp/* \
|
||||
# Keep displaying log messages to stdout
|
||||
&& find /var/log -type f | while read f; do echo -ne '' > $f; done;
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
# vim:set ft=dockerfile:
|
||||
|
||||
####################
|
||||
# Base image start #
|
||||
####################
|
||||
|
||||
FROM ubuntu:16.04 as BASE_IMAGE
|
||||
|
||||
MAINTAINER Roberto Rosario "roberto.rosario@mayan-edms.com"
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV PROJECT_INSTALL_DIR=/usr/local/lib/python2.7/dist-packages/mayan
|
||||
|
||||
ARG APT_PROXY
|
||||
# Package caching
|
||||
RUN if [ "${APT_PROXY}" ]; then echo "Acquire::http { Proxy \"http://${APT_PROXY}\"; };" > /etc/apt/apt.conf.d/01proxy; fi
|
||||
|
||||
# Install base Ubuntu libraries
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
g++ \
|
||||
gcc \
|
||||
gettext-base \
|
||||
ghostscript \
|
||||
gpgv \
|
||||
graphviz \
|
||||
libffi-dev \
|
||||
libjpeg-dev \
|
||||
libmagic1 \
|
||||
libmysqlclient-dev \
|
||||
libpng-dev \
|
||||
libpq-dev \
|
||||
libreoffice \
|
||||
libtiff-dev \
|
||||
locales \
|
||||
netcat-openbsd \
|
||||
poppler-utils \
|
||||
python-dev \
|
||||
python-pip \
|
||||
python-setuptools \
|
||||
python-wheel \
|
||||
redis-server \
|
||||
supervisor \
|
||||
tesseract-ocr \
|
||||
zlib1g-dev \
|
||||
&& \
|
||||
apt-get clean autoclean && \
|
||||
apt-get autoremove --purge -y && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm -f /var/cache/apt/archives/*.deb
|
||||
|
||||
# Switch to UTF locale
|
||||
RUN echo "LC_ALL=\"en_US.UTF-8\"" >> /etc/default/locale && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
update-locale LANG=en_US.UTF-8 && \
|
||||
export LC_ALL=en_US.UTF-8
|
||||
|
||||
# Install apt-get-install
|
||||
ADD https://raw.githubusercontent.com/guilhem/apt-get-install/master/apt-get-install /usr/bin/
|
||||
RUN chmod +x /usr/bin/apt-get-install
|
||||
|
||||
# Install Python clients for PostgreSQL, REDIS, librabbitmq
|
||||
RUN pip install psycopg2==2.7.3.2 redis==2.10.6 mysql-python==1.2.5 librabbitmq==1.6.1
|
||||
|
||||
RUN adduser mayan --disabled-password --disabled-login --no-create-home --gecos ""
|
||||
|
||||
# Pillow can't find zlib or libjpeg on aarch64
|
||||
RUN if [ "$(uname -m)" = "aarch64" ]; then \
|
||||
ln -s /usr/lib/aarch64-linux-gnu/libz.so /usr/lib/ && \
|
||||
ln -s /usr/lib/aarch64-linux-gnu/libjpeg.so /usr/lib/ \
|
||||
; fi
|
||||
|
||||
#####################
|
||||
# Build image start #
|
||||
#####################
|
||||
|
||||
FROM python:2-alpine3.7 as BUILDER_IMAGE
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
COPY . /code
|
||||
|
||||
RUN apk update && \
|
||||
apk add make
|
||||
|
||||
RUN pip install -r requirements/build.txt
|
||||
|
||||
RUN make wheel
|
||||
|
||||
RUN chmod 777 dist -R
|
||||
|
||||
#####################
|
||||
# Final image start #
|
||||
#####################
|
||||
|
||||
FROM BASE_IMAGE
|
||||
|
||||
WORKDIR /root/
|
||||
|
||||
COPY --from=BUILDER_IMAGE /code/dist/*.whl .
|
||||
|
||||
# Install build Mayan EDMS
|
||||
RUN pip install *.whl && \
|
||||
rm *.whl
|
||||
|
||||
# Setup supervisor
|
||||
#RUN mkdir /etc/supervisor.d/
|
||||
COPY docker/etc/supervisor/beat.conf /etc/supervisor/conf.d
|
||||
COPY docker/etc/supervisor/gunicorn.conf /etc/supervisor/conf.d
|
||||
COPY docker/etc/supervisor/redis.conf /etc/supervisor/conf.d
|
||||
COPY docker/etc/supervisor/workers.conf /etc/supervisor/conf.d
|
||||
|
||||
# Create the directory for the logs
|
||||
RUN mkdir /var/log/mayan
|
||||
|
||||
# Fix ownership
|
||||
RUN chown -R mayan:mayan $PROJECT_INSTALL_DIR
|
||||
|
||||
# Allow flanker to autogenerate its PLY files
|
||||
RUN chown -R mayan:mayan /usr/local/lib/python2.7/dist-packages/flanker/
|
||||
|
||||
RUN mkdir /var/lib/mayan
|
||||
VOLUME ["/var/lib/mayan"]
|
||||
|
||||
COPY docker/entrypoint.sh /usr/local/bin/
|
||||
RUN ln -s usr/local/bin/entrypoint.sh / # backwards compat
|
||||
ENTRYPOINT ["entrypoint.sh"]
|
||||
|
||||
# Healthcheck setup
|
||||
HEALTHCHECK --interval=15s --timeout=1s --retries=20 \
|
||||
CMD curl -s -f http://localhost/authentication/login/ | grep 'form' > /dev/null || exit 1
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["mayan"]
|
||||
|
||||
RUN rm /root/.cache -R
|
||||
RUN rm -rf /tmp/*
|
||||
|
||||
RUN apt-get -y autoremove --purge && apt-get -y autoclean && apt-get -y clean
|
||||
|
||||
RUN rm -rf /usr/share/man/*
|
||||
RUN rm -rf /usr/share/doc/*
|
||||
|
||||
RUN find /var/lib/apt -type f | xargs rm -f
|
||||
RUN find /var/cache -type f -exec rm -rf {} \;
|
||||
|
||||
RUN find /var/log -type f | while read f; do echo -ne '' > $f; done;
|
||||
@@ -1,33 +1,25 @@
|
||||
APT_PROXY ?= `/sbin/ip route|awk '/docker0/ { print $$9 }'`:3142
|
||||
IMAGE_VERSION ?= `cat docker/version`
|
||||
IMAGE_VERSION ?= `cat docker/rootfs/version`
|
||||
CONSOLE_COLUMNS ?= `echo $$(tput cols)`
|
||||
CONSOLE_LINES ?= `echo $$(tput lines)`
|
||||
|
||||
docker-help:
|
||||
@echo
|
||||
@echo "**** Docker makefile ****"
|
||||
@echo "docker-build - Build a new image locally."
|
||||
@echo "docker-build-with-proxy - Build a new image locally using an APT proxy."
|
||||
@echo "docker-test-container - Build and run a test container."
|
||||
@echo "docker-test-cleanup - Delete the test container and the test volume."
|
||||
@echo "docker-test-all - Build and executed the test suite in a test container."
|
||||
@echo "docker-shell - Launch a bash instance inside a running container. Pass the container name via DOCKER_CONTAINER."
|
||||
|
||||
docker-build:
|
||||
docker-build: ## Build a new image locally.
|
||||
docker build -t mayanedms/mayanedms:$(IMAGE_VERSION) -f docker/Dockerfile .
|
||||
|
||||
docker-build-with-proxy:
|
||||
docker-build-with-proxy: ## Build a new image locally using an APT proxy as APT_PROXY.
|
||||
docker build -t mayanedms/mayanedms:$(IMAGE_VERSION) -f docker/Dockerfile --build-arg APT_PROXY=$(APT_PROXY) .
|
||||
|
||||
docker-shell:
|
||||
docker-shell: ## Launch a bash instance inside a running container. Pass the container name via DOCKER_CONTAINER.
|
||||
docker exec -e TERM=$(TERM) -e "COLUMNS=$(CONSOLE_COLUMNS)" -e "LINES=$(CONSOLE_LINES)" -it $(DOCKER_CONTAINER) /bin/bash
|
||||
|
||||
docker-test-container: ## Build and run a test container.
|
||||
docker-test-container: docker-build-with-proxy docker-test-cleanup
|
||||
docker run -d --name test-mayan-edms -p 80:8000 -v test-mayan_data:/var/lib/mayan mayanedms/mayanedms:$(DOCKER_VERSION)
|
||||
|
||||
docker-test-cleanup:
|
||||
docker-test-cleanup: ## Delete the test container and the test volume.
|
||||
@docker rm -f test-mayan-edms || true
|
||||
@docker volume rm test-mayan_data || true
|
||||
|
||||
docker-test-all: ## Build and executed the test suite in a test container.
|
||||
docker-test-all: docker-build-with-proxy
|
||||
docker run --rm run-tests
|
||||
|
||||
@@ -126,13 +126,13 @@ Defaults to `None`. This optional environment variable is used to set the hostna
|
||||
|
||||
Defaults to `None`. This optional environment variable is used to set the port number to use when connecting to the database. An empty string means the default port. Not used with SQLite. For more information read the pertinent Django documentation page: [Settings, PORT](https://docs.djangoproject.com/en/1.11/ref/settings/#port)
|
||||
|
||||
### `MAYAN_CELERY_BROKER_URL`
|
||||
### `MAYAN_BROKER_URL`
|
||||
|
||||
Defaults to 'redis://127.0.0.1:6379/0'. This optional environment variable is determines the broker that Celery will use to relay task messages between the frontend code and the background workers. For more information read the pertinent Celery Kombu documentation page: [Broker URL](http://kombu.readthedocs.io/en/latest/userguide/connections.html#connection-urls)
|
||||
|
||||
This Docker image supports using Redis and RabbitMQ as brokers.
|
||||
|
||||
Caveat: If the `MAYAN_CELERY_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
Caveat: If the `MAYAN_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
|
||||
### `MAYAN_CELERY_RESULT_BACKEND`
|
||||
|
||||
@@ -140,7 +140,7 @@ Defaults to 'redis://127.0.0.1:6379/0'. This optional environment variable is de
|
||||
|
||||
This Docker image supports using Redis and RabbitMQ as result backends.
|
||||
|
||||
Caveat: If the `MAYAN_CELERY_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
Caveat: If the `MAYAN_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
|
||||
### `MAYAN_NGINX_CLIENT_MAX_BODY_SIZE`
|
||||
|
||||
|
||||
@@ -126,13 +126,13 @@ Defaults to `None`. This optional environment variable is used to set the hostna
|
||||
|
||||
Defaults to `None`. This optional environment variable is used to set the port number to use when connecting to the database. An empty string means the default port. Not used with SQLite. For more information read the pertinent Django documentation page: [Settings, PORT](https://docs.djangoproject.com/en/1.11/ref/settings/#port)
|
||||
|
||||
### `MAYAN_CELERY_BROKER_URL`
|
||||
### `MAYAN_BROKER_URL`
|
||||
|
||||
Defaults to 'redis://127.0.0.1:6379/0'. This optional environment variable is determines the broker that Celery will use to relay task messages between the frontend code and the background workers. For more information read the pertinent Celery Kombu documentation page: [Broker URL](http://kombu.readthedocs.io/en/latest/userguide/connections.html#connection-urls)
|
||||
|
||||
This Docker image supports using Redis and RabbitMQ as brokers.
|
||||
|
||||
Caveat: If the `MAYAN_CELERY_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
Caveat: If the `MAYAN_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
|
||||
### `MAYAN_CELERY_RESULT_BACKEND`
|
||||
|
||||
@@ -140,7 +140,7 @@ Defaults to 'redis://127.0.0.1:6379/0'. This optional environment variable is de
|
||||
|
||||
This Docker image supports using Redis and RabbitMQ as result backends.
|
||||
|
||||
Caveat: If the `MAYAN_CELERY_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
Caveat: If the `MAYAN_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment variables are specified, the built-in Redis server inside the container will be disabled.
|
||||
|
||||
### `MAYAN_NGINX_CLIENT_MAX_BODY_SIZE`
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ services:
|
||||
results:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
MAYAN_CELERY_BROKER_URL: amqp://mayan:mayan@broker:5672/mayan
|
||||
MAYAN_BROKER_URL: amqp://mayan:mayan@broker:5672/mayan
|
||||
MAYAN_CELERY_RESULT_BACKEND: redis://results:6379/0
|
||||
MAYAN_DATABASE_ENGINE: django.db.backends.postgresql
|
||||
MAYAN_DATABASE_HOST: db
|
||||
|
||||
@@ -45,7 +45,7 @@ services:
|
||||
results:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
MAYAN_CELERY_BROKER_URL: amqp://mayan:mayan@broker:5672/mayan
|
||||
MAYAN_BROKER_URL: amqp://mayan:mayan@broker:5672/mayan
|
||||
MAYAN_CELERY_RESULT_BACKEND: redis://results:6379/0
|
||||
MAYAN_DATABASE_ENGINE: django.db.backends.postgresql
|
||||
MAYAN_DATABASE_HOST: db
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
[program:mayan-gunicorn]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = /bin/bash -c "${MAYAN_GUNICORN_BIN} -w ${MAYAN_GUNICORN_WORKERS} mayan.wsgi --max-requests 500 --max-requests-jitter 50 --worker-class gevent --bind 0.0.0.0:8000 --env DJANGO_SETTINGS_MODULE=${MAYAN_SETTINGS_MODULE}" --timeout 120
|
||||
redirect_stderr = true
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
stdout_logfile = /dev/fd/1
|
||||
stdout_logfile_maxbytes = 0
|
||||
user = mayan
|
||||
|
||||
[program:redis]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = /bin/bash -c "if [ ${MAYAN_CELERY_BROKER_URL} == ${MAYAN_DEFAULT_BROKER_URL} ] && [ ${MAYAN_CELERY_RESULT_BACKEND} == ${MAYAN_DEFAULT_CELERY_RESULT_BACKEND} ];then /usr/bin/redis-server /etc/redis/;fi"
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
stdout_logfile = /dev/fd/1
|
||||
stdout_logfile_maxbytes = 0
|
||||
user = root
|
||||
|
||||
[program:mayan-worker-fast]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = nice -n 1 /bin/bash -c "${MAYAN_BIN} celery --settings=${MAYAN_SETTINGS_MODULE} worker -l ERROR -Q converter,document_states_fast,sources_fast -n mayan-worker-fast.%%h ${MAYAN_WORKER_FAST_CONCURRENCY}"
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
startsecs = 10
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
stdout_logfile = /dev/fd/1
|
||||
stdout_logfile_maxbytes = 0
|
||||
stopwaitsecs = 1
|
||||
user = mayan
|
||||
|
||||
[program:mayan-worker-medium]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = nice -n 18 /bin/bash -c "${MAYAN_BIN} celery --settings=${MAYAN_SETTINGS_MODULE} worker -l ERROR -Q checkouts_periodic,documents_periodic,indexing,metadata,sources,sources_periodic,uploads,documents -n mayan-worker-medium.%%h ${MAYAN_WORKER_MEDIUM_CONCURRENCY}"
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
startsecs = 10
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
stdout_logfile = /dev/fd/1
|
||||
stdout_logfile_maxbytes = 0
|
||||
stopwaitsecs = 1
|
||||
user = mayan
|
||||
|
||||
[program:mayan-worker-slow]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = nice -n 19 /bin/bash -c "${MAYAN_BIN} celery --settings=${MAYAN_SETTINGS_MODULE} worker -l ERROR -Q mailing,tools,statistics,parsing,ocr -n mayan-worker-slow.%%h ${MAYAN_WORKER_SLOW_CONCURRENCY}"
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
startsecs = 10
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
stdout_logfile = /dev/fd/1
|
||||
stdout_logfile_maxbytes = 0
|
||||
stopwaitsecs = 1
|
||||
user = mayan
|
||||
|
||||
[program:mayan-celery-beat]
|
||||
autorestart = false
|
||||
autostart = true
|
||||
command = nice -n 1 /bin/bash -c "${MAYAN_BIN} celery --settings=${MAYAN_SETTINGS_MODULE} beat --pidfile= -l ERROR"
|
||||
killasgroup = true
|
||||
numprocs = 1
|
||||
priority = 998
|
||||
stderr_logfile = /dev/fd/2
|
||||
stderr_logfile_maxbytes = 0
|
||||
stdout_logfile = /dev/fd/1
|
||||
stdout_logfile_maxbytes = 0
|
||||
startsecs = 10
|
||||
stopwaitsecs = 1
|
||||
user = mayan
|
||||
@@ -4,14 +4,16 @@ set -e
|
||||
echo "mayan: starting entrypoint.sh"
|
||||
INSTALL_FLAG=/var/lib/mayan/system/SECRET_KEY
|
||||
CONCURRENCY_ARGUMENT=--concurrency=
|
||||
export DOCKER_ROOT=/opt/mayan-edms
|
||||
|
||||
export MAYAN_DEFAULT_CELERY_BROKER_URL=redis://127.0.0.1:6379/0
|
||||
DEFAULT_USER_UID=1000
|
||||
DEFAULT_USER_GUID=1000
|
||||
|
||||
export MAYAN_DEFAULT_BROKER_URL=redis://127.0.0.1:6379/0
|
||||
export MAYAN_DEFAULT_CELERY_RESULT_BACKEND=redis://127.0.0.1:6379/0
|
||||
|
||||
export MAYAN_ALLOWED_HOSTS='["*"]'
|
||||
export MAYAN_BIN=/opt/mayan-edms/bin/mayan-edms.py
|
||||
export MAYAN_CELERY_BROKER_URL=${MAYAN_CELERY_BROKER_URL:-${MAYAN_DEFAULT_CELERY_BROKER_URL}}
|
||||
export MAYAN_BROKER_URL=${MAYAN_BROKER_URL:-${MAYAN_DEFAULT_BROKER_URL}}
|
||||
export MAYAN_CELERY_RESULT_BACKEND=${MAYAN_CELERY_RESULT_BACKEND:-${MAYAN_DEFAULT_CELERY_RESULT_BACKEND}}
|
||||
export MAYAN_INSTALL_DIR=/opt/mayan-edms
|
||||
export MAYAN_PYTHON_BIN_DIR=/opt/mayan-edms/bin/
|
||||
@@ -21,11 +23,16 @@ export MAYAN_SETTINGS_MODULE=${MAYAN_SETTINGS_MODULE:-mayan.settings.production}
|
||||
export MAYAN_GUNICORN_BIN=${MAYAN_PYTHON_BIN_DIR}gunicorn
|
||||
export MAYAN_GUNICORN_WORKERS=${MAYAN_GUNICORN_WORKERS:-2}
|
||||
export MAYAN_PIP_BIN=${MAYAN_PYTHON_BIN_DIR}pip
|
||||
export MAYAN_STATIC_ROOT=${MAYAN_INSTALL_DIR}/static
|
||||
|
||||
MAYAN_WORKER_FAST_CONCURRENCY=${MAYAN_WORKER_FAST_CONCURRENCY:-1}
|
||||
MAYAN_WORKER_MEDIUM_CONCURRENCY=${MAYAN_WORKER_MEDIUM_CONCURRENCY:-1}
|
||||
MAYAN_WORKER_SLOW_CONCURRENCY=${MAYAN_WORKER_SLOW_CONCURRENCY:-1}
|
||||
|
||||
echo "mayan: changing uid/guid"
|
||||
usermod mayan -u ${MAYAN_USER_UID:-${DEFAULT_USER_UID}}
|
||||
groupmod mayan -g ${MAYAN_USER_GUID:-${DEFAULT_USER_GUID}}
|
||||
|
||||
if [ "$MAYAN_WORKER_FAST_CONCURRENCY" -eq 0 ]; then
|
||||
MAYAN_WORKER_FAST_CONCURRENCY=
|
||||
else
|
||||
@@ -52,16 +59,30 @@ export PYTHONPATH=$PYTHONPATH:$MAYAN_MEDIA_ROOT
|
||||
|
||||
chown mayan:mayan /var/lib/mayan -R
|
||||
|
||||
initialize() {
|
||||
echo "mayan: initialize()"
|
||||
su mayan -c "${MAYAN_BIN} initialsetup --force"
|
||||
su mayan -c "${MAYAN_BIN} collectstatic --noinput --clear"
|
||||
apt_get_install() {
|
||||
apt-get -q update
|
||||
apt-get install -y --force-yes --no-install-recommends --auto-remove "$@"
|
||||
apt-get -q clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
}
|
||||
|
||||
upgrade() {
|
||||
echo "mayan: upgrade()"
|
||||
su mayan -c "${MAYAN_BIN} performupgrade"
|
||||
su mayan -c "${MAYAN_BIN} collectstatic --noinput --clear"
|
||||
initialize() {
|
||||
echo "mayan: initialize()"
|
||||
su mayan -c "${MAYAN_BIN} initialsetup --force --no-javascript"
|
||||
}
|
||||
|
||||
os_package_installs() {
|
||||
echo "mayan: os_package_installs()"
|
||||
if [ "${MAYAN_APT_INSTALLS}" ]; then
|
||||
DEBIAN_FRONTEND=noninteractive apt_get_install $MAYAN_APT_INSTALLS
|
||||
fi
|
||||
}
|
||||
|
||||
pip_installs() {
|
||||
echo "mayan: pip_installs()"
|
||||
if [ "${MAYAN_PIP_INSTALLS}" ]; then
|
||||
su mayan -c "${MAYAN_PIP_BIN} install $MAYAN_PIP_INSTALLS"
|
||||
fi
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -70,18 +91,9 @@ start() {
|
||||
exec /usr/bin/supervisord -nc /etc/supervisor/supervisord.conf
|
||||
}
|
||||
|
||||
os_package_installs() {
|
||||
echo "mayan: os_package_installs()"
|
||||
if [ "${MAYAN_APT_INSTALLS}" ]; then
|
||||
apt-get-install $MAYAN_APT_INSTALLS
|
||||
fi
|
||||
}
|
||||
|
||||
pip_installs() {
|
||||
echo "mayan: pip_installs()"
|
||||
if [ "${MAYAN_PIP_INSTALLS}" ]; then
|
||||
$MAYAN_PIP_BIN install $MAYAN_PIP_INSTALLS
|
||||
fi
|
||||
upgrade() {
|
||||
echo "mayan: upgrade()"
|
||||
su mayan -c "${MAYAN_BIN} performupgrade --no-javascript"
|
||||
}
|
||||
|
||||
os_package_installs || true
|
||||
@@ -106,7 +118,7 @@ run-tests) # Check if this is a new install, otherwise try to upgrade the existi
|
||||
else
|
||||
upgrade
|
||||
fi
|
||||
$DOCKER_ROOT/run-tests.sh
|
||||
run-tests.sh
|
||||
;;
|
||||
|
||||
*) su mayan -c "$@";
|
||||
10
docker/rootfs/usr/local/bin/run-tests.sh
Executable file
10
docker/rootfs/usr/local/bin/run-tests.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends gcc python-dev tesseract-ocr-deu
|
||||
|
||||
su mayan -c "$MAYAN_PIP_BIN install -r ${MAYAN_INSTALL_DIR}/testing-base.txt"
|
||||
|
||||
su mayan -c "$MAYAN_BIN test --mayan-apps --settings=mayan.settings.testing"
|
||||
1
docker/rootfs/version
Executable file
1
docker/rootfs/version
Executable file
@@ -0,0 +1 @@
|
||||
3.2b1
|
||||
@@ -27,6 +27,6 @@ services:
|
||||
MAYAN_DATABASE_NAME: mayan
|
||||
MAYAN_DATABASE_PASSWORD: mayan-password
|
||||
MAYAN_DATABASE_USER: mayan
|
||||
MAYAN_DATABASE_CONN_MAX_AGE: 60
|
||||
MAYAN_DATABASE_CONN_MAX_AGE: 0
|
||||
volumes:
|
||||
- app:/var/lib/mayan
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
3.1.9
|
||||
5
docs/_static/css/custom.css
vendored
Normal file
5
docs/_static/css/custom.css
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.menuselection {
|
||||
color: white;
|
||||
background: #2c3e50;
|
||||
padding: 3px;
|
||||
}
|
||||
@@ -26,3 +26,77 @@ endpoints are structured by resource type. Examples:
|
||||
|
||||
The API supports the HTTP verbs: **GET**, **POST**, **PUT**, **PATCH**,
|
||||
and **DELETE**.
|
||||
|
||||
|
||||
Example use
|
||||
===========
|
||||
|
||||
Install Python Requests (http://docs.python-requests.org/en/master/)::
|
||||
|
||||
pip install requests
|
||||
|
||||
Get a list of document types::
|
||||
|
||||
import requests
|
||||
|
||||
requests.get('http://127.0.0.1:8000/api/document_types/', auth=('username', 'password')).json()
|
||||
|
||||
{u'count': 1,
|
||||
u'next': None,
|
||||
u'previous': None,
|
||||
u'results': [{u'delete_time_period': 30,
|
||||
u'delete_time_unit': u'days',
|
||||
u'documents_count': 12,
|
||||
u'documents_url': u'http://127.0.0.1:8000/api/document_types/1/documents/',
|
||||
u'filenames': [],
|
||||
u'id': 1,
|
||||
u'label': u'Default',
|
||||
u'trash_time_period': None,
|
||||
u'trash_time_unit': None,
|
||||
u'url': u'http://127.0.0.1:8000/api/document_types/1/'}]}
|
||||
|
||||
Upload a new document::
|
||||
|
||||
with open('test_document.pdf', mode='rb') as
|
||||
requests.post('http://127.0.0.1:8000/api/documents/', auth=('username', 'password'), files={'file': file_object}, data={'document_type': 1}).json()
|
||||
|
||||
{u'description': u'',
|
||||
u'document_type': 1,
|
||||
u'id': 19,
|
||||
u'label': u'test_document.pdf',
|
||||
u'language': u'eng'}
|
||||
|
||||
Use API tokens to avoid sending the username and password on every request. Obtain a token by making a POST request to ``/api/auth/token/obtain/?format=json``::
|
||||
|
||||
requests.post('http://127.0.0.1:8000/api/auth/token/obtain/?format=json', data={'username': 'username', 'password': 'password'}).json()
|
||||
|
||||
{u'token': u'4ccbc35b5eb327aa82dc3b7c9747b578900f02bb'}
|
||||
|
||||
Add the API token to the request header::
|
||||
|
||||
headers = {'Authorization': 'Token 4ccbc35b5eb327aa82dc3b7c9747b578900f02bb'}
|
||||
|
||||
requests.get('http://127.0.0.1:8000/api/document_types/', headers=headers).json()
|
||||
|
||||
{u'description': u'',
|
||||
u'document_type': 1,
|
||||
u'id': 19,
|
||||
u'label': u'test_document.pdf',
|
||||
u'language': u'eng'}
|
||||
|
||||
|
||||
Use sessions to avoid having to add the headers on each request::
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
headers = {'Authorization': 'Token 4ccbc35b5eb327aa82dc3b7c9747b578900f02bb'}
|
||||
|
||||
session.headers.update(headers)
|
||||
|
||||
session.get('http://127.0.0.1:8000/api/document_types/')
|
||||
|
||||
{u'description': u'',
|
||||
u'document_type': 1,
|
||||
u'id': 19,
|
||||
u'label': u'test_document.pdf',
|
||||
u'language': u'eng'}
|
||||
|
||||
@@ -59,6 +59,17 @@ App modules
|
||||
corresponding signal in the ready() method of the MayanAppConfig subclass in
|
||||
apps.py
|
||||
|
||||
- html_widgets.py
|
||||
|
||||
Classes to render an HTML widget. HTML widget are not the same as Django's
|
||||
native form widgets. Form widgets only work as part of a form field.
|
||||
HTML widgets are for use outside of forms, such as in a table cell.
|
||||
|
||||
- licenses.py
|
||||
|
||||
This module outlines the license text of the third party content used in
|
||||
the app. It could be other Python libraries, JavaScript libraries, etc.
|
||||
|
||||
- links.py
|
||||
|
||||
Defines the links to be used by the app. Import only from the navigation app
|
||||
@@ -92,6 +103,11 @@ App modules
|
||||
This module acts as a shared memory space for the other modules of the app or
|
||||
other apps.
|
||||
|
||||
- search.py
|
||||
|
||||
Search model definitions. Define which field of the app's models are
|
||||
searchable.
|
||||
|
||||
- serializers.py
|
||||
|
||||
Hold Django REST Framework serializers used by the api_views.py module.
|
||||
@@ -127,7 +143,7 @@ App modules
|
||||
|
||||
- widgets.py
|
||||
|
||||
HTML widgets go here. This should be the only place with presentation
|
||||
Custom form widgets go here. This should be the only place with presentation
|
||||
directives in the app (aside the templates).
|
||||
|
||||
|
||||
@@ -136,8 +152,8 @@ 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``.
|
||||
are: SingleObjectCreateView, SingleObjectDetailView, SingleObjectEditView,
|
||||
and SingleObjectListView
|
||||
|
||||
These views handle aspects relating to view permissions, object permissions,
|
||||
post action redirection and template context generation.
|
||||
|
||||
@@ -59,7 +59,7 @@ Example::
|
||||
-e POSTGRES_DB=mayan \
|
||||
-e POSTGRES_PASSWORD=mayanuserpass \
|
||||
-v /docker-volumes/mayan-edms/postgres-new:/var/lib/postgresql/data \
|
||||
-d postgres:9.5
|
||||
-d postgres:9.6
|
||||
|
||||
docker exec -i mayan-edms-pg-new pg_restore -U mayan -d mayan < 2018-06-07_17-09-34.dump
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Direct install
|
||||
|
||||
* Install the Python client for PostgreSQL::
|
||||
|
||||
sudo -u mayan /opt/mayan-edms/bin/pip install --no-cache-dir psycopg2==2.7.3.2
|
||||
sudo -u mayan /opt/mayan-edms/bin/pip install --no-cache-dir --no-use-pep517 psycopg2==2.7.3.2
|
||||
|
||||
* Copy the newly created fallback config file::
|
||||
|
||||
@@ -99,5 +99,5 @@ Direct install
|
||||
MAYAN_DATABASE_NAME=mayan,
|
||||
MAYAN_DATABASE_PASSWORD=mayanuserpass,
|
||||
MAYAN_DATABASE_USER=mayan,
|
||||
MAYAN_DATABASE_CONN_MAX_AGE=360,
|
||||
MAYAN_DATABASE_CONN_MAX_AGE=0,
|
||||
<...>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -447,28 +447,13 @@ Version numbering
|
||||
=================
|
||||
|
||||
Mayan EDMS uses the Semantic Versioning (http://semver.org/) method to choose
|
||||
version numbers along with Python's PEP-0440
|
||||
(https://www.python.org/dev/peps/pep-0440/) to format them.
|
||||
version numbers along with Python's PEP-0440 (https://www.python.org/dev/peps/pep-0440/)
|
||||
to format them.
|
||||
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
| Version number | Name | Description |
|
||||
+================+===================+=========================================+
|
||||
| X.YalphaN | Alpha release | Usable but unstable, API changes. |
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
| X.YbetaN | Beta release | Code is frozen, testing. |
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
| X.YrcN | Release Candidate | Almost ready for production, not major |
|
||||
| | | changes between this version and the |
|
||||
| | | final release. |
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
| X.Y | Final release | API changes, many backward incompatible |
|
||||
| | | changes. |
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
| X.Y+1 | Minor release | Minor changes, minor backwards |
|
||||
| | | incompatible changes |
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
| X.Y.Z | Micro release | Minor changes, bugfixes. |
|
||||
+----------------+-------------------+-----------------------------------------+
|
||||
X.YaN # Alpha release
|
||||
X.YbN # Beta release
|
||||
X.YrcN # Release Candidate
|
||||
X.Y # Final release
|
||||
|
||||
|
||||
Release checklist
|
||||
|
||||
@@ -1,10 +1,125 @@
|
||||
************
|
||||
============
|
||||
Docker image
|
||||
************
|
||||
============
|
||||
|
||||
How to use this image
|
||||
=====================
|
||||
|
||||
.. _docker_install:
|
||||
|
||||
Start a Mayan EDMS Docker image
|
||||
-------------------------------
|
||||
|
||||
With Docker properly installed, proceed to download the Mayan EDMS image using
|
||||
the command::
|
||||
|
||||
docker pull mayanedms/mayanedms:<version>
|
||||
|
||||
Instead of a specific version tag you may use then generic ``:latest`` tag
|
||||
to the get latest version available automatically. If you use the ``:latest``
|
||||
tag here, remember to do so in the next steps also.::
|
||||
|
||||
docker pull mayanedms/mayanedms:latest
|
||||
|
||||
Then download version 9.6 of the Docker PostgreSQL image::
|
||||
|
||||
docker pull postgres:9.6
|
||||
|
||||
Create and run a PostgreSQL container::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms-postgres \
|
||||
--restart=always \
|
||||
-p 5432:5432 \
|
||||
-e POSTGRES_USER=mayan \
|
||||
-e POSTGRES_DB=mayan \
|
||||
-e POSTGRES_PASSWORD=mayanuserpass \
|
||||
-v /docker-volumes/mayan-edms/postgres:/var/lib/postgresql/data \
|
||||
-d postgres:9.6
|
||||
|
||||
The PostgreSQL container will have one database named ``mayan``, with an user
|
||||
named ``mayan`` too, with a password of ``mayanuserpass``. The container will
|
||||
expose its internal 5432 port (PostgreSQL's default port) via the host's
|
||||
5432 port. The data of this container will reside on the host's
|
||||
``/docker-volumes/mayan-edms/postgres`` folder.
|
||||
|
||||
Finally create and run a Mayan EDMS container.
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms \
|
||||
--restart=always \
|
||||
-p 80:8000 \
|
||||
-e MAYAN_DATABASE_ENGINE=django.db.backends.postgresql \
|
||||
-e MAYAN_DATABASE_HOST=172.17.0.1 \
|
||||
-e MAYAN_DATABASE_NAME=mayan \
|
||||
-e MAYAN_DATABASE_PASSWORD=mayanuserpass \
|
||||
-e MAYAN_DATABASE_USER=mayan \
|
||||
-e MAYAN_DATABASE_CONN_MAX_AGE=0 \
|
||||
-v /docker-volumes/mayan-edms/media:/var/lib/mayan \
|
||||
mayanedms/mayanedms:<version>
|
||||
|
||||
The Mayan EDMS container will connect to the PostgreSQL container via the
|
||||
``172.17.0.1`` IP address (the Docker host's default IP address). It will
|
||||
connect using the ``django.db.backends.postgresql`` database driver and
|
||||
connect to the ``mayan`` database using the ``mayan`` user with the password
|
||||
``mayanuserpass``. The container will keep connections to the database
|
||||
for up to 60 seconds in an attempt to reuse them increasing response time
|
||||
and reducing memory usage. The files of the container will be store in the
|
||||
host's ``/docker-volumes/mayan-edms/media`` folder. The container will
|
||||
expose its web service running on port 8000 on the host's port 80.
|
||||
|
||||
The container will be available by browsing to ``http://localhost`` or to
|
||||
the IP address of the computer running the container.
|
||||
|
||||
If another web server is running on port 80 use a different port in the
|
||||
``-p`` option. For example: ``-p 81:8000``.
|
||||
|
||||
|
||||
Using a dedicated Docker network
|
||||
--------------------------------
|
||||
|
||||
Use this method to avoid having to expose PostreSQL port to the host's network
|
||||
or if you have other PostgreSQL instances but still want to use the default
|
||||
port of 5432 for this installation.
|
||||
|
||||
Create the network::
|
||||
|
||||
docker network create mayan
|
||||
|
||||
Launch the PostgreSQL container with the network option and remove the port
|
||||
binding (``-p 5432:5432``)::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms-postgres \
|
||||
--network=mayan \
|
||||
--restart=always \
|
||||
-e POSTGRES_USER=mayan \
|
||||
-e POSTGRES_DB=mayan \
|
||||
-e POSTGRES_PASSWORD=mayanuserpass \
|
||||
-v /docker-volumes/mayan-edms/postgres:/var/lib/postgresql/data \
|
||||
-d postgres:9.6
|
||||
|
||||
Launch the Mayan EDMS container with the network option and change the
|
||||
database hostname to the PostgreSQL container name (``mayan-edms-postgres``)
|
||||
instead of the IP address of the Docker host (``172.17.0.1``)::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms \
|
||||
--network=mayan \
|
||||
--restart=always \
|
||||
-p 80:8000 \
|
||||
-e MAYAN_DATABASE_ENGINE=django.db.backends.postgresql \
|
||||
-e MAYAN_DATABASE_HOST=mayan-edms-postgres \
|
||||
-e MAYAN_DATABASE_NAME=mayan \
|
||||
-e MAYAN_DATABASE_PASSWORD=mayanuserpass \
|
||||
-e MAYAN_DATABASE_USER=mayan \
|
||||
-e MAYAN_DATABASE_CONN_MAX_AGE=0 \
|
||||
-v /docker-volumes/mayan-edms/media:/var/lib/mayan \
|
||||
mayanedms/mayanedms:<version>
|
||||
|
||||
|
||||
Stopping and starting the container
|
||||
===================================
|
||||
-----------------------------------
|
||||
|
||||
To stop the container use::
|
||||
|
||||
@@ -18,12 +133,11 @@ To start the container again::
|
||||
|
||||
.. _docker_environment_variables:
|
||||
|
||||
Environment Variables
|
||||
=====================
|
||||
|
||||
In addition to the all the environment variables supported by Mayan EDMS, the
|
||||
Mayan EDMS image provides some additional variables to configure the Docker
|
||||
specifics of the image.
|
||||
Environment Variables
|
||||
---------------------
|
||||
|
||||
The Mayan EDMS image can be configure via environment variables.
|
||||
|
||||
``MAYAN_DATABASE_ENGINE``
|
||||
|
||||
@@ -39,6 +153,27 @@ When using the SQLite backend, the database file will be saved in the Docker
|
||||
volume. The SQLite database as used by Mayan EDMS is meant only for development
|
||||
or testing, never use it in production.
|
||||
|
||||
``MAYAN_DATABASE_NAME``
|
||||
|
||||
Defaults to 'mayan'. This optional environment variable can be used to define
|
||||
the database name that Mayan EDMS will connect to. For more information read
|
||||
the pertinent Django documentation page:
|
||||
:django-docs:`Connecting to the database <ref/databases/#connecting-to-the-database>`
|
||||
|
||||
``MAYAN_DATABASE_USER``
|
||||
|
||||
Defaults to 'mayan'. This optional environment variable is used to set the
|
||||
username that will be used to connect to the database. For more information
|
||||
read the pertinent Django documentation page:
|
||||
:django-docs:`Settings, USER <ref/settings/#user>`
|
||||
|
||||
``MAYAN_DATABASE_PASSWORD``
|
||||
|
||||
Defaults to ''. This optional environment variable is used to set the
|
||||
password that will be used to connect to the database. For more information
|
||||
read the pertinent Django documentation page:
|
||||
:django-docs:`Settings, PASSWORD <ref/settings/#password>`
|
||||
|
||||
``MAYAN_DATABASE_HOST``
|
||||
|
||||
Defaults to `None`. This optional environment variable is used to set the
|
||||
@@ -55,7 +190,7 @@ the default port. Not used with SQLite. For more information read the
|
||||
pertinent Django documentation page:
|
||||
:django-docs:`Settings, PORT <ref/settings/#port>`
|
||||
|
||||
``MAYAN_CELERY_BROKER_URL``
|
||||
``MAYAN_BROKER_URL``
|
||||
|
||||
This optional environment variable determines the broker that Celery will use
|
||||
to relay task messages between the frontend code and the background workers.
|
||||
@@ -65,7 +200,7 @@ For more information read the pertinent Celery Kombu documentation page: `Broker
|
||||
|
||||
This Docker image supports using Redis and RabbitMQ as brokers.
|
||||
|
||||
Caveat: If the `MAYAN_CELERY_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment
|
||||
Caveat: If the `MAYAN_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment
|
||||
variables are specified, the built-in Redis server inside the container will
|
||||
be disabled.
|
||||
|
||||
@@ -80,7 +215,7 @@ code. For more information read the pertinent Celery Kombu documentation page:
|
||||
|
||||
This Docker image supports using Redis and RabbitMQ as result backends.
|
||||
|
||||
Caveat: If the `MAYAN_CELERY_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment
|
||||
Caveat: If the `MAYAN_BROKER_URL` and `MAYAN_CELERY_RESULT_BACKEND` environment
|
||||
variables are specified, the built-in Redis server inside the container will
|
||||
be disabled.
|
||||
|
||||
@@ -88,6 +223,16 @@ be disabled.
|
||||
|
||||
Optional. Allows loading an alternate settings file.
|
||||
|
||||
``MAYAN_DATABASE_CONN_MAX_AGE``
|
||||
|
||||
Amount in seconds to keep a database connection alive. Allow reuse of database
|
||||
connections. For more information read the pertinent Django documentation
|
||||
page: :django-docs:`Settings, CONN_MAX_AGE <ref/settings/#conn-max-age>`
|
||||
According to new information Gunicorn's microthreads don't share connections
|
||||
and will exhaust the available Postgres connections available if a number
|
||||
other than 0 is used. Reference: https://serverfault.com/questions/635100/django-conn-max-age-persists-connections-but-doesnt-reuse-them-with-postgresq
|
||||
and https://github.com/benoitc/gunicorn/issues/996
|
||||
|
||||
``MAYAN_GUNICORN_WORKERS``
|
||||
|
||||
Optional. This environment variable controls the number of frontend workers
|
||||
@@ -119,6 +264,18 @@ category. Default is 1. Use 0 to disable hardcoded concurrency and allow the
|
||||
Celery worker to launch its default number of child processes (equal to the
|
||||
number of CPUs detected).
|
||||
|
||||
``MAYAN_USER_UID``
|
||||
|
||||
Optional. Changes the UID of the ``mayan`` user internal to the Docker
|
||||
container. Defaults to 1000.
|
||||
|
||||
``MAYAN_USER_GUID``
|
||||
|
||||
Optional. Changes the GUID of the ``mayan`` user internal to the Docker
|
||||
container. Defaults to 1000.
|
||||
|
||||
|
||||
.. _docker-accessing-outside-data:
|
||||
|
||||
Accessing outside data
|
||||
======================
|
||||
@@ -230,7 +387,6 @@ running the APT proxy and caching service.
|
||||
Customizing the image
|
||||
=====================
|
||||
|
||||
|
||||
Simple method
|
||||
-------------
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
*******************
|
||||
Docker installation
|
||||
*******************
|
||||
|
||||
Docker is a system that allows running programs in isolated areas which
|
||||
have restricted access to resources, devices, and memory. Docker usage also
|
||||
distributing software as a single file.
|
||||
|
||||
Make sure Docker is properly installed and working before attempting to install
|
||||
Mayan EDMS.
|
||||
|
||||
Docker can be installed using their automated script::
|
||||
|
||||
wget -qO- https://get.docker.com/ | sh
|
||||
|
||||
This installs the latest versions of Docker. If you don't want run an automated
|
||||
script follow the instructions outlined in their documentation:
|
||||
https://docs.docker.com/install/
|
||||
|
||||
With Docker properly installed, proceed to download the Mayan EDMS image using the command::
|
||||
|
||||
docker pull mayanedms/mayanedms:<version>
|
||||
|
||||
Then download version 9.5 of the Docker PostgreSQL image::
|
||||
|
||||
docker pull postgres:9.5
|
||||
|
||||
Create and run a PostgreSQL container::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms-postgres \
|
||||
--restart=always \
|
||||
-p 5432:5432 \
|
||||
-e POSTGRES_USER=mayan \
|
||||
-e POSTGRES_DB=mayan \
|
||||
-e POSTGRES_PASSWORD=mayanuserpass \
|
||||
-v /docker-volumes/mayan-edms/postgres:/var/lib/postgresql/data \
|
||||
-d postgres:9.5
|
||||
|
||||
The PostgreSQL container will have one database named ``mayan``, with an user
|
||||
named ``mayan`` too, with a password of ``mayanuserpass``. The container will
|
||||
expose its internal 5432 port (PostgreSQL's default port) via the host's
|
||||
5432 port. The data of this container will reside on the host's
|
||||
``/docker-volumes/mayan-edms/postgres`` folder.
|
||||
|
||||
Finally create and run a Mayan EDMS container. Change <version> with the
|
||||
latest version in numeric form (example: 2.7.3) or use the ``latest``
|
||||
identifier::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms \
|
||||
--restart=always \
|
||||
-p 80:8000 \
|
||||
-e MAYAN_DATABASES='{default: {ENGINE: django.db.backends.postgresql, HOST: 172.17.0.1, NAME: mayan, PASSWORD: mayanuserpass, USER: mayan, CONN_MAX_AGE: 60}}' \
|
||||
-v /docker-volumes/mayan-edms/media:/var/lib/mayan \
|
||||
mayanedms/mayanedms:<version>
|
||||
|
||||
The Mayan EDMS container will connect to the PostgreSQL container via the
|
||||
``172.17.0.1`` IP address (the Docker host's default IP address). It will
|
||||
connect using the ``django.db.backends.postgresql`` database driver and
|
||||
connect to the ``mayan`` database using the ``mayan`` user with the password
|
||||
``mayanuserpass``. The container will keep connections to the database
|
||||
for up to 60 seconds in an attempt to reuse them increasing response time
|
||||
and reducing memory usage. The files of the container will be store in the
|
||||
host's ``/docker-volumes/mayan-edms/media`` folder. The container will
|
||||
expose its web service running on port 8000 on the host's port 80.
|
||||
|
||||
The container will be available by browsing to ``http://localhost`` or to
|
||||
the IP address of the computer running the container.
|
||||
|
||||
If another web server is running on port 80 use a different port in the
|
||||
``-p`` option. For example: ``-p 81:8000``.
|
||||
|
||||
|
||||
Using a dedicated Docker network
|
||||
================================
|
||||
Use this method to avoid having to expose PostreSQL port to the host's network
|
||||
or if you have other PostgreSQL instances but still want to use the default
|
||||
port of 5432 for this installation.
|
||||
|
||||
Create the network::
|
||||
|
||||
docker network create mayan
|
||||
|
||||
Launch the PostgreSQL container with the network option and remove the port
|
||||
binding (``-p 5432:5432``)::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms-postgres \
|
||||
--network=mayan \
|
||||
--restart=always \
|
||||
-e POSTGRES_USER=mayan \
|
||||
-e POSTGRES_DB=mayan \
|
||||
-e POSTGRES_PASSWORD=mayanuserpass \
|
||||
-v /docker-volumes/mayan-edms/postgres:/var/lib/postgresql/data \
|
||||
-d postgres:9.5
|
||||
|
||||
Launch the Mayan EDMS container with the network option and change the
|
||||
database hostname to the PostgreSQL container name (``mayan-edms-postgres``)
|
||||
instead of the IP address of the Docker host (``172.17.0.1``)::
|
||||
|
||||
docker run -d \
|
||||
--name mayan-edms \
|
||||
--network=mayan \
|
||||
--restart=always \
|
||||
-p 80:8000 \
|
||||
-e MAYAN_DATABASES='{default: {ENGINE: django.db.backends.postgresql, HOST: mayan-edms-postgres, NAME: mayan, PASSWORD: mayanuserpass, USER: mayan, CONN_MAX_AGE: 60}}' \
|
||||
-v /docker-volumes/mayan-edms/media:/var/lib/mayan \
|
||||
mayanedms/mayanedms:<version>
|
||||
@@ -68,5 +68,21 @@ 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.
|
||||
|
||||
Document types are create in the
|
||||
:menuselection:`System --> Setup --> Document types` menu.
|
||||
|
||||
Creating document types
|
||||
=======================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Create document types" permission is required for this action.
|
||||
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Document types` menu.
|
||||
#. From the :guilabel:`Actions` dropdown select :guilabel:`Create document type`.
|
||||
#. Enter a label to be shown to users when using this document type.
|
||||
#. Optional: Enter a period of time after which documents of this type will be moved to the trash.
|
||||
#. Optional: Select the unit of time for the period after which the document will be moved to the trash.
|
||||
#. Optional: Enter a period of time after which documents moved to the trash will be permanently deleted.
|
||||
#. Optional: Select the unit of time for the period of time after which the documents moved to the trash will be permanently deleted
|
||||
#. Press :guilabel:`Submit`.
|
||||
|
||||
@@ -5,22 +5,32 @@ Index examples
|
||||
Index of document types
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
- The "Create new document indexes" permission is required for this action.
|
||||
- The "Edit document indexes" permission is required for this action, globally
|
||||
of via an ACL for a document index.
|
||||
- The "Edit document types" permission is required for this action, globally
|
||||
of via an ACL for a document type.
|
||||
|
||||
|
||||
This index will create one level for each document type in the system and place
|
||||
links to the document of each respective type.
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Indexes` menu.
|
||||
#. Create a new index using :menuselection:`Actions --> Create new`.
|
||||
#. Create a new index using :guilabel:`Actions` > :guilabel:`Create new`.
|
||||
#. Give it a label to describe it, and an internal name. The internal name is
|
||||
used when referencing this index in other parts of the system.
|
||||
#. Press the :menuselection:`Template` link of the newly created index.
|
||||
#. Select :menuselection:`New child node` to create a new level in which the
|
||||
#. Press the :guilabel:`Template` link of the newly created index.
|
||||
#. Select :guilabel:`New child node` to create a new level in which the
|
||||
following template code will be entered.
|
||||
::
|
||||
|
||||
{{ document.document_type }}
|
||||
|
||||
#. Save the template.
|
||||
#. Go to :menuselection:`Document types` and associate this index with
|
||||
#. Click on :guilabel:`Document types` and associate this index with
|
||||
existing document types in the system.
|
||||
#. Finally go to :menuselection:`Tools --> Rebuild indexes` to execute the
|
||||
index template. The rebuild process is only necessary when changes are
|
||||
@@ -86,11 +96,11 @@ Index by OCR content
|
||||
This example indexes documents in a "quarterly report" level if they have the
|
||||
fragment “quarterly report” in the OCR text::
|
||||
|
||||
{% if "quarterly report" in document.ocr_content.lower() %}Quarterly reports{% endif %}
|
||||
{% if "quarterly report" in document.latest_version.ocr_content|join:" "|lower %}Quarterly reports{% endif %}
|
||||
|
||||
The same applies to text content extracted for the document::
|
||||
|
||||
{% if "quarterly report" in document.content.lower() %}Quarterly reports{% endif %}
|
||||
{% if "quarterly report" in document.latest_version.content|join:" "|lower %}Quarterly reports{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ The list of languages choices in the language dropdown used for documents is
|
||||
based on the current ISO 639 list. This list can be quite extensive. To reduce
|
||||
the number of languages available use the setting ``DOCUMENTS_LANGUAGE_CODES``,
|
||||
and set it to a nested list of abbreviations. This setting can be found in the
|
||||
:menuselection:`System --> Setup -> Settings -> Common` menu.
|
||||
:menuselection:`System --> Setup --> Settings --> Common` menu.
|
||||
|
||||
For example, to reduce the list to just English and Spanish use
|
||||
::
|
||||
|
||||
@@ -26,3 +26,74 @@ 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.
|
||||
|
||||
|
||||
Creating metadata types
|
||||
=======================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Create new metadata types" permission is required for this action.
|
||||
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Metadata types` menu.
|
||||
#. From the :guilabel:`Actions` dropdown select :guilabel:`Create new`.
|
||||
#. Provide a name to reference this metadata type in other parts of the system.
|
||||
#. Enter a label to be shown to users when using this metadata type.
|
||||
#. Optional: Enter a default value for the metadata type.
|
||||
#. Optional: Provide a comma separated list of options to restrict the data entry
|
||||
when using this metadata type.
|
||||
#. Optional: Select a validator and a parser to validate and cleanup the data
|
||||
entry when not using a predetermined list of values.
|
||||
#. Press :guilabel:`Submit`.
|
||||
|
||||
|
||||
Assigning a metadata type to a document type
|
||||
============================================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
- The "Edit metadata types" permission is required for this action, globally or
|
||||
via an ACL for a metadata type.
|
||||
- Also the "Edit document type" permission
|
||||
is required, globally or via an ACL for a document type.
|
||||
|
||||
|
||||
This action can be performed in two ways.
|
||||
|
||||
Option 1: Via the metadata type view
|
||||
------------------------------------
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Metadata types` menu.
|
||||
#. Click on the button :guilabel:`Document types` of the metadata type you which
|
||||
to associate.
|
||||
#. From the list of existing document types press either:
|
||||
|
||||
- :guilabel:`None` if this metadata type will not be available for documents
|
||||
of the type.
|
||||
- :guilabel:`Optional` if this metadata type will be available and is
|
||||
optional to provide a value for documents of the type.
|
||||
- :guilabel:`Required` if this metadata type will be available and is
|
||||
required to provide a value for documents of the type.
|
||||
|
||||
#. Press :guilabel:`Save`.
|
||||
|
||||
|
||||
Option 2: Via the document type view
|
||||
------------------------------------
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Document types` menu.
|
||||
#. Click on the button :guilabel:`Metadata types` of the metadata type you which
|
||||
to associate.
|
||||
#. From the list of existing metadata types press either:
|
||||
|
||||
- :guilabel:`None` if this metadata type will not be available for documents
|
||||
of the type.
|
||||
- :guilabel:`Optional` if this metadata type will be available and is
|
||||
optional to provide a value for documents of the type.
|
||||
- :guilabel:`Required` if this metadata type will be available and is
|
||||
required to provide a value for documents of the type.
|
||||
|
||||
#. Press :guilabel:`Save`.
|
||||
|
||||
@@ -29,32 +29,3 @@ to use a S3 style storage for documents.
|
||||
'{access_key: <your S3 access key>, secret_key: <your S3 secret key>, bucket_name: <S3 bucket name>}'
|
||||
|
||||
5. Save and restart your Mayan EDMS installation for the setting to take effect.
|
||||
|
||||
|
||||
Storage
|
||||
=======
|
||||
Mayan EDMS stores documents in their original file format only changing the
|
||||
filename to avoid collision. For best input and output speed use a block
|
||||
based local filesystem for the ``/media`` sub folder of the path specified by
|
||||
the MEDIA_ROOT setting. For increased storage capacity use an object storage
|
||||
filesystem like S3.
|
||||
|
||||
To use a S3 compatible object storage do the following:
|
||||
|
||||
* Install the Python packages ``django-storages`` and ``boto3``:
|
||||
|
||||
* Using Python::
|
||||
|
||||
pip install django-storages boto3
|
||||
|
||||
* Using Docker::
|
||||
|
||||
-e MAYAN_PIP_INSTALLS='django-storages boto3'
|
||||
|
||||
On the Mayan EDMS user interface, go to ``System``, ``Setup``, ``Settings``,
|
||||
``Documents`` and change the following setting:
|
||||
|
||||
* ``DOCUMENTS_STORAGE_BACKEND`` to ``storages.backends.s3boto3.S3Boto3Storage``
|
||||
* ``DOCUMENTS_STORAGE_BACKEND_ARGUMENTS`` to ``'{access_key: <your access key>, secret_key: <your secret key>, bucket_name: <bucket name>}'``.
|
||||
|
||||
Restart Mayan EDMS for the changes to take effect.
|
||||
|
||||
@@ -15,7 +15,6 @@ via the :ref:`configuration file <configuration_file>`.
|
||||
|
||||
Example::
|
||||
|
||||
DEFAULT_FROM_EMAIL: '<your administrator email>'
|
||||
EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend
|
||||
EMAIL_HOST: '<your smtp ip address or hostname>'
|
||||
EMAIL_HOST_PASSWORD: '<your smtp password>'
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
*******************
|
||||
Password validation
|
||||
*******************
|
||||
|
||||
To help reduce the use of weak passwords, Mayan EDMS includes support for
|
||||
password validators. Password validator enforce policies by rejecting
|
||||
password that don't conform with the validator's logic.
|
||||
|
||||
By default, Mayan EDMS sets this password validation setup:
|
||||
|
||||
- That the password is not similar no any user attributes.
|
||||
- A minimum password size of 8 characters.
|
||||
- The password is not one of the 20,000 commonly used weak password.
|
||||
- That the password is not entirely numeric.
|
||||
|
||||
This default is coded in the following manner by the default Python setup file::
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
If using the YAML configuration file the same setup would be coded in the
|
||||
following manner::
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS:
|
||||
- NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator
|
||||
- NAME: django.contrib.auth.password_validation.MinimumLengthValidator
|
||||
- NAME: django.contrib.auth.password_validation.CommonPasswordValidator
|
||||
- NAME: django.contrib.auth.password_validation.NumericPasswordValidator
|
||||
|
||||
In addition to the password validators provided by Django
|
||||
:django-docs:`validators provided by Django <topics/auth/passwords/#included-validators>`,
|
||||
Mayan EDMS adds the following validators:
|
||||
|
||||
.. autoclass:: mayan.apps.authentication.validators.MinimumCapitalLettersContentValidator
|
||||
|
||||
.. autoclass:: mayan.apps.authentication.validators.MinimumNumberContentValidator
|
||||
70
docs/chapters/quick_labels.rst
Normal file
70
docs/chapters/quick_labels.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
************
|
||||
Quick labels
|
||||
************
|
||||
|
||||
Quick labels are predetermined filenames that allow the quick renaming of
|
||||
documents as they are uploaded or after they have been uploaded.
|
||||
|
||||
Quick labels are added and associated to a document type.
|
||||
|
||||
Example of quick label: Invoice, Receipt from X store, Purchase order.
|
||||
|
||||
It is possible to preserve the file extension when using quick labels.
|
||||
Extensions are required for some operating system to be able to detect the
|
||||
correct file type to access the content.
|
||||
|
||||
For example if a document file is named "file0001.pdf" and the quick label
|
||||
"Receipt from X store" is applied, the resulting document label will be
|
||||
"Receipt from X store.pdf".
|
||||
|
||||
|
||||
Creating quick labels
|
||||
=====================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Edit document types" permission is required for this action, either
|
||||
globally or via an ACL for a document type.
|
||||
|
||||
|
||||
Since quick labels are associated with document types, creating quick labels
|
||||
must be done from the document type view.
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Document types` menu.
|
||||
#. In the document type list, click on the :guilabel:`Quick labels` button of
|
||||
the document type for which you wish to create a quick label.
|
||||
#. In the view titled "Quick labels for document type: <your document type>",
|
||||
from the :guilabel:`Actions` dropdown select :guilabel:`Add quick label to document type`.
|
||||
#. At the quick label creation form enter the desired label and press :guilabel:`Save`.
|
||||
|
||||
|
||||
Using quick labels during upload
|
||||
================================
|
||||
|
||||
#. Use the new document upload wizard from :menuselection:`Documents --> New document`.
|
||||
#. Select a document type and navigate to the penultimate step, where you have
|
||||
the option to drag and drop files to upload.
|
||||
#. Select a an option from the :guilabel:`Quick document rename` dropdown.
|
||||
#. Optionally select the :guilabel:`Preserve extension` checkbox to keep the file
|
||||
extension.
|
||||
#. Upload your documents.
|
||||
|
||||
|
||||
Using quick labels for existing documents
|
||||
=========================================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Edit document properties" permission is required for this action, either
|
||||
globally or via an ACL for a document or document type.
|
||||
|
||||
|
||||
#. Navigate to the document preview view of the document to rename. Make sure
|
||||
quick labels for the document type of the document select have been created.
|
||||
#. From the :guilabel:`Actions` dropdown select :guilabel:`Edit Properties`.
|
||||
#. Select a an option from the :guilabel:`Quick document rename` dropdown.
|
||||
#. Optionally select the :guilabel:`Preserve extension` checkbox to keep the file
|
||||
extension.
|
||||
#. Press :guilabel:`Save` to rename the document.
|
||||
@@ -6,15 +6,19 @@ The default installation method fits most use cases. If you use case requires
|
||||
more speed or capacity here are some suggestion that can help you improve the
|
||||
performance of your installation.
|
||||
|
||||
|
||||
Change the database manager
|
||||
===========================
|
||||
|
||||
Use PostgreSQL or MySQL as the database manager.
|
||||
Tweak the memory setting of the database manager to increase memory allocation.
|
||||
More PostgreSQL specific examples are available in their wiki page:
|
||||
https://wiki.postgresql.org/wiki/Performance_Optimization
|
||||
|
||||
|
||||
Increase the number of Gunicorn workers
|
||||
=======================================
|
||||
|
||||
The Gunicorn workers process HTTP requests and affect the speed at which the
|
||||
website responds.
|
||||
|
||||
@@ -33,6 +37,7 @@ And increase the value of the ``-w 2`` argument. This line is found in the
|
||||
|
||||
Background task processing
|
||||
==========================
|
||||
|
||||
The Celery workers are system processes that take care of the background
|
||||
tasks requested by the frontend interactions like document image rendering
|
||||
and periodic tasks like OCR. There are several dozen tasks defined in the code.
|
||||
@@ -45,37 +50,9 @@ low volume, medium duration tasks. It is not advisable to have the same
|
||||
worker processing OCR to process image rendering too. If the worker is
|
||||
processing several OCR tasks it will not be able to provide fast images
|
||||
when an user is browsing the user interface. This is why by default the
|
||||
queues are split into 3 workers: fast, medium, and slow.
|
||||
queues are split into 3 workers: fast, medium, and slow. Each worker will handle
|
||||
queues based on the latency required by each queue group.
|
||||
|
||||
The fast worker handles the queues:
|
||||
|
||||
* converter: Handles document page rendering
|
||||
* sources_fast: Does staging file image rendering
|
||||
|
||||
The medium worker handles the queues:
|
||||
|
||||
* checkouts_periodic: Scheduled tasks that check if a document's checkout
|
||||
period has expired
|
||||
* documents_periodic:
|
||||
* indexing: Does reindexing of documents in the background when their
|
||||
properties change
|
||||
* metadata:
|
||||
* sources:
|
||||
* sources_periodic: Checking email accounts and watch folders for new
|
||||
documents.
|
||||
* uploads: Processes files to turn the into Mayan documents. Processing
|
||||
encompasses MIME type detection, page count detection.
|
||||
* documents:
|
||||
|
||||
The slow worker handles the queues:
|
||||
|
||||
* mailing: Does the actual sending of documents via email as requested by
|
||||
users via the mailing profiles
|
||||
* tools: Executes in the background maintenance requests from the options
|
||||
in the tools menu
|
||||
* statistics: Recalculates statistics and charts
|
||||
* parsing: Parses documents to extract actual text content
|
||||
* ocr: Performs OCR to transcribe page images to text
|
||||
|
||||
Optimizations
|
||||
-------------
|
||||
@@ -88,15 +65,16 @@ Optimizations
|
||||
* By default each worker process uses 1 thread. You can increase the thread
|
||||
count of each worker process with the Docker environment options:
|
||||
|
||||
* MAYAN_WORKER_FAST_CONCURRENCY
|
||||
* MAYAN_WORKER_MEDIUM_CONCURRENCY
|
||||
* MAYAN_WORKER_SLOW_CONCURRENCY
|
||||
* ``MAYAN_WORKER_FAST_CONCURRENCY``
|
||||
* ``MAYAN_WORKER_MEDIUM_CONCURRENCY``
|
||||
* ``MAYAN_WORKER_SLOW_CONCURRENCY``
|
||||
|
||||
* If using direct deployment, increase the value of the --concurrency=1
|
||||
* If using direct deployment, increase the value of the ``--concurrency=1``
|
||||
argument of each worker in the supervisor file. You can also remove this
|
||||
argument and let the Celery algorithm choose the number of threads to
|
||||
launch. Usually this defaults to the number of CPU cores + 1.
|
||||
|
||||
|
||||
Change the message broker
|
||||
=========================
|
||||
Messages are the method of communication between front end interactive code
|
||||
@@ -116,22 +94,24 @@ For the Docker image, launch a separate RabbitMQ container
|
||||
|
||||
docker run -d --name mayan-edms-rabbitmq -e RABBITMQ_DEFAULT_USER=mayan -e RABBITMQ_DEFAULT_PASS=mayanrabbitmqpassword -e RABBITMQ_DEFAULT_VHOST=mayan rabbitmq:3
|
||||
|
||||
Pass the MAYAN_CELERY_BROKER_URL environment variable (https://kombu.readthedocs.io/en/latest/userguide/connections.html#connection-urls)
|
||||
Pass the MAYAN_BROKER_URL environment variable (https://kombu.readthedocs.io/en/latest/userguide/connections.html#connection-urls)
|
||||
to the Mayan EDMS container so that it uses the RabbitMQ container the
|
||||
message broker::
|
||||
|
||||
-e MAYAN_CELERY_BROKER_URL="amqp://mayan:mayanrabbitmqpassword@localhost:5672/mayan",
|
||||
-e MAYAN_BROKER_URL="amqp://mayan:mayanrabbitmqpassword@localhost:5672/mayan",
|
||||
|
||||
When tasks finish, they leave behind a return status or the result of a
|
||||
calculation, these are stored for a while so that whoever requested the
|
||||
background task, is able retrieve the result. These results are stored in the
|
||||
result storage. By default a Redis server is launched inside the Mayan EDMS
|
||||
container. You can launch a separate Docker Redis container and tell the Mayan
|
||||
EDMS container to use this via the MAYAN_CELERY_RESULT_BACKEND environment
|
||||
EDMS container to use this via the ``MAYAN_CELERY_RESULT_BACKEND`` environment
|
||||
variable. The format of this variable is explained here: http://docs.celeryproject.org/en/3.1/configuration.html#celery-result-backend
|
||||
|
||||
|
||||
Deployment type
|
||||
===============
|
||||
|
||||
Docker provides a faster deployment and the overhead is not high on modern
|
||||
systems. It is however memory and CPU limited by default and you need to
|
||||
increase this limits. The settings to change the container resource limits
|
||||
@@ -140,8 +120,10 @@ are here: https://docs.docker.com/config/containers/resource_constraints/#limit-
|
||||
For the best performance possible use the advanced deployment method on a
|
||||
host dedicated to serving only Mayan EDMS.
|
||||
|
||||
|
||||
Storage
|
||||
=======
|
||||
|
||||
For best input and output speed use a block based local filesystem on an
|
||||
SSD drive for the ``/media`` sub folder. The location of the ``/media`` folder
|
||||
will be specified by the ``MEDIA_ROOT`` setting.
|
||||
@@ -149,8 +131,10 @@ will be specified by the ``MEDIA_ROOT`` setting.
|
||||
If capacity is your bottom line, switch to an
|
||||
:doc:`object storage <../chapters/object_storage>` system.
|
||||
|
||||
|
||||
Use additional hosts
|
||||
====================
|
||||
|
||||
When one host is not enough you can use multiple hosts and share the load.
|
||||
Make sure that all hosts share the ``/media`` folder as specified by the
|
||||
``MEDIA_ROOT`` setting, also the database, the broker, and the result storage.
|
||||
|
||||
@@ -37,7 +37,6 @@ http://yaml.org/). Here is an example of what the looks like::
|
||||
|
||||
DOCUMENT_PARSING_AUTO_PARSING: true
|
||||
DOCUMENT_PARSING_PDFTOTEXT_PATH: /usr/bin/pdftotext
|
||||
DEFAUL_FROM_EMAIL: mayan.admin@example.com
|
||||
EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend
|
||||
EMAIL_HOST: localhost
|
||||
EMAIL_HOST_PASSWORD: ''
|
||||
|
||||
@@ -11,6 +11,7 @@ signatures sections of a document.
|
||||
.. blockdiag::
|
||||
|
||||
blockdiag {
|
||||
|
||||
orientation = portrait
|
||||
span_width = 240;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ The current document sources supported are:
|
||||
- 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 found in the watch folder is uploaded and subsequently deleted.
|
||||
Any file in the watch folder is automatically uploaded.
|
||||
- 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. Staging folders and Watch folders
|
||||
@@ -51,7 +51,29 @@ The current document sources supported are:
|
||||
web -> manual;
|
||||
}
|
||||
|
||||
Document source can be configure to allow document bundles to uploaded as
|
||||
Document sources 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.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
If you deployed a Mayan EDMS Docker container and want to use watched folders
|
||||
or staging folder, refer to the Docker chapter :ref:`docker-accessing-outside-data`.
|
||||
|
||||
|
||||
Creating new sources
|
||||
====================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Create new document sources" permission is required for this action.
|
||||
|
||||
|
||||
#. Go to the :menuselection:`System --> Setup --> Sources` menu.
|
||||
#. From the :guilabel:`Actions` dropdown select the new type of source to create.
|
||||
#. Each source type will have different fields to customize its behaviour. Enter
|
||||
the required information in each field based on the help text provided.
|
||||
#. Press :guilabel:`Save`.
|
||||
|
||||
@@ -5,10 +5,6 @@ Tags are color coded properties that can be attached or removed from documents.
|
||||
Tags allow giving documents a binary property. Documents can also be tagged
|
||||
with more than one tag.
|
||||
|
||||
Tags are created from the :menuselection:`Tags --> Create` menu.
|
||||
|
||||
To view all created tags use the :menuselection:`Tags --> All` menu.
|
||||
|
||||
Once tagged, documents can be searched by their tags. It is also possible to
|
||||
show all the documents tagged with a particular
|
||||
tag via the **Documents** link of each tag.
|
||||
@@ -21,3 +17,30 @@ more tags to the document and another to remove tags from the document.
|
||||
It is also possible to tag documents in bulk by selecting several documents
|
||||
from any view that displays a list documents and selecting the **Attach tag**
|
||||
or **Remove tags** from the dropdown menu.
|
||||
|
||||
|
||||
Creating tags
|
||||
=============
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Create new tags" permission is required for this action.
|
||||
|
||||
|
||||
#. Go to the :menuselection:`Tags --> Create` menu.
|
||||
#. Enter a label to identify the tag.
|
||||
#. Select a color for the tag.
|
||||
#. Press :guilabel:`Submit`.
|
||||
|
||||
|
||||
View all tags
|
||||
=============
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "View tags" permission is required for this action, globally or via an
|
||||
ACL for a tag.
|
||||
|
||||
#. Go to the :menuselection:`Tags --> All` menu.
|
||||
|
||||
@@ -46,3 +46,35 @@ There is no limit to the number of versions a document can have.
|
||||
|
||||
By default, the last version will be showed when working with the document
|
||||
but any of the versions can be inspected and viewed.
|
||||
|
||||
|
||||
View a document version list
|
||||
============================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "View documents' versions list" permission is required for this action,
|
||||
either globally or via an ACL for a document or document type.
|
||||
|
||||
|
||||
#. Navigate to the select document's preview view.
|
||||
#. Click on the sibebar's :guilabel:`Versions` button.
|
||||
|
||||
|
||||
Uploading a new document version
|
||||
================================
|
||||
|
||||
.. admonition:: Permissions required
|
||||
:class: warning
|
||||
|
||||
The "Create new document versions" permission is required for this action,
|
||||
either globally or via an ACL for a document or document type.
|
||||
|
||||
|
||||
#. Navigate to the select document's versions list view.
|
||||
#. From the :guilabel:`Actions` dropdown select :guilabel:`Upload new version`.
|
||||
#. Optionally type a comment explaining the changes in the new version.
|
||||
#. Press the :guilabel:`Browse` button and select a new file.
|
||||
#. Press :guilabel:`Save` upload the new verision.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Workflows
|
||||
Introduction
|
||||
============
|
||||
|
||||
Workflows provide a structure method for storing a sequence of states over
|
||||
Workflows provide a structured method for storing a sequence of states over
|
||||
which the a document will progress. Workflows keep track how a document has
|
||||
been processed so far.
|
||||
|
||||
@@ -20,6 +20,36 @@ provide and order for the sequence of possible states changes.
|
||||
Transitions can be executed manually by users if they have the required access
|
||||
level as configure by the system administrator.
|
||||
|
||||
.. blockdiag::
|
||||
:caption: Example workflow. Circles represent states, rectangles represent transitions.
|
||||
|
||||
span_width = 30;
|
||||
|
||||
submitted [shape = circle, width = 60, height = 60];
|
||||
approved [shape = circle, width = 60, height = 60];
|
||||
rejected [shape = circle, width = 60, height = 60];
|
||||
archived [shape = circle, width = 60, height = 60];
|
||||
|
||||
approve [label = approve];
|
||||
reject [label = reject];
|
||||
reopen [label = "re-open"];
|
||||
|
||||
|
||||
submitted -> approve -> approved;
|
||||
approved -> archived;
|
||||
submitted -> reject -> rejected;
|
||||
rejected -> archived;
|
||||
archived -> reopen -> submitted;
|
||||
|
||||
|
||||
|
||||
Workflows in Mayan EDMS are implemented as finite state machines
|
||||
(https://en.wikipedia.org/wiki/Finite-state_machine).
|
||||
|
||||
Workflows are mainly used to represent business processes. But they can also be
|
||||
used an automation system to customized Mayan EDMS and have it perform some
|
||||
tasks automatically.
|
||||
|
||||
|
||||
Automation
|
||||
==========
|
||||
@@ -66,26 +96,18 @@ Implementation
|
||||
==============
|
||||
|
||||
Internally, workflows are implemented as a finite state machines
|
||||
(https://en.wikipedia.org/wiki/Finite-state_machine). And have the limitation
|
||||
that only one state can be the current active state for a workflow being
|
||||
executed. The other limitation of the current implementation is that every
|
||||
workflow needs at least one state marked as the initial state. These limitations
|
||||
are the result of a compromised in the design between flexibility and ease of
|
||||
use.
|
||||
(https://en.wikipedia.org/wiki/Finite-state_machine). To make them simpler to
|
||||
use, workflow have been designed so that only one state can be the current
|
||||
active state for a workflow being executed. Another design decision is that
|
||||
every workflow needs at least one state marked as the initial state.
|
||||
|
||||
|
||||
Visualizations
|
||||
==============
|
||||
|
||||
The graphical representation of a workflow (or a finite state machine style
|
||||
in Mayan EDMS's case) is similar to a flowchart. The states are represented
|
||||
with circles. The transitions are represented with arrows. Circle with a
|
||||
double border represent the initial state of the workflow.
|
||||
The graphical representation of a workflow is similar to a flowchart. The
|
||||
states are represented with circles. The transitions are represented with
|
||||
arrows. Circle with a double border represent the initial state of the workflow.
|
||||
|
||||
To view the graphical representations of workflow use **Preview** button of
|
||||
the workflow in the setup view.
|
||||
|
||||
|
||||
|
||||
We are working now on workflow transition trigger filters to have
|
||||
the trigger move the state of the workflow on certain conditions. For example: Attach a tag if there is a specific word found in the OCR text.
|
||||
|
||||
92
docs/conf.py
92
docs/conf.py
@@ -13,8 +13,7 @@ from __future__ import unicode_literals
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import sys, os
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
@@ -23,25 +22,24 @@ import mayan
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.append(
|
||||
os.path.abspath(os.path.join(os.path.dirname(__file__), '_ext'))
|
||||
)
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "_ext")))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
# needs_sphinx = '1.0'
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||
#extensions = ["djangodocs", "sphinx.ext.intersphinx"]
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc', 'sphinx.ext.extlinks', 'sphinxcontrib.blockdiag',
|
||||
'sphinxcontrib.spelling', 'sphinx.ext.viewcode'
|
||||
'sphinx.ext.extlinks', 'sphinxcontrib.blockdiag', 'sphinxcontrib.spelling'
|
||||
]
|
||||
|
||||
blockdiag_antialias = True
|
||||
blockdiag_html_image_format = 'SVG'
|
||||
blockdiag_latex_image_format = 'PDF'
|
||||
blockdiag_html_image_format = "SVG"
|
||||
blockdiag_latex_image_format = "PDF"
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -71,20 +69,20 @@ release = version
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
# language = None
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
# today_fmt = '%B %d, %Y'
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# default_role = None
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
add_function_parentheses = True
|
||||
@@ -101,7 +99,7 @@ show_authors = False
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
@@ -113,26 +111,26 @@ html_theme = 'classic'
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
# html_theme_options = {}
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
# html_title = None
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
# html_short_title = None
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
# html_logo = None
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
# html_favicon = None
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
@@ -141,44 +139,44 @@ html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
# html_use_smartypants = True
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
# html_sidebars = {}
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
# html_additional_pages = {}
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
# html_domain_indices = True
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
# html_use_index = True
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
# html_split_index = False
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
# html_show_sourcelink = True
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
# html_show_sphinx = True
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
# html_show_copyright = True
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
# html_use_opensearch = ''
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'MayanEDMSdoc'
|
||||
@@ -190,42 +188,41 @@ html_show_sphinx = False
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
# latex_paper_size = 'letter'
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
# latex_font_size = '10pt'
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
(
|
||||
'index', 'MayanEDMS.tex', 'Mayan EDMS Documentation',
|
||||
mayan.__author__, 'manual'
|
||||
),
|
||||
('index', 'MayanEDMS.tex', 'Mayan EDMS Documentation',
|
||||
mayan.__author__, 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
# latex_logo = None
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
# latex_use_parts = False
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
# latex_show_pagerefs = False
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# latex_show_urls = False
|
||||
#latex_show_urls = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
# latex_preamble = ''
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# latex_appendices = []
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# latex_domain_indices = True
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
@@ -252,3 +249,6 @@ extlinks = {
|
||||
'https://gitlab.com/mayan-edms/mayan-edms/issues/%s', 'GitLab issue #'
|
||||
)
|
||||
}
|
||||
|
||||
def setup(app):
|
||||
app.add_stylesheet('css/custom.css')
|
||||
|
||||
@@ -21,14 +21,17 @@ repository for electronic documents.
|
||||
topics/installation
|
||||
releases/index
|
||||
topics/getting_started
|
||||
topics/adding_documents
|
||||
topics/access_control
|
||||
topics/categorization
|
||||
topics/collaboration
|
||||
topics/settings
|
||||
topics/storage
|
||||
topics/integration
|
||||
topics/docker
|
||||
topics/advanced
|
||||
topics/administration
|
||||
topics/troubleshooting
|
||||
topics/development
|
||||
topics/faq
|
||||
topics/license
|
||||
|
||||
@@ -31,9 +31,9 @@ for Mayan EDMS. Most MERCs will be Feature MERCs.
|
||||
2. An **Informational** MERC describes a Mayan EDMS design issue, or
|
||||
provides general guidelines or information to the Mayan EDMS community,
|
||||
but does not propose a new feature. Informational MERCs do not
|
||||
necessarily represent a community consensus or
|
||||
recommendation, so users and implementers are free to ignore
|
||||
Informational MERCs or follow their advice.
|
||||
necessarily represent a community consensus or recommendation, so users
|
||||
and implementers are free to ignore Informational MERCs or follow their
|
||||
advice.
|
||||
|
||||
3. A **Process** MERC describes a process surrounding Mayan EDMS, or
|
||||
proposes a change to (or an event in) a process. Process MERCs are
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
=====================
|
||||
====================
|
||||
MERC 2: Test writing
|
||||
=====================
|
||||
====================
|
||||
|
||||
:MERC: 2
|
||||
:Author: Michael Price
|
||||
|
||||
149
docs/mercs/0005-explicit-arguments.rst
Normal file
149
docs/mercs/0005-explicit-arguments.rst
Normal file
@@ -0,0 +1,149 @@
|
||||
==========================
|
||||
MERC 5: Explicit arguments
|
||||
==========================
|
||||
|
||||
:MERC: 5
|
||||
:Author: Roberto Rosario
|
||||
:Status: Accepted
|
||||
:Type: Feature
|
||||
:Created: 2018-12-30
|
||||
:Last-Modified: 2018-12-31
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:depth: 3
|
||||
:local:
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This MERC proposes the adoption of a new methodology when performing calls.
|
||||
It seeks to reduce the use of positional arguments in favor of keyword
|
||||
arguments in as many places as possible.
|
||||
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
As the project grows, legibility of code becomes more important. Keyword
|
||||
argument help document the use of services, clases and functions. Refactors
|
||||
that affect the interface of services are also easier to find and update and
|
||||
fix. Positional argument can cause a call to continue working as long as the
|
||||
datatype of the argument remains the same. Usage of keyword arguments will
|
||||
automatically raise and error that will prevent such situations. Keyword
|
||||
argument further eliminate the relevance of position or the arguments, and
|
||||
the arguments can be sorted alphabetically for easier visual scanning or by
|
||||
semantic significance improving code readability.
|
||||
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
||||
Adoption of this MERC will require an audit of existing calls and the use
|
||||
of the method proposed for new calls. Every call regardless of the type or
|
||||
origin of the source callable will name each argument used. By type it is
|
||||
meant: classes, functions, methods. Origin means: local from the project,
|
||||
from the framework, third party libraries or the standard library.
|
||||
|
||||
|
||||
Backwards Compatibility
|
||||
=======================
|
||||
|
||||
No backwards compatibility issues are expected. New errors arising from the use
|
||||
if keyword arguments could be interpreted as existing latent issues that
|
||||
have not been uncovered.
|
||||
|
||||
|
||||
Reference Implementation
|
||||
========================
|
||||
|
||||
Example:
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from mayan.apps.common.classes import Template
|
||||
|
||||
Template(
|
||||
'menu_main', 'appearance/menu_main.html'
|
||||
)
|
||||
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from mayan.apps.common.classes import Template
|
||||
|
||||
Template(
|
||||
name='menu_main', template_name='appearance/menu_main.html'
|
||||
)
|
||||
|
||||
|
||||
When calls use a mixture or positional and keyword arguments, the keywords
|
||||
arguments can only be found after the positional arguments. Complete use
|
||||
of keyword arguments allow the reposition of arguments for semantic
|
||||
purposes.
|
||||
|
||||
Example:
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .views import AboutView, HomeView, RootView
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', RootView.as_view(), name='root'),
|
||||
url(r'^home/$', HomeView.as_view(), name='home'),
|
||||
url(r'^about/$', AboutView.as_view(), name='about_view'),
|
||||
]
|
||||
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .views import AboutView, HomeView, RootView
|
||||
|
||||
urlpatterns = [
|
||||
url(regex=r'^$', name='root', view=RootView.as_view()),
|
||||
url(regex=r'^home/$', name='home', view=HomeView.as_view()),
|
||||
url(regex=r'^about/$', name='about_view', view=AboutView.as_view()),
|
||||
]
|
||||
|
||||
|
||||
Keyword arguments should also be used for callables that pass those to others
|
||||
down the line like Django's ``reverse`` function. Any change to the name of
|
||||
the ``pk`` URL parameter will raise an exception in this code alerting to
|
||||
any posible incompatible use.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
viewname='documents:document_preview', kwargs={'pk': self.pk}
|
||||
)
|
||||
|
||||
|
||||
This becomes even more important when multiple URL parameters are used. Since
|
||||
the API documentation is auto generated from the code itself, it would make
|
||||
sense to rename the first URL parameter from ``pk`` to ``document_pk``. Such
|
||||
change will cause all address to view resolutions to break forcing their
|
||||
update and allowing all consumers' interface usage to remain synchonized to the
|
||||
callable's interface.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
url(
|
||||
regex=r'^documents/(?P<pk>[0-9]+)/versions/(?P<document_version_pk>[0-9]+)/pages/(?P<document_page_pk>[0-9]+)/image/$',
|
||||
name='documentpage-image', view=APIDocumentPageImageView.as_view()
|
||||
),
|
||||
81
docs/mercs/0006-lower-information-disclose.rst
Normal file
81
docs/mercs/0006-lower-information-disclose.rst
Normal file
@@ -0,0 +1,81 @@
|
||||
==================================
|
||||
MERC 6: Lower information disclose
|
||||
==================================
|
||||
|
||||
:MERC: 6
|
||||
:Author: Michael Price
|
||||
:Status: Accepted
|
||||
:Type: Feature
|
||||
:Created: 2018-12-30
|
||||
:Last-Modified: 2018-12-31
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:depth: 3
|
||||
:local:
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This MERC proposes the use of errors that don't disclose the existance of a
|
||||
resource in the event that the requester doesn't have the required credentials.
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
When an user tries to perform an action like opening a view to a document for
|
||||
which the required permission is missing, a permission required or access
|
||||
denied error is presented. This is semantically correct, but from the stand
|
||||
point of security it is still failing because it is letting the user know
|
||||
that such document exists in the first place. This MERC proposes changing the
|
||||
error message for existing resource to one that doesn't divulge any information
|
||||
to unauthorized parties, like "Not Found".
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
||||
Out of the 4 basic CRUD operations, Read, Update and Delete should return an
|
||||
HTTP 404 error instead of an HTTP 403 error. Only the Create operation will
|
||||
continue returning the current HTTP 403 error, unless it is creating a
|
||||
new resource that is related to an existing resource.
|
||||
|
||||
Since most view use the internal custom CRUD classes making a change to the
|
||||
``ObjectPermissionCheckMixin`` class to raise an HTTP 404 on object access
|
||||
failure will fulfill the proposal of this MERC.
|
||||
|
||||
Adding the ``object_permission_raise_404`` class attribute and setting it
|
||||
to default to False will allow fulfullin the goal of this MERC while
|
||||
keeping the existing functionality intact.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class ObjectPermissionCheckMixin(object):
|
||||
"""
|
||||
If object_permission_raise_404 is True an HTTP 404 error will be raised
|
||||
instead of the normal 403.
|
||||
"""
|
||||
object_permission = None
|
||||
object_permission_raise_404 = False
|
||||
|
||||
def get_permission_object(self):
|
||||
return self.get_object()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if self.object_permission:
|
||||
try:
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=self.object_permission, user=request.user,
|
||||
obj=self.get_permission_object(),
|
||||
related=getattr(self, 'object_permission_related', None)
|
||||
)
|
||||
except PermissionDenied:
|
||||
if self.object_permission_raise_404:
|
||||
raise Http404
|
||||
else:
|
||||
raise
|
||||
|
||||
return super(
|
||||
ObjectPermissionCheckMixin, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
@@ -20,6 +20,8 @@ Accepted
|
||||
../mercs/0001-merc-process
|
||||
../mercs/0002-test-writing
|
||||
../mercs/0003-using-javascript-libraries
|
||||
../mercs/0005-explicit-arguments
|
||||
../mercs/0006-lower-information-disclose
|
||||
|
||||
Draft
|
||||
-----
|
||||
@@ -49,3 +51,5 @@ Feature
|
||||
|
||||
../mercs/0002-test-writing
|
||||
../mercs/0003-using-javascript-libraries
|
||||
../mercs/0005-explicit-arguments
|
||||
../mercs/0006-lower-information-disclose
|
||||
|
||||
@@ -63,5 +63,5 @@ Changes needed:
|
||||
the Role model's permissions many to many field.
|
||||
4. Update the ``AccessControlList`` models roles field to point to the group
|
||||
models.
|
||||
5. Update the role checks in the ``check_access`` and ``filter_by_access``
|
||||
5. Update the role checks in the ``check_access`` and ``restrict_queryset``
|
||||
``AccessControlList`` model manager methods.
|
||||
|
||||
188
docs/releases/3.1.10.rst
Normal file
188
docs/releases/3.1.10.rst
Normal file
@@ -0,0 +1,188 @@
|
||||
Version 3.1.10
|
||||
==============
|
||||
|
||||
Released: April 04, 2019
|
||||
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
Test improvements
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
A number of test improvements were backported from the development branch. These
|
||||
include a mixin to assign random primary keys to the test objects. Normally
|
||||
primary keys are sequential and their predictability can hide edge cases that
|
||||
would normally only manifest in production. The tests case code was also split
|
||||
into smaller mixin units separating them by purpose. All code to perform HTTP
|
||||
requests now resides in the ``ClientMethodsTestCaseMixin``. Changes in the
|
||||
``ContentTypeCheckTestCaseMixin`` were added to enable this mixin for the API views
|
||||
in a future minor version. The test view code was moved into its own mixin
|
||||
called ``TestViewTestCaseMixin``. This mixin allows creating dynamic views to test
|
||||
object and link resolution among other things. The API base test case class is
|
||||
now part of the same class hierarchy, this means that the API test code will
|
||||
now behave the same and will benefit from all improvements in the base test case
|
||||
classes. Some indexing tests were failing randomly. This was caused by the way
|
||||
the test were built and not because of faulty code. The tests were updated and
|
||||
now operate as expected. While there is no official support for installing
|
||||
Mayan EDMS as a sub URL updates to the ``TestViewTestCaseMixin`` will allow it to
|
||||
execute with custom ``ROOT_URLCONF`` configurations. Further work and feedback is
|
||||
needed to officially support this installation method.
|
||||
|
||||
|
||||
Fixes
|
||||
^^^^^
|
||||
|
||||
The advanced search API endpoint was fixed and is now usable. Tests for all
|
||||
the issues fixed were added to avoid future regressions. A fix was applied
|
||||
to the compressed class that caused compressed files uploads to fail from the
|
||||
web form.
|
||||
|
||||
Docker
|
||||
^^^^^^
|
||||
|
||||
Updates were added to the Docker image that allow it to build on armv7l
|
||||
platforms like the RasperryPi, Odroid XU4, and Odroid HC2. This doesn't imply
|
||||
official support for these platforms. Further experimentation and optimization
|
||||
is needed and this changed will now allow users to build the image and provide
|
||||
feedback in an easier manner.
|
||||
|
||||
|
||||
Installation
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The installation process has been updated to work around the Python pip
|
||||
issue #6197 (https://github.com/pypa/pip/issues/6197).
|
||||
|
||||
|
||||
User interface
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Improvements in the AJAX menu rendering were conflicting with an old method
|
||||
of refreshing the unread notification counter badge. This conflict would cause
|
||||
the unread notification counter badge to blink and/or disappear. The older
|
||||
badge refresh method was removed and improvements to the menu rendering from
|
||||
the development branch were backported to support displaying link badges from
|
||||
the templates completing fixing the issue. An API entrypoint was also backported
|
||||
showing a list of all the server side AJAX templates. This change doesn't affect
|
||||
the API layout and it remains compatible with the previous version. Newlines
|
||||
are now explicitly removed from the rendered AJAX templates avoiding rendering
|
||||
issues on some browsers.
|
||||
|
||||
|
||||
Emails
|
||||
^^^^^^
|
||||
|
||||
An update was added to will now cause Mayan EDMS to reject all email attachments
|
||||
with a size 0 even if the attachment is valid. Documents of size 0 are not
|
||||
consideref valid in Mayan EDMS since they can't be introspected for MIME type,
|
||||
don't contain at least one version, and don't contain a single page. All these
|
||||
are requirements for a valid document in Mayan EDMS.
|
||||
|
||||
|
||||
Memory usage
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The ``MIMETYPE_FILE_READ_SIZE`` setting was added to limit the number of bytes that
|
||||
will be read into memory to determine the MIME type of a new document. For
|
||||
compatibility with the current bevahor this setting defaults to 0 which means
|
||||
that it is disabled. Disabling the setting will cause the entire document's
|
||||
file to be loaded into memory. If documents are not processing due to out of
|
||||
memory errors (large documents or devices with limited memory), set
|
||||
``MIMETYPE_FILE_READ_SIZE`` to a value other than 0. Limited tests suggest 1024
|
||||
to be a good alternative as most "magic numbers" used for MIME type detection
|
||||
are located at the start of the file and just reading the first 1024 bytes will
|
||||
result in a positive identification with little memory usage.
|
||||
|
||||
|
||||
Other changes
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
* Add missing document index API view create permission.
|
||||
* Fix index list API view. Add index create, delete, detail API tests.
|
||||
* Add support for skipping a default set of tests. Tests to be excluded
|
||||
by default should be tagged as 'exclude'.
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
* None
|
||||
|
||||
|
||||
Upgrading from a previous version
|
||||
---------------------------------
|
||||
|
||||
If installed via Python's PIP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ curl https://gitlab.com/mayan-edms/mayan-edms/raw/master/removals.txt | pip uninstall -r /dev/stdin
|
||||
|
||||
Type in the console::
|
||||
|
||||
$ pip install mayan-edms==3.1.10
|
||||
|
||||
the requirements will also be updated automatically.
|
||||
|
||||
|
||||
Using Git
|
||||
^^^^^^^^^
|
||||
|
||||
If you installed Mayan EDMS by cloning the Git repository issue the commands::
|
||||
|
||||
$ git reset --hard HEAD
|
||||
$ git pull
|
||||
|
||||
otherwise download the compressed archived and uncompress it overriding the
|
||||
existing installation.
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ pip uninstall -y -r removals.txt
|
||||
|
||||
Next upgrade/add the new requirements::
|
||||
|
||||
$ pip install --upgrade -r requirements.txt
|
||||
|
||||
|
||||
Common steps
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Perform these steps after updating the code from either step above.
|
||||
|
||||
Migrate existing database schema with::
|
||||
|
||||
$ mayan-edms.py performupgrade
|
||||
|
||||
Add new static media::
|
||||
|
||||
$ mayan-edms.py collectstatic --noinput
|
||||
|
||||
The upgrade procedure is now complete.
|
||||
|
||||
|
||||
Backward incompatible changes
|
||||
-----------------------------
|
||||
|
||||
* None
|
||||
|
||||
|
||||
Bugs fixed or issues closed
|
||||
---------------------------
|
||||
|
||||
* :gitlab-issue:`557` Break workflows with invalid input
|
||||
* :gitlab-issue:`559` IndexTestCase.test_dual_level_dual_document_index failure
|
||||
* :gitlab-issue:`562` events.links.link_user_notifications_list should use
|
||||
reverse
|
||||
* :gitlab-issue:`564` API REST /api/indexes/ generates an "Internal Server Error"
|
||||
* :gitlab-issue:`566` apps.common.tests.base.GenericViewTestCase doesn't work
|
||||
with a custom ROOT_URLCONF
|
||||
* :gitlab-issue:`568` Tornado 6.0 doesn't support Python 2.7
|
||||
* :gitlab-issue:`572` Error when sending compressed files: ziparchive object
|
||||
has no attribute children
|
||||
* :gitlab-issue:`574` import of E-Mails with empty attachment fails
|
||||
* :gitlab-issue:`576` Exception with access check for cabinets containing
|
||||
NON-ASCII chars
|
||||
|
||||
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
148
docs/releases/3.1.11.rst
Normal file
148
docs/releases/3.1.11.rst
Normal file
@@ -0,0 +1,148 @@
|
||||
Version 3.1.11
|
||||
==============
|
||||
|
||||
Released: April XX, 2019
|
||||
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
Memory usage
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The ``DOCUMENTS_HASH_BLOCK_SIZE`` setting was added to limit the number of
|
||||
bytes that will be read into memory when calculating the checksum of a new
|
||||
document. For compatibility with the current bevahor this setting defaults to
|
||||
0 which means that it is disabled. Disabling the setting will cause the
|
||||
entire document's file to be loaded into memory. If documents are not
|
||||
processing due to out of memory errors (large documents or devices with
|
||||
limited memory), set ``DOCUMENTS_HASH_BLOCK_SIZE`` to a value other than 0.
|
||||
Limited tests suggest 65535 to be a good alternative.
|
||||
|
||||
|
||||
Tag wizard step
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The tag wizard step was fixed and will now allow attaching multple tags to a
|
||||
new document.
|
||||
|
||||
|
||||
Permissions
|
||||
^^^^^^^^^^^
|
||||
|
||||
Previously the document checkout information link required one of the following
|
||||
permissions: document check in, document check in override, or document
|
||||
checkout. Meanwhile the document checkout information view would require the
|
||||
document checkout detail view permission. This difference in permissions
|
||||
has been eliminated and the link will now required the document checkout
|
||||
detail view permission, same as the view. Update your user role permissions
|
||||
accordingly.
|
||||
|
||||
|
||||
Other changes
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
* Lower the log severity when links don't resolve.
|
||||
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
* None
|
||||
|
||||
|
||||
Upgrading from a previous version
|
||||
---------------------------------
|
||||
|
||||
If installed via Python's PIP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ curl https://gitlab.com/mayan-edms/mayan-edms/raw/master/removals.txt | pip uninstall -r /dev/stdin
|
||||
|
||||
Type in the console::
|
||||
|
||||
$ pip install mayan-edms==3.1.11
|
||||
|
||||
the requirements will also be updated automatically.
|
||||
|
||||
Migrate existing database schema with::
|
||||
|
||||
$ mayan-edms.py performupgrade
|
||||
|
||||
Add new static media::
|
||||
|
||||
$ mayan-edms.py collectstatic --noinput
|
||||
|
||||
The upgrade procedure is now complete.
|
||||
|
||||
|
||||
If installed using a direct deployment
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ curl https://gitlab.com/mayan-edms/mayan-edms/raw/master/removals.txt | sudo -u mayan /opt/mayan-edms/bin/pip uninstall -r /dev/stdin
|
||||
|
||||
Download and install the new version::
|
||||
|
||||
$ sudo -u mayan /opt/mayan-edms/bin/pip install --no-cache-dir --no-use-pep517 mayan-edms==3.1.11
|
||||
|
||||
the requirements will also be updated automatically.
|
||||
|
||||
Run the upgrade command::
|
||||
|
||||
$ sudo -u mayan MAYAN_DATABASE_ENGINE=django.db.backends.postgresql \
|
||||
MAYAN_DATABASE_NAME=mayan MAYAN_DATABASE_PASSWORD=mayanuserpass \
|
||||
MAYAN_DATABASE_USER=mayan MAYAN_DATABASE_HOST=127.0.0.1 \
|
||||
MAYAN_MEDIA_ROOT=/opt/mayan-edms/media /opt/mayan-edms/bin/mayan-edms.py performupgrade
|
||||
|
||||
Add any new static files::
|
||||
|
||||
$ sudo -u mayan MAYAN_MEDIA_ROOT=/opt/mayan-edms/media /opt/mayan-edms/bin/mayan-edms.py collectstatic --noinput
|
||||
|
||||
The upgrade procedure is now complete.
|
||||
|
||||
Using Git
|
||||
^^^^^^^^^
|
||||
|
||||
If you installed Mayan EDMS by cloning the Git repository issue the commands::
|
||||
|
||||
$ git reset --hard HEAD
|
||||
$ git pull
|
||||
|
||||
otherwise download the compressed archived and uncompress it overriding the
|
||||
existing installation.
|
||||
|
||||
Remove deprecated requirements::
|
||||
|
||||
$ pip uninstall -y -r removals.txt
|
||||
|
||||
Next upgrade/add the new requirements::
|
||||
|
||||
$ pip install --upgrade -r requirements.txt
|
||||
|
||||
Migrate existing database schema with::
|
||||
|
||||
$ mayan-edms.py performupgrade
|
||||
|
||||
Add new static media::
|
||||
|
||||
$ mayan-edms.py collectstatic --noinput
|
||||
|
||||
The upgrade procedure is now complete.
|
||||
|
||||
|
||||
Backward incompatible changes
|
||||
-----------------------------
|
||||
|
||||
* None
|
||||
|
||||
|
||||
Bugs fixed or issues closed
|
||||
---------------------------
|
||||
|
||||
* None
|
||||
|
||||
.. _PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
@@ -9,10 +9,10 @@ Changes
|
||||
|
||||
* Improve index mirroring value clean up code to remove the spaces at the
|
||||
starts and at the end of directories. Closes again GitLab issue #520
|
||||
Thanks to @TheOneValen for the report.
|
||||
Thanks to TheOneValen @ for the report.
|
||||
* Improve index mirroring cache class to use the hash of the keys
|
||||
instead of the literal keys. Avoid warning about invalid key
|
||||
characters. Closes GitLab issue #518. Thanks to @TheOneValen for the
|
||||
characters. Closes GitLab issue #518. Thanks to TheOneValen @ for the
|
||||
report.
|
||||
* Only render the Template API view for authenticated users.
|
||||
Thanks rgarcia for the report.
|
||||
|
||||
@@ -12,10 +12,10 @@ Changes
|
||||
* Remove duplicate YAML loading of environment variables.
|
||||
* Don't load development apps if they are already loaded.
|
||||
* Make sure all key used as input for the cache key hash are
|
||||
bytes and not unicode. GitLab issue #520. Thanks to @TheOneValen for
|
||||
the report.
|
||||
bytes and not unicode. GitLab issue #520. Thanks to TheOneValen
|
||||
@TheOneValen for the report.
|
||||
* Ignore document stub from the index mirror. GitLab issue
|
||||
#520. Thanks to @TheOneValen for the report.
|
||||
#520. Thanks to TheOneValen @TheOneValen for the report.
|
||||
* Fix for the Docker image INSTALL_FLAG path. Thanks to
|
||||
Mark Maglana @relaxdiego for the report and to Hamish Farroq @farroq_HAM
|
||||
for the patch. GitLab issue #525.
|
||||
|
||||
@@ -8,8 +8,7 @@ Changes
|
||||
-------
|
||||
|
||||
* Convert the furl instance to text to allow serializing it into
|
||||
JSON and be passed as arguments to the background task. Fixes
|
||||
metadata assignment issues when uploading new documents.
|
||||
JSON to be passed as arguments to the background task.
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,8 @@ versions of the documentation contain the release notes for any later releases.
|
||||
:maxdepth: 1
|
||||
|
||||
3.2
|
||||
3.1.11
|
||||
3.1.10
|
||||
3.1.9
|
||||
3.1.8
|
||||
3.1.7
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Archlinux
|
||||
archlinux
|
||||
adf
|
||||
ajax
|
||||
ajaxForm
|
||||
@@ -173,3 +175,15 @@ YaN
|
||||
yasg
|
||||
YbN
|
||||
YrcN
|
||||
metacopy
|
||||
overlayfs
|
||||
sys
|
||||
supervisord
|
||||
Monkeypatch
|
||||
Bootswatch
|
||||
sortable
|
||||
Odroid
|
||||
callables
|
||||
ModelPermission
|
||||
mixins
|
||||
kwargs
|
||||
|
||||
5
docs/topics/adding_documents.rst
Normal file
5
docs/topics/adding_documents.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
################
|
||||
Adding documents
|
||||
################
|
||||
|
||||
.. include:: ../chapters/sources.rst
|
||||
@@ -9,4 +9,3 @@ Administration
|
||||
.. include:: ../chapters/backups.rst
|
||||
.. include:: ../chapters/scaling_up.rst
|
||||
.. include:: ../chapters/database_conversion.rst
|
||||
.. include:: ../chapters/docker.rst
|
||||
|
||||
@@ -8,4 +8,4 @@ Advanced topics
|
||||
.. include:: ../chapters/metadata.rst
|
||||
.. include:: ../chapters/transformations.rst
|
||||
.. include:: ../chapters/versioning.rst
|
||||
.. include:: ../chapters/password_validation.rst
|
||||
.. include:: ../chapters/quick_labels.rst
|
||||
|
||||
@@ -7,10 +7,12 @@ allows showing users different views of document groups. These are divided
|
||||
into ones requiring manual maintenance and others that are updated
|
||||
automatically.
|
||||
|
||||
|
||||
**************
|
||||
Manual methods
|
||||
**************
|
||||
|
||||
.. include:: ../chapters/document_types.rst
|
||||
.. include:: ../chapters/cabinets.rst
|
||||
.. include:: ../chapters/tags.rst
|
||||
|
||||
|
||||
8
docs/topics/docker.rst
Normal file
8
docs/topics/docker.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
######
|
||||
Docker
|
||||
######
|
||||
|
||||
Docker is a container technology. Containers are a standard unit of software
|
||||
that packages up code and all its dependencies.
|
||||
|
||||
.. include:: ../chapters/docker.rst
|
||||
@@ -83,43 +83,6 @@ moment this could cause problems is when running South migrations during
|
||||
upgrades, if a migration fails the database structure is left in a transitory
|
||||
state and has to be reverted manually before trying again.
|
||||
|
||||
_mysql_exceptions. OperationalError: (1267, "Illegal mix of collations (latin1_swedish_ci, IMPLICIT) and (utf8_general_ci, COERCIBLE) for operation ‘='”)
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
$ mayan-edms.py shell
|
||||
>>> from django.db import connection
|
||||
>>> cursor = connection.cursor()
|
||||
>>> cursor.execute('SHOW TABLES')
|
||||
>>> results=[]
|
||||
>>> for row in cursor.fetchall(): results.append(row)
|
||||
>>> for row in results: cursor.execute('ALTER TABLE %s CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;' % (row[0]))
|
||||
|
||||
References:
|
||||
|
||||
* http://stackoverflow.com/questions/1073295/django-character-set-with-mysql-weirdness
|
||||
|
||||
|
||||
Incorrect string value: ``'xE2x80x95rs6…'`` for column ``'content'`` at row 1
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
When using MySQL and doing OCR on languages other than English
|
||||
|
||||
Use utf-8 collation on MySQL server, or at least in table
|
||||
‘documents_documentpage', ‘content' field
|
||||
|
||||
References:
|
||||
|
||||
* http://groups.google.com/group/django-users/browse_thread/thread/429447086fca6412
|
||||
* http://markmail.org/message/bqajx2utvmtriixi
|
||||
|
||||
Error "django.db.utils.IntegrityError IntegrityError: (1452, ‘Cannot add or update a child row: a foreign key constraint fails (`…`.`…`, CONSTRAINT `…_refs_id_b0252274` FOREIGN KEY (`…`) REFERENCES `…` (`…`))')
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Solution:
|
||||
Convert all MySQL tables to the same type, either all MyISAM or InnoDB
|
||||
|
||||
|
||||
Document versions
|
||||
=================
|
||||
@@ -185,7 +148,7 @@ Django's development server doesn't serve static files unless the DEBUG option
|
||||
is set to True, this mode of operation should only be used for development or
|
||||
testing. For production deployments the management command::
|
||||
|
||||
$ mayan-edms.py collectstatic
|
||||
$ mayan-edms.py preparestatic
|
||||
|
||||
should be used and the resulting static folder served from a webserver.
|
||||
For more information check the
|
||||
|
||||
@@ -92,7 +92,7 @@ Features
|
||||
* It is very easy to use 3rd party plugins such as the ones available for
|
||||
Amazon EC2.
|
||||
|
||||
* Color coded <../chapters/tags>`.
|
||||
* :doc:`Color coded tags <../chapters/tags>`.
|
||||
|
||||
* Labeled and color coded tags can be assigned for intuitive recognition.
|
||||
|
||||
|
||||
@@ -4,6 +4,19 @@ Getting started
|
||||
|
||||
These are the basic concepts you need to understand to start using Mayan EDMS.
|
||||
|
||||
The absolute minimum setup to start using Mayan EDMS is:
|
||||
|
||||
#. A document type
|
||||
#. A document source to add new documents
|
||||
|
||||
that's it!
|
||||
|
||||
To make things even easier, a default document type (named "Default") and a
|
||||
default document source (also named "Default") were created for you during the
|
||||
installation. So you don't need to do anything more to start adding documents
|
||||
right now, however take your time reading the information below to get a deeper
|
||||
understanding about how these concepts work.
|
||||
|
||||
.. include:: ../chapters/document_types.rst
|
||||
.. include:: ../chapters/sources.rst
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
Installation
|
||||
############
|
||||
|
||||
Mayan EDMS can be install in several way. The two recommended ways are: by
|
||||
using Docker_, and by doing a direct installation.
|
||||
|
||||
The Docker method provides the easiest installation process while the direct
|
||||
installation provides better performance and customization.
|
||||
The easiest way to use Mayan EDMS is by using the official Docker_ image.
|
||||
Make sure Docker is properly installed and working before attempting to install
|
||||
Mayan EDMS.
|
||||
|
||||
*****************************
|
||||
Minimum hardware requirements
|
||||
@@ -17,9 +15,34 @@ Minimum hardware requirements
|
||||
- Unix-like operating system like Linux and OpenBSD. For other operating systems
|
||||
user container technologies like Docker or virtual machines.
|
||||
|
||||
****************
|
||||
Docker procedure
|
||||
****************
|
||||
|
||||
.. include:: ../chapters/docker_installation.rst
|
||||
.. include:: ../chapters/deploying.rst
|
||||
Docker is a computer program that performs operating-system-level
|
||||
virtualization also known as containerization. It allows independent
|
||||
"containers" to run within a single Linux instance, avoiding the overhead
|
||||
of starting and maintaining virtual machines (VMs).
|
||||
|
||||
Docker can be installed using their automated script::
|
||||
|
||||
wget -qO- https://get.docker.com/ | sh
|
||||
|
||||
This installs the latest versions of Docker. If you don't want run an automated
|
||||
script follow the instructions outlined in their documentation: https://docs.docker.com/install/
|
||||
|
||||
Once the Docker installation is finished, proceed to the link below to install
|
||||
the Docker image for Mayan EDMS.
|
||||
|
||||
Docker image chapter: :ref:`docker_install`
|
||||
|
||||
*******************
|
||||
Direct installation
|
||||
*******************
|
||||
|
||||
For users with knowledge of Python, Django, Ubuntu, and databases.
|
||||
|
||||
Deployments chapter: :doc:`../chapters/deploying`
|
||||
|
||||
|
||||
.. _Docker: https://www.docker.com/
|
||||
|
||||
138
docs/topics/troubleshooting.rst
Normal file
138
docs/topics/troubleshooting.rst
Normal file
@@ -0,0 +1,138 @@
|
||||
###############
|
||||
Troubleshooting
|
||||
###############
|
||||
|
||||
|
||||
********
|
||||
Database
|
||||
********
|
||||
|
||||
_mysql_exceptions. OperationalError: (1267, "Illegal mix of collations (latin1_swedish_ci, IMPLICIT) and (utf8_general_ci, COERCIBLE) for operation ‘='”)
|
||||
=========================================================================================================================================================
|
||||
|
||||
::
|
||||
|
||||
$ mayan-edms.py shell
|
||||
>>> from django.db import connection
|
||||
>>> cursor = connection.cursor()
|
||||
>>> cursor.execute('SHOW TABLES')
|
||||
>>> results=[]
|
||||
>>> for row in cursor.fetchall(): results.append(row)
|
||||
>>> for row in results: cursor.execute('ALTER TABLE %s CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;' % (row[0]))
|
||||
|
||||
References:
|
||||
|
||||
* http://stackoverflow.com/questions/1073295/django-character-set-with-mysql-weirdness
|
||||
|
||||
|
||||
Incorrect string value: ``'xE2x80x95rs6…'`` for column ``'content'`` at row 1
|
||||
=============================================================================
|
||||
|
||||
When using MySQL and doing OCR on languages other than English
|
||||
|
||||
Use utf-8 collation on MySQL server, or at least in table
|
||||
‘documents_documentpage', ‘content' field
|
||||
|
||||
References:
|
||||
|
||||
* http://groups.google.com/group/django-users/browse_thread/thread/429447086fca6412
|
||||
* http://markmail.org/message/bqajx2utvmtriixi
|
||||
|
||||
|
||||
Error "django.db.utils.IntegrityError IntegrityError: (1452, ‘Cannot add or update a child row: a foreign key constraint fails (`…`.`…`, CONSTRAINT `…_refs_id_b0252274` FOREIGN KEY (`…`) REFERENCES `…` (`…`))')
|
||||
==================================================================================================================================================================================================================
|
||||
|
||||
Solution:
|
||||
Convert all MySQL tables to the same type, either all MyISAM or InnoDB
|
||||
|
||||
|
||||
******
|
||||
Docker
|
||||
******
|
||||
|
||||
MAYAN_APT_INSTALLS does not work for Archlinux with kernels > 4.14
|
||||
==================================================================
|
||||
|
||||
This is caused by a change from kernel 4.18 - 4.19. Metacopy on these kernels
|
||||
is set to yes in archlinux kernels (/sys/module/overlay/parameters/metacopy)
|
||||
and overlayfs should override this which it does not at the moment.
|
||||
|
||||
The workaround is to disable metacopy::
|
||||
|
||||
echo N | sudo tee /sys/module/overlay/parameters/metacopy
|
||||
|
||||
References:
|
||||
|
||||
* https://bbs.archlinux.org/viewtopic.php?id=241866
|
||||
* https://www.spinics.net/lists/linux-unionfs/msg06316.html
|
||||
|
||||
|
||||
|
||||
*********
|
||||
Passwords
|
||||
*********
|
||||
|
||||
.. _troubleshooting-admin-password:
|
||||
|
||||
Admin password reset
|
||||
====================
|
||||
|
||||
To reset the password of the admin account use the following command::
|
||||
|
||||
MAYAN_MEDIA_ROOT=<your Mayan media root setting> <installation directory>/bin/mayan-edms.py changepassword admin
|
||||
|
||||
If you followed the deploying instructions from the documentation your
|
||||
``MAYAN_MEDIA_ROOT`` will be ``/opt/mayan-edms/media``.
|
||||
|
||||
If using a Docker image, execute the command inside the container. First you
|
||||
need to know the name of the Docker container running Mayan EDMS on your setup
|
||||
with::
|
||||
|
||||
docker ps
|
||||
|
||||
Then execute the password reset command inside the Docker container::
|
||||
|
||||
docker exec -ti <your docker container name> /opt/mayan-edms/bin/mayan-edms.py changepassword admin
|
||||
|
||||
Another way to do this is to execute a shell inside the container to get a
|
||||
command prompt::
|
||||
|
||||
docker exec -ti <your docker container name> /bin/bash
|
||||
|
||||
And then execute the command::
|
||||
|
||||
/opt/mayan-edms/bin/mayan-edms.py changepassword admin
|
||||
|
||||
|
||||
.. _troubleshooting-autoadmin-account:
|
||||
|
||||
Missing automatic admin account after installation
|
||||
==================================================
|
||||
|
||||
This is caused when the ``initialsetup`` command is interrupted as the admin
|
||||
user is created outside of the database migrations.
|
||||
|
||||
To create an admin super user account manually use the command::
|
||||
|
||||
MAYAN_MEDIA_ROOT=<your Mayan media root setting> <installation directory>/bin/mayan-edms.py createsuperuser
|
||||
|
||||
If you followed the deploying instructions from the documentation your
|
||||
``MAYAN_MEDIA_ROOT`` will be ``/opt/mayan-edms/media``.
|
||||
|
||||
If using a Docker image, execute the command inside the container. First
|
||||
find you container name with::
|
||||
|
||||
docker ps
|
||||
|
||||
Then execute the command inside the container::
|
||||
|
||||
docker exec -ti <your docker container name> /opt/mayan-edms/bin/mayan-edms.py createsuperuser
|
||||
|
||||
Another way to do this is to execute a shell inside the container to get a
|
||||
command prompt::
|
||||
|
||||
docker exec -ti <your docker container name> /bin/bash
|
||||
|
||||
And then execute the command::
|
||||
|
||||
/opt/mayan-edms/bin/mayan-edms.py createsuperuser
|
||||
@@ -1,9 +1,9 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__title__ = 'Mayan EDMS'
|
||||
__version__ = '3.1.9'
|
||||
__build__ = 0x030109
|
||||
__build_string__ = 'v3.1.9_Thu Nov 1 03:55:06 2018 -0400'
|
||||
__version__ = '3.2b1'
|
||||
__build__ = 0x030200
|
||||
__build_string__ = 'v3.2b1_Thu May 16 01:31:36 2019 -0400'
|
||||
__django_version__ = '1.11'
|
||||
__author__ = 'Roberto Rosario'
|
||||
__author_email__ = 'roberto.rosario@mayan-edms.com'
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .classes import ModelPermission # NOQA
|
||||
|
||||
default_app_config = 'mayan.apps.acls.apps.ACLsApp'
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from rest_framework import generics
|
||||
|
||||
from .models import AccessControlList
|
||||
@@ -25,7 +26,7 @@ class APIObjectACLListView(generics.ListCreateAPIView):
|
||||
)
|
||||
|
||||
content_object = get_object_or_404(
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_pk']
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_id']
|
||||
)
|
||||
|
||||
if self.request.method == 'GET':
|
||||
@@ -34,8 +35,8 @@ class APIObjectACLListView(generics.ListCreateAPIView):
|
||||
permission_required = permission_acl_edit
|
||||
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=permission_required, user=self.request.user,
|
||||
obj=content_object
|
||||
obj=content_object, permissions=(permission_required,),
|
||||
user=self.request.user
|
||||
)
|
||||
|
||||
return content_object
|
||||
@@ -61,7 +62,9 @@ class APIObjectACLListView(generics.ListCreateAPIView):
|
||||
if not self.request:
|
||||
return None
|
||||
|
||||
return super(APIObjectACLListView, self).get_serializer(*args, **kwargs)
|
||||
return super(APIObjectACLListView, self).get_serializer(
|
||||
*args, **kwargs
|
||||
)
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.request.method == 'GET':
|
||||
@@ -89,12 +92,12 @@ class APIObjectACLView(generics.RetrieveDestroyAPIView):
|
||||
)
|
||||
|
||||
content_object = get_object_or_404(
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_pk']
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_id']
|
||||
)
|
||||
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=permission_required, user=self.request.user,
|
||||
obj=content_object
|
||||
obj=content_object, permissions=(permission_required,),
|
||||
user=self.request.user
|
||||
)
|
||||
|
||||
return content_object
|
||||
@@ -120,12 +123,17 @@ class APIObjectACLPermissionListView(generics.ListCreateAPIView):
|
||||
)
|
||||
|
||||
content_object = get_object_or_404(
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_pk']
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_id']
|
||||
)
|
||||
|
||||
if self.request.method == 'GET':
|
||||
permission = permission_acl_view
|
||||
else:
|
||||
permission = permission_acl_edit
|
||||
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=permission_acl_view, user=self.request.user,
|
||||
obj=content_object
|
||||
obj=content_object, permissions=(permission,),
|
||||
user=self.request.user
|
||||
)
|
||||
|
||||
return content_object
|
||||
@@ -146,7 +154,9 @@ class APIObjectACLPermissionListView(generics.ListCreateAPIView):
|
||||
return WritableAccessControlListPermissionSerializer
|
||||
|
||||
def get_serializer_context(self):
|
||||
context = super(APIObjectACLPermissionListView, self).get_serializer_context()
|
||||
context = super(
|
||||
APIObjectACLPermissionListView, self
|
||||
).get_serializer_context()
|
||||
if self.kwargs:
|
||||
context.update(
|
||||
{
|
||||
@@ -177,12 +187,17 @@ class APIObjectACLPermissionView(generics.RetrieveDestroyAPIView):
|
||||
)
|
||||
|
||||
content_object = get_object_or_404(
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_pk']
|
||||
klass=content_type.model_class(), pk=self.kwargs['object_id']
|
||||
)
|
||||
|
||||
if self.request.method == 'GET':
|
||||
permission = permission_acl_view
|
||||
else:
|
||||
permission = permission_acl_edit
|
||||
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=permission_acl_view, user=self.request.user,
|
||||
obj=content_object
|
||||
obj=content_object, permissions=(permission,),
|
||||
user=self.request.user
|
||||
)
|
||||
|
||||
return content_object
|
||||
@@ -191,7 +206,9 @@ class APIObjectACLPermissionView(generics.RetrieveDestroyAPIView):
|
||||
return self.get_acl().permissions.all()
|
||||
|
||||
def get_serializer_context(self):
|
||||
context = super(APIObjectACLPermissionView, self).get_serializer_context()
|
||||
context = super(
|
||||
APIObjectACLPermissionView, self
|
||||
).get_serializer_context()
|
||||
if self.kwargs:
|
||||
context.update(
|
||||
{
|
||||
|
||||
@@ -2,9 +2,16 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mayan.apps.common import MayanAppConfig, menu_object, menu_sidebar
|
||||
from mayan.apps.navigation import SourceColumn
|
||||
from mayan.apps.common.apps import MayanAppConfig
|
||||
from mayan.apps.common.menus import menu_object, menu_secondary
|
||||
from mayan.apps.events.classes import ModelEventType
|
||||
from mayan.apps.events.links import (
|
||||
link_events_for_object, link_object_event_types_user_subcriptions_list
|
||||
)
|
||||
from mayan.apps.navigation.classes import SourceColumn
|
||||
|
||||
from .classes import ModelPermission
|
||||
from .events import event_acl_created, event_acl_edited
|
||||
from .links import link_acl_create, link_acl_delete, link_acl_permissions
|
||||
|
||||
|
||||
@@ -18,21 +25,33 @@ class ACLsApp(MayanAppConfig):
|
||||
|
||||
def ready(self):
|
||||
super(ACLsApp, self).ready()
|
||||
from actstream import registry
|
||||
|
||||
AccessControlList = self.get_model('AccessControlList')
|
||||
AccessControlList = self.get_model(model_name='AccessControlList')
|
||||
|
||||
SourceColumn(
|
||||
source=AccessControlList, label=_('Role'), attribute='role'
|
||||
ModelEventType.register(
|
||||
event_types=(event_acl_created, event_acl_edited),
|
||||
model=AccessControlList
|
||||
)
|
||||
|
||||
ModelPermission.register_inheritance(
|
||||
model=AccessControlList, related='content_object',
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
source=AccessControlList, label=_('Permissions'),
|
||||
attribute='get_permission_titles'
|
||||
attribute='role', is_sortable=True, source=AccessControlList,
|
||||
)
|
||||
|
||||
menu_object.bind_links(
|
||||
links=(link_acl_permissions, link_acl_delete),
|
||||
links=(
|
||||
link_acl_permissions, link_acl_delete,
|
||||
link_events_for_object,
|
||||
link_object_event_types_user_subcriptions_list
|
||||
),
|
||||
sources=(AccessControlList,)
|
||||
)
|
||||
menu_sidebar.bind_links(
|
||||
menu_secondary.bind_links(
|
||||
links=(link_acl_create,), sources=('acls:acl_list',)
|
||||
)
|
||||
|
||||
registry.register(AccessControlList)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
@@ -8,10 +8,26 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ModelPermission(object):
|
||||
_functions = {}
|
||||
_inheritances = {}
|
||||
_proxies = {}
|
||||
_registry = {}
|
||||
|
||||
@classmethod
|
||||
def register(cls, model, permissions):
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
|
||||
cls._registry.setdefault(model, [])
|
||||
for permission in permissions:
|
||||
cls._registry[model].append(permission)
|
||||
|
||||
AccessControlList = apps.get_model(
|
||||
app_label='acls', model_name='AccessControlList'
|
||||
)
|
||||
|
||||
model.add_to_class(
|
||||
name='acls', value=GenericRelation(AccessControlList)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_classes(cls, as_content_type=False):
|
||||
ContentType = apps.get_model(
|
||||
@@ -20,7 +36,7 @@ class ModelPermission(object):
|
||||
|
||||
if as_content_type:
|
||||
content_type_dictionary = ContentType.objects.get_for_models(
|
||||
*cls._registry.keys()
|
||||
models=cls._registry.keys()
|
||||
)
|
||||
content_type_ids = [
|
||||
content_type.pk for content_type in content_type_dictionary.values()
|
||||
@@ -47,40 +63,23 @@ class ModelPermission(object):
|
||||
if class_permissions:
|
||||
permissions.extend(class_permissions)
|
||||
|
||||
proxy = cls._proxies.get(type(instance))
|
||||
|
||||
if proxy:
|
||||
permissions.extend(cls._registry.get(proxy))
|
||||
|
||||
pks = [
|
||||
permission.stored_permission.pk for permission in set(permissions)
|
||||
]
|
||||
return StoredPermission.objects.filter(pk__in=pks)
|
||||
|
||||
@classmethod
|
||||
def get_function(cls, model):
|
||||
return cls._functions[model]
|
||||
|
||||
@classmethod
|
||||
def get_inheritance(cls, model):
|
||||
return cls._inheritances[model]
|
||||
|
||||
@classmethod
|
||||
def register(cls, model, permissions):
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
|
||||
cls._registry.setdefault(model, [])
|
||||
for permission in permissions:
|
||||
cls._registry[model].append(permission)
|
||||
|
||||
AccessControlList = apps.get_model(
|
||||
app_label='acls', model_name='AccessControlList'
|
||||
)
|
||||
|
||||
model.add_to_class(
|
||||
name='acls', value=GenericRelation(to=AccessControlList)
|
||||
)
|
||||
def register_function(cls, model, function):
|
||||
cls._functions[model] = function
|
||||
|
||||
@classmethod
|
||||
def register_inheritance(cls, model, related):
|
||||
cls._inheritances[model] = related
|
||||
|
||||
@classmethod
|
||||
def register_proxy(cls, source, model):
|
||||
cls._proxies[model] = source
|
||||
|
||||
16
mayan/apps/acls/events.py
Normal file
16
mayan/apps/acls/events.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mayan.apps.events.classes import EventTypeNamespace
|
||||
|
||||
namespace = EventTypeNamespace(
|
||||
label=_('Access control lists'), name='acls'
|
||||
)
|
||||
|
||||
event_acl_created = namespace.add_event_type(
|
||||
label=_('ACL created'), name='acl_created'
|
||||
)
|
||||
event_acl_edited = namespace.add_event_type(
|
||||
label=_('ACL edited'), name='acl_edited'
|
||||
)
|
||||
17
mayan/apps/acls/forms.py
Normal file
17
mayan/apps/acls/forms.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mayan.apps.common.forms import FilteredSelectionForm
|
||||
|
||||
from .models import AccessControlList
|
||||
|
||||
|
||||
class ACLCreateForm(FilteredSelectionForm, forms.ModelForm):
|
||||
class Meta:
|
||||
field_name = 'role'
|
||||
fields = ('role',)
|
||||
label = _('Role')
|
||||
model = AccessControlList
|
||||
widget_attributes = {'class': 'select2'}
|
||||
@@ -1,9 +1,12 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from mayan.apps.appearance.classes import Icon
|
||||
from mayan.apps.permissions.icons import icon_permission
|
||||
|
||||
icon_acl_delete = Icon(driver_name='fontawesome', symbol='times')
|
||||
icon_acl_list = Icon(driver_name='fontawesome', symbol='lock')
|
||||
icon_acl_new = Icon(
|
||||
driver_name='fontawesome-dual', primary_symbol='lock',
|
||||
secondary_symbol='plus'
|
||||
)
|
||||
icon_acl_permissions = icon_permission
|
||||
|
||||
@@ -3,10 +3,12 @@ from __future__ import unicode_literals
|
||||
from django.apps import apps
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mayan.apps.navigation import Link
|
||||
from mayan.apps.navigation.classes import Link
|
||||
|
||||
from .icons import icon_acl_list, icon_acl_new
|
||||
from .permissions import permission_acl_edit, permission_acl_view
|
||||
from .icons import (
|
||||
icon_acl_delete, icon_acl_list, icon_acl_new, icon_acl_permissions
|
||||
)
|
||||
from .permissions import permission_acl_view, permission_acl_edit
|
||||
|
||||
|
||||
def get_kwargs_factory(variable_name):
|
||||
@@ -27,22 +29,22 @@ def get_kwargs_factory(variable_name):
|
||||
return get_kwargs
|
||||
|
||||
|
||||
link_acl_delete = Link(
|
||||
args='resolved_object.pk', permissions=(permission_acl_edit,),
|
||||
permissions_related='content_object', tags='dangerous', text=_('Delete'),
|
||||
view='acls:acl_delete',
|
||||
)
|
||||
link_acl_list = Link(
|
||||
icon_class=icon_acl_list, kwargs=get_kwargs_factory('resolved_object'),
|
||||
permissions=(permission_acl_view,), text=_('ACLs'), view='acls:acl_list'
|
||||
)
|
||||
link_acl_create = Link(
|
||||
icon_class=icon_acl_new, kwargs=get_kwargs_factory('resolved_object'),
|
||||
permissions=(permission_acl_edit,), text=_('New ACL'),
|
||||
view='acls:acl_create'
|
||||
)
|
||||
link_acl_permissions = Link(
|
||||
args='resolved_object.pk', permissions=(permission_acl_edit,),
|
||||
permissions_related='content_object', text=_('Permissions'),
|
||||
view='acls:acl_permissions',
|
||||
link_acl_delete = Link(
|
||||
args='resolved_object.pk', icon_class=icon_acl_delete,
|
||||
permissions=(permission_acl_edit,), tags='dangerous', text=_('Delete'),
|
||||
view='acls:acl_delete'
|
||||
)
|
||||
link_acl_list = Link(
|
||||
icon_class=icon_acl_list, kwargs=get_kwargs_factory('resolved_object'),
|
||||
permissions=(permission_acl_view,), text=_('ACLs'), view='acls:acl_list'
|
||||
)
|
||||
link_acl_permissions = Link(
|
||||
args='resolved_object.pk', icon_class=icon_acl_permissions,
|
||||
permissions=(permission_acl_edit,),
|
||||
text=_('Permissions'), view='acls:acl_permissions'
|
||||
)
|
||||
|
||||
Binary file not shown.
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-10-29 12:42-0400\n"
|
||||
"PO-Revision-Date: 2018-09-08 08:06+0000\n"
|
||||
"POT-Creation-Date: 2019-05-21 00:57-0400\n"
|
||||
"PO-Revision-Date: 2019-05-05 01:43+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/rosarior/mayan-edms/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -17,52 +17,61 @@ msgstr ""
|
||||
"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"
|
||||
|
||||
#: apps.py:15 links.py:37
|
||||
#: apps.py:24 links.py:44
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: apps.py:23 models.py:47
|
||||
#: events.py:8 permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Access control lists"
|
||||
|
||||
#: events.py:12
|
||||
msgid "ACL created"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:15
|
||||
msgid "ACL edited"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15 models.py:49
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: apps.py:26 links.py:46 models.py:43 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "الصلاحيات"
|
||||
|
||||
#: links.py:32
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:41
|
||||
#: links.py:34
|
||||
msgid "New ACL"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:57 managers.py:96
|
||||
#: links.py:39
|
||||
msgid "Delete"
|
||||
msgstr "حذف"
|
||||
|
||||
#: links.py:49 models.py:45 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "الصلاحيات"
|
||||
|
||||
#: managers.py:209
|
||||
#, python-format
|
||||
msgid "Object \"%s\" is not a model and cannot be checked for access."
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:229
|
||||
#, python-format
|
||||
msgid "Insufficient access for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:55
|
||||
#: models.py:57
|
||||
msgid "Access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:56
|
||||
#: models.py:58
|
||||
msgid "Access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:60
|
||||
#: models.py:62
|
||||
#, python-format
|
||||
msgid "Permissions \"%(permissions)s\" to role \"%(role)s\" for \"%(object)s\""
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: models.py:77
|
||||
msgid "None"
|
||||
msgstr "لا شيء"
|
||||
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Access control lists"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Edit ACLs"
|
||||
@@ -71,76 +80,80 @@ msgstr "Edit ACLs"
|
||||
msgid "View ACLs"
|
||||
msgstr "View ACLs"
|
||||
|
||||
#: serializers.py:24 serializers.py:132
|
||||
#: serializers.py:26 serializers.py:136
|
||||
msgid ""
|
||||
"API URL pointing to the list of permissions for this access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:57
|
||||
#: serializers.py:59
|
||||
msgid ""
|
||||
"API URL pointing to a permission in relation to the access control list to "
|
||||
"which it is attached. This URL is different than the canonical workflow URL."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:87
|
||||
#: serializers.py:91
|
||||
msgid "Primary key of the new permission to grant to the access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:111 serializers.py:187
|
||||
#: serializers.py:115 serializers.py:191
|
||||
#, python-format
|
||||
msgid "No such permission: %s"
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:126
|
||||
#: serializers.py:130
|
||||
msgid ""
|
||||
"Comma separated list of permission primary keys to grant to this access "
|
||||
"control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:138
|
||||
#: serializers.py:142
|
||||
msgid "Primary keys of the role to which this access control list binds to."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:77
|
||||
#: views.py:62
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104
|
||||
#: views.py:100
|
||||
#, python-format
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:148
|
||||
#: views.py:147
|
||||
msgid "There are no ACLs for this object"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:151
|
||||
#: views.py:150
|
||||
msgid ""
|
||||
"ACL stands for Access Control List and is a precise method to control user "
|
||||
"access to objects in the system."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:155
|
||||
#: views.py:154
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:167
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:168
|
||||
#: views.py:170
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:230
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
#: views.py:171
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:250
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
#: views.py:215
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:224
|
||||
msgid ""
|
||||
"Disabled permissions are inherited from a parent object or directly granted "
|
||||
"to the role and can't be removed from this view. Inherited permissions need "
|
||||
"to be removed from the parent object's ACL or from them role via the Setup "
|
||||
"menu."
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:25
|
||||
@@ -177,6 +190,6 @@ msgstr ""
|
||||
msgid "Grant access"
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:129
|
||||
#: workflow_actions.py:135
|
||||
msgid "Revoke access"
|
||||
msgstr ""
|
||||
|
||||
Binary file not shown.
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-10-29 12:42-0400\n"
|
||||
"PO-Revision-Date: 2018-09-08 08:06+0000\n"
|
||||
"POT-Creation-Date: 2019-05-21 00:57-0400\n"
|
||||
"PO-Revision-Date: 2019-05-05 01:43+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/rosarior/mayan-edms/language/bg/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -17,52 +17,61 @@ msgstr ""
|
||||
"Language: bg\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: apps.py:15 links.py:37
|
||||
#: apps.py:24 links.py:44
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: apps.py:23 models.py:47
|
||||
#: events.py:8 permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
|
||||
#: events.py:12
|
||||
msgid "ACL created"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:15
|
||||
msgid "ACL edited"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15 models.py:49
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: apps.py:26 links.py:46 models.py:43 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Разрешения"
|
||||
|
||||
#: links.py:32
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:41
|
||||
#: links.py:34
|
||||
msgid "New ACL"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:57 managers.py:96
|
||||
#: links.py:39
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:49 models.py:45 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Разрешения"
|
||||
|
||||
#: managers.py:209
|
||||
#, python-format
|
||||
msgid "Object \"%s\" is not a model and cannot be checked for access."
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:229
|
||||
#, python-format
|
||||
msgid "Insufficient access for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:55
|
||||
#: models.py:57
|
||||
msgid "Access entry"
|
||||
msgstr "достъп вписване"
|
||||
|
||||
#: models.py:56
|
||||
#: models.py:58
|
||||
msgid "Access entries"
|
||||
msgstr "достъп вписвания"
|
||||
|
||||
#: models.py:60
|
||||
#: models.py:62
|
||||
#, python-format
|
||||
msgid "Permissions \"%(permissions)s\" to role \"%(role)s\" for \"%(object)s\""
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: models.py:77
|
||||
msgid "None"
|
||||
msgstr "Няма"
|
||||
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Редактиране на контролни списъци за достъп"
|
||||
@@ -71,76 +80,80 @@ msgstr "Редактиране на контролни списъци за до
|
||||
msgid "View ACLs"
|
||||
msgstr "Преглед на контролни списъци за достъп"
|
||||
|
||||
#: serializers.py:24 serializers.py:132
|
||||
#: serializers.py:26 serializers.py:136
|
||||
msgid ""
|
||||
"API URL pointing to the list of permissions for this access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:57
|
||||
#: serializers.py:59
|
||||
msgid ""
|
||||
"API URL pointing to a permission in relation to the access control list to "
|
||||
"which it is attached. This URL is different than the canonical workflow URL."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:87
|
||||
#: serializers.py:91
|
||||
msgid "Primary key of the new permission to grant to the access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:111 serializers.py:187
|
||||
#: serializers.py:115 serializers.py:191
|
||||
#, python-format
|
||||
msgid "No such permission: %s"
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:126
|
||||
#: serializers.py:130
|
||||
msgid ""
|
||||
"Comma separated list of permission primary keys to grant to this access "
|
||||
"control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:138
|
||||
#: serializers.py:142
|
||||
msgid "Primary keys of the role to which this access control list binds to."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:77
|
||||
#: views.py:62
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104
|
||||
#: views.py:100
|
||||
#, python-format
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:148
|
||||
#: views.py:147
|
||||
msgid "There are no ACLs for this object"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:151
|
||||
#: views.py:150
|
||||
msgid ""
|
||||
"ACL stands for Access Control List and is a precise method to control user "
|
||||
"access to objects in the system."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:155
|
||||
#: views.py:154
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:167
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:168
|
||||
#: views.py:170
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:230
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
#: views.py:171
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:250
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
#: views.py:215
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:224
|
||||
msgid ""
|
||||
"Disabled permissions are inherited from a parent object or directly granted "
|
||||
"to the role and can't be removed from this view. Inherited permissions need "
|
||||
"to be removed from the parent object's ACL or from them role via the Setup "
|
||||
"menu."
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:25
|
||||
@@ -177,6 +190,6 @@ msgstr ""
|
||||
msgid "Grant access"
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:129
|
||||
#: workflow_actions.py:135
|
||||
msgid "Revoke access"
|
||||
msgstr ""
|
||||
|
||||
Binary file not shown.
@@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-10-29 12:42-0400\n"
|
||||
"PO-Revision-Date: 2018-09-08 08:06+0000\n"
|
||||
"POT-Creation-Date: 2019-05-21 00:57-0400\n"
|
||||
"PO-Revision-Date: 2019-05-05 01:43+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Bosnian (Bosnia and Herzegovina) (http://www.transifex.com/rosarior/mayan-edms/language/bs_BA/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -18,51 +18,60 @@ msgstr ""
|
||||
"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"
|
||||
|
||||
#: apps.py:15 links.py:37
|
||||
#: apps.py:24 links.py:44
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: apps.py:23 models.py:47
|
||||
#: events.py:8 permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Liste kontrole pristupa (ACLs)"
|
||||
|
||||
#: events.py:12
|
||||
msgid "ACL created"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:15
|
||||
msgid "ACL edited"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15 models.py:49
|
||||
msgid "Role"
|
||||
msgstr "Uloga"
|
||||
|
||||
#: apps.py:26 links.py:46 models.py:43 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Dozvole"
|
||||
|
||||
#: links.py:32
|
||||
msgid "Delete"
|
||||
msgstr "Obriši"
|
||||
|
||||
#: links.py:41
|
||||
#: links.py:34
|
||||
msgid "New ACL"
|
||||
msgstr "Novi ACL"
|
||||
|
||||
#: managers.py:57 managers.py:96
|
||||
#: links.py:39
|
||||
msgid "Delete"
|
||||
msgstr "Obriši"
|
||||
|
||||
#: links.py:49 models.py:45 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Dozvole"
|
||||
|
||||
#: managers.py:209
|
||||
#, python-format
|
||||
msgid "Object \"%s\" is not a model and cannot be checked for access."
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:229
|
||||
#, python-format
|
||||
msgid "Insufficient access for: %s"
|
||||
msgstr "Nedovoljan pristup za:%s"
|
||||
|
||||
#: models.py:55
|
||||
#: models.py:57
|
||||
msgid "Access entry"
|
||||
msgstr "Pristupni unos"
|
||||
|
||||
#: models.py:56
|
||||
#: models.py:58
|
||||
msgid "Access entries"
|
||||
msgstr "Pristupni unosi"
|
||||
|
||||
#: models.py:60
|
||||
#: models.py:62
|
||||
#, python-format
|
||||
msgid "Permissions \"%(permissions)s\" to role \"%(role)s\" for \"%(object)s\""
|
||||
msgstr "Pristup \"%(permissions)s\" za ulogu \"%(role)s\" za \"%(object)s\""
|
||||
|
||||
#: models.py:77
|
||||
msgid "None"
|
||||
msgstr "Nijedno"
|
||||
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "Liste kontrole pristupa (ACLs)"
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr "Uloga \"%(role)s\" dozvole za \"%(object)s\""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
@@ -72,77 +81,81 @@ msgstr "Izmjeniti ACLs"
|
||||
msgid "View ACLs"
|
||||
msgstr "Pregledati ACLs"
|
||||
|
||||
#: serializers.py:24 serializers.py:132
|
||||
#: serializers.py:26 serializers.py:136
|
||||
msgid ""
|
||||
"API URL pointing to the list of permissions for this access control list."
|
||||
msgstr "API URL ukazujući na listu dozvola za ovu listu kontrole pristupa."
|
||||
|
||||
#: serializers.py:57
|
||||
#: serializers.py:59
|
||||
msgid ""
|
||||
"API URL pointing to a permission in relation to the access control list to "
|
||||
"which it is attached. This URL is different than the canonical workflow URL."
|
||||
msgstr "URL API koji ukazuje na dozvolu u vezi sa listom kontrole pristupa kojoj je priložena. Ova URL adresa se razlikuje od kanonskog URL-a za radni tok."
|
||||
|
||||
#: serializers.py:87
|
||||
#: serializers.py:91
|
||||
msgid "Primary key of the new permission to grant to the access control list."
|
||||
msgstr "Primarni ključ za novu dozvolu za dodjelu listi kontrole pristupa."
|
||||
|
||||
#: serializers.py:111 serializers.py:187
|
||||
#: serializers.py:115 serializers.py:191
|
||||
#, python-format
|
||||
msgid "No such permission: %s"
|
||||
msgstr "Nema takve dozvole: %s"
|
||||
|
||||
#: serializers.py:126
|
||||
#: serializers.py:130
|
||||
msgid ""
|
||||
"Comma separated list of permission primary keys to grant to this access "
|
||||
"control list."
|
||||
msgstr "Lista odvojenih primarnih ključeva za razdvajanje sa komandom dodeljuje se ovoj listi kontrola pristupa."
|
||||
|
||||
#: serializers.py:138
|
||||
#: serializers.py:142
|
||||
msgid "Primary keys of the role to which this access control list binds to."
|
||||
msgstr "Primarni ključevi uloge na koje se ova lista kontrole pristupa vezuje."
|
||||
|
||||
#: views.py:77
|
||||
#: views.py:62
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr "Nove kontrole pristupa za:%s"
|
||||
|
||||
#: views.py:104
|
||||
#: views.py:100
|
||||
#, python-format
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr "Obriši ACL:%s"
|
||||
|
||||
#: views.py:148
|
||||
#: views.py:147
|
||||
msgid "There are no ACLs for this object"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:151
|
||||
#: views.py:150
|
||||
msgid ""
|
||||
"ACL stands for Access Control List and is a precise method to control user "
|
||||
"access to objects in the system."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:155
|
||||
#: views.py:154
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr "Liste kontrole pristupa (ACL) za: %s"
|
||||
|
||||
#: views.py:167
|
||||
msgid "Available permissions"
|
||||
msgstr "Dostupne dozvole"
|
||||
|
||||
#: views.py:168
|
||||
#: views.py:170
|
||||
msgid "Granted permissions"
|
||||
msgstr "Dodjeljene dozvole"
|
||||
|
||||
#: views.py:230
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr "Uloga \"%(role)s\" dozvole za \"%(object)s\""
|
||||
#: views.py:171
|
||||
msgid "Available permissions"
|
||||
msgstr "Dostupne dozvole"
|
||||
|
||||
#: views.py:250
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
msgstr "Dozvole za onesposobljavanje su nasledjene od roditeljskog objekta."
|
||||
#: views.py:215
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:224
|
||||
msgid ""
|
||||
"Disabled permissions are inherited from a parent object or directly granted "
|
||||
"to the role and can't be removed from this view. Inherited permissions need "
|
||||
"to be removed from the parent object's ACL or from them role via the Setup "
|
||||
"menu."
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:25
|
||||
msgid "Object type"
|
||||
@@ -178,6 +191,6 @@ msgstr "Dozvole za dodeljivanje / poništavanje / od uloge za gore izabrani obje
|
||||
msgid "Grant access"
|
||||
msgstr "Dodjeljen pristup"
|
||||
|
||||
#: workflow_actions.py:129
|
||||
#: workflow_actions.py:135
|
||||
msgid "Revoke access"
|
||||
msgstr "Opozvati pristup"
|
||||
|
||||
BIN
mayan/apps/acls/locale/cs/LC_MESSAGES/django.mo
Normal file
BIN
mayan/apps/acls/locale/cs/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
@@ -3,150 +3,163 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Ford Guo <agile.guo@gmail.com>, 2018
|
||||
# Jiri Fait <fait@orkasolutions.cz>, 2019
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-10-29 12:42-0400\n"
|
||||
"PO-Revision-Date: 2018-10-11 03:19+0000\n"
|
||||
"Last-Translator: Ford Guo <agile.guo@gmail.com>\n"
|
||||
"Language-Team: Chinese (China) (http://www.transifex.com/rosarior/mayan-edms/language/zh_CN/)\n"
|
||||
"POT-Creation-Date: 2019-05-21 00:57-0400\n"
|
||||
"PO-Revision-Date: 2019-05-17 14:41+0000\n"
|
||||
"Last-Translator: Jiri Fait <fait@orkasolutions.cz>\n"
|
||||
"Language-Team: Czech (http://www.transifex.com/rosarior/mayan-edms/language/cs/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: zh_CN\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"Language: cs\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
||||
|
||||
#: apps.py:15 links.py:37
|
||||
#: apps.py:24 links.py:44
|
||||
msgid "ACLs"
|
||||
msgstr "访问控制列表"
|
||||
msgstr ""
|
||||
|
||||
#: apps.py:23 models.py:47
|
||||
#: events.py:8 permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:12
|
||||
msgid "ACL created"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:15
|
||||
msgid "ACL edited"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15 models.py:49
|
||||
msgid "Role"
|
||||
msgstr "角色"
|
||||
msgstr ""
|
||||
|
||||
#: apps.py:26 links.py:46 models.py:43 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "权限"
|
||||
|
||||
#: links.py:32
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
||||
#: links.py:41
|
||||
#: links.py:34
|
||||
msgid "New ACL"
|
||||
msgstr "新建访问控制表"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:57 managers.py:96
|
||||
#: links.py:39
|
||||
msgid "Delete"
|
||||
msgstr "Odstranit"
|
||||
|
||||
#: links.py:49 models.py:45 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Práva"
|
||||
|
||||
#: managers.py:209
|
||||
#, python-format
|
||||
msgid "Object \"%s\" is not a model and cannot be checked for access."
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:229
|
||||
#, python-format
|
||||
msgid "Insufficient access for: %s"
|
||||
msgstr "访问: %s权限不足"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:55
|
||||
#: models.py:57
|
||||
msgid "Access entry"
|
||||
msgstr "访问入口"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:56
|
||||
#: models.py:58
|
||||
msgid "Access entries"
|
||||
msgstr "多个访问入口"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:60
|
||||
#: models.py:62
|
||||
#, python-format
|
||||
msgid "Permissions \"%(permissions)s\" to role \"%(role)s\" for \"%(object)s\""
|
||||
msgstr "把 \"%(object)s\"的权限\"%(permissions)s\"给角色\"%(role)s\""
|
||||
|
||||
#: models.py:77
|
||||
msgid "None"
|
||||
msgstr "无"
|
||||
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr "访问控制列表"
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "编辑访问控制列表"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "View ACLs"
|
||||
msgstr "查看访问控制列表"
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:24 serializers.py:132
|
||||
#: serializers.py:26 serializers.py:136
|
||||
msgid ""
|
||||
"API URL pointing to the list of permissions for this access control list."
|
||||
msgstr "指向这个访问控制列表的权限列表的API URL"
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:57
|
||||
#: serializers.py:59
|
||||
msgid ""
|
||||
"API URL pointing to a permission in relation to the access control list to "
|
||||
"which it is attached. This URL is different than the canonical workflow URL."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:87
|
||||
#: serializers.py:91
|
||||
msgid "Primary key of the new permission to grant to the access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:111 serializers.py:187
|
||||
#: serializers.py:115 serializers.py:191
|
||||
#, python-format
|
||||
msgid "No such permission: %s"
|
||||
msgstr "无此权限: %s"
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:126
|
||||
#: serializers.py:130
|
||||
msgid ""
|
||||
"Comma separated list of permission primary keys to grant to this access "
|
||||
"control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:138
|
||||
#: serializers.py:142
|
||||
msgid "Primary keys of the role to which this access control list binds to."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:77
|
||||
#: views.py:62
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr "为 %s新建访问控制列表"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104
|
||||
#: views.py:100
|
||||
#, python-format
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr "删除访问控制列表: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:148
|
||||
#: views.py:147
|
||||
msgid "There are no ACLs for this object"
|
||||
msgstr "无此对象的访问控制列表"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:151
|
||||
#: views.py:150
|
||||
msgid ""
|
||||
"ACL stands for Access Control List and is a precise method to control user "
|
||||
"access to objects in the system."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:155
|
||||
#: views.py:154
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr "%s的访问控制列表"
|
||||
|
||||
#: views.py:167
|
||||
msgid "Available permissions"
|
||||
msgstr "有效的权限"
|
||||
|
||||
#: views.py:168
|
||||
msgid "Granted permissions"
|
||||
msgstr "被授权的权限"
|
||||
|
||||
#: views.py:230
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: views.py:250
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
#: views.py:170
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:171
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:215
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:224
|
||||
msgid ""
|
||||
"Disabled permissions are inherited from a parent object or directly granted "
|
||||
"to the role and can't be removed from this view. Inherited permissions need "
|
||||
"to be removed from the parent object's ACL or from them role via the Setup "
|
||||
"menu."
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:25
|
||||
msgid "Object type"
|
||||
msgstr "对象类型"
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:28
|
||||
msgid "Type of the object for which the access will be modified."
|
||||
@@ -154,7 +167,7 @@ msgstr ""
|
||||
|
||||
#: workflow_actions.py:34
|
||||
msgid "Object ID"
|
||||
msgstr "对象ID"
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:37
|
||||
msgid ""
|
||||
@@ -163,7 +176,7 @@ msgstr ""
|
||||
|
||||
#: workflow_actions.py:42
|
||||
msgid "Roles"
|
||||
msgstr "角色"
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:44
|
||||
msgid "Roles whose access will be modified."
|
||||
@@ -176,8 +189,8 @@ msgstr ""
|
||||
|
||||
#: workflow_actions.py:59
|
||||
msgid "Grant access"
|
||||
msgstr "授权访问"
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:129
|
||||
#: workflow_actions.py:135
|
||||
msgid "Revoke access"
|
||||
msgstr "撤销访问"
|
||||
msgstr ""
|
||||
Binary file not shown.
BIN
mayan/apps/acls/locale/da_DK/LC_MESSAGES/django.mo
Normal file
BIN
mayan/apps/acls/locale/da_DK/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
@@ -8,145 +8,158 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-10-29 12:42-0400\n"
|
||||
"PO-Revision-Date: 2018-09-08 08:06+0000\n"
|
||||
"POT-Creation-Date: 2019-05-21 00:57-0400\n"
|
||||
"PO-Revision-Date: 2019-05-05 01:43+0000\n"
|
||||
"Last-Translator: Roberto Rosario\n"
|
||||
"Language-Team: Danish (http://www.transifex.com/rosarior/mayan-edms/language/da/)\n"
|
||||
"Language-Team: Danish (Denmark) (http://www.transifex.com/rosarior/mayan-edms/language/da_DK/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: da\n"
|
||||
"Language: da_DK\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: apps.py:15 links.py:37
|
||||
#: apps.py:24 links.py:44
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
msgstr "ACL'er"
|
||||
|
||||
#: apps.py:23 models.py:47
|
||||
#: events.py:8 permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:12
|
||||
msgid "ACL created"
|
||||
msgstr ""
|
||||
|
||||
#: events.py:15
|
||||
msgid "ACL edited"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15 models.py:49
|
||||
msgid "Role"
|
||||
msgstr "Rolle"
|
||||
|
||||
#: apps.py:26 links.py:46 models.py:43 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Tilladelse"
|
||||
|
||||
#: links.py:32
|
||||
msgid "Delete"
|
||||
msgstr "Slet"
|
||||
|
||||
#: links.py:41
|
||||
#: links.py:34
|
||||
msgid "New ACL"
|
||||
msgstr "Ny ACL"
|
||||
|
||||
#: managers.py:57 managers.py:96
|
||||
#: links.py:39
|
||||
msgid "Delete"
|
||||
msgstr "Slet"
|
||||
|
||||
#: links.py:49 models.py:45 workflow_actions.py:48
|
||||
msgid "Permissions"
|
||||
msgstr "Tilladelser"
|
||||
|
||||
#: managers.py:209
|
||||
#, python-format
|
||||
msgid "Object \"%s\" is not a model and cannot be checked for access."
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:229
|
||||
#, python-format
|
||||
msgid "Insufficient access for: %s"
|
||||
msgstr "Utilstrækkelig adgang til: %s"
|
||||
msgstr "Utilstækkelig adgang for: %s"
|
||||
|
||||
#: models.py:55
|
||||
#: models.py:57
|
||||
msgid "Access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:56
|
||||
#: models.py:58
|
||||
msgid "Access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:60
|
||||
#: models.py:62
|
||||
#, python-format
|
||||
msgid "Permissions \"%(permissions)s\" to role \"%(role)s\" for \"%(object)s\""
|
||||
msgstr "Tilladelse \"%(permissions)s\" til rolle \"%(role)s\" for \"%(object)s\""
|
||||
|
||||
#: models.py:77
|
||||
msgid "None"
|
||||
msgstr "Ingen"
|
||||
|
||||
#: permissions.py:7
|
||||
msgid "Access control lists"
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Redigér ACL'er"
|
||||
msgstr "Editér ACL"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "View ACLs"
|
||||
msgstr "Se ACL'er"
|
||||
msgstr "Se ACL"
|
||||
|
||||
#: serializers.py:24 serializers.py:132
|
||||
#: serializers.py:26 serializers.py:136
|
||||
msgid ""
|
||||
"API URL pointing to the list of permissions for this access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:57
|
||||
#: serializers.py:59
|
||||
msgid ""
|
||||
"API URL pointing to a permission in relation to the access control list to "
|
||||
"which it is attached. This URL is different than the canonical workflow URL."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:87
|
||||
#: serializers.py:91
|
||||
msgid "Primary key of the new permission to grant to the access control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:111 serializers.py:187
|
||||
#: serializers.py:115 serializers.py:191
|
||||
#, python-format
|
||||
msgid "No such permission: %s"
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:126
|
||||
#: serializers.py:130
|
||||
msgid ""
|
||||
"Comma separated list of permission primary keys to grant to this access "
|
||||
"control list."
|
||||
msgstr ""
|
||||
|
||||
#: serializers.py:138
|
||||
#: serializers.py:142
|
||||
msgid "Primary keys of the role to which this access control list binds to."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:77
|
||||
#: views.py:62
|
||||
#, python-format
|
||||
msgid "New access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104
|
||||
#: views.py:100
|
||||
#, python-format
|
||||
msgid "Delete ACL: %s"
|
||||
msgstr "Slet ACL: %s"
|
||||
|
||||
#: views.py:148
|
||||
#: views.py:147
|
||||
msgid "There are no ACLs for this object"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:151
|
||||
#: views.py:150
|
||||
msgid ""
|
||||
"ACL stands for Access Control List and is a precise method to control user "
|
||||
"access to objects in the system."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:155
|
||||
#: views.py:154
|
||||
#, python-format
|
||||
msgid "Access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:167
|
||||
msgid "Available permissions"
|
||||
msgstr "Tilgængelige tilladelser"
|
||||
|
||||
#: views.py:168
|
||||
#: views.py:170
|
||||
msgid "Granted permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:230
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\""
|
||||
#: views.py:171
|
||||
msgid "Available permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:250
|
||||
msgid "Disabled permissions are inherited from a parent object."
|
||||
#: views.py:215
|
||||
#, python-format
|
||||
msgid "Role \"%(role)s\" permission's for \"%(object)s\"."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:224
|
||||
msgid ""
|
||||
"Disabled permissions are inherited from a parent object or directly granted "
|
||||
"to the role and can't be removed from this view. Inherited permissions need "
|
||||
"to be removed from the parent object's ACL or from them role via the Setup "
|
||||
"menu."
|
||||
msgstr ""
|
||||
|
||||
#: workflow_actions.py:25
|
||||
msgid "Object type"
|
||||
msgstr ""
|
||||
msgstr "Objekttype"
|
||||
|
||||
#: workflow_actions.py:28
|
||||
msgid "Type of the object for which the access will be modified."
|
||||
@@ -154,7 +167,7 @@ msgstr ""
|
||||
|
||||
#: workflow_actions.py:34
|
||||
msgid "Object ID"
|
||||
msgstr ""
|
||||
msgstr "Objekt ID"
|
||||
|
||||
#: workflow_actions.py:37
|
||||
msgid ""
|
||||
@@ -176,8 +189,8 @@ msgstr ""
|
||||
|
||||
#: workflow_actions.py:59
|
||||
msgid "Grant access"
|
||||
msgstr ""
|
||||
msgstr "Giv tilladelse"
|
||||
|
||||
#: workflow_actions.py:129
|
||||
#: workflow_actions.py:135
|
||||
msgid "Revoke access"
|
||||
msgstr ""
|
||||
msgstr "Tilbagekald tilladelse"
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user