Compare commits
719 Commits
features/d
...
unstable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4397784388 | ||
|
|
d41dac13ea | ||
|
|
3b9a5080b5 | ||
|
|
de9b716e77 | ||
|
|
deef1dc19c | ||
|
|
9f3838b5f6 | ||
|
|
4a9e2c2aa7 | ||
|
|
e62835fd27 | ||
|
|
0f1e01084c | ||
|
|
0753d40a5d | ||
|
|
2fb1208888 | ||
|
|
2eb3dfcbfd | ||
|
|
cad7cd4e95 | ||
|
|
6225e8f561 | ||
|
|
e9f3ba67a6 | ||
|
|
fe2d57e2f3 | ||
|
|
a7be0d567f | ||
|
|
0ee2c98d51 | ||
|
|
f2ad6b5cde | ||
|
|
73912f11d4 | ||
|
|
3821f9bf3e | ||
|
|
474da4308d | ||
|
|
64b06dc56f | ||
|
|
7ccb3cc152 | ||
|
|
830e937e1b | ||
|
|
7681f82321 | ||
|
|
e8a0e2b5ab | ||
|
|
c7a464797c | ||
|
|
6c713bd2de | ||
|
|
95e1b9036b | ||
|
|
714af0764a | ||
|
|
6d434b57f8 | ||
|
|
ae4e7ce32e | ||
|
|
b5d09be31b | ||
|
|
daf72a8770 | ||
|
|
71c1f02a8d | ||
|
|
647835d0f5 | ||
|
|
87d27a6d7a | ||
|
|
9e9e154642 | ||
|
|
27f0fca914 | ||
|
|
2b24314d25 | ||
|
|
b4b7d610f9 | ||
|
|
9b70f6c11c | ||
|
|
2aa1c2fcce | ||
|
|
b2828d1e1c | ||
|
|
1d8266fe5d | ||
|
|
3b895d7560 | ||
|
|
b42a43bafd | ||
|
|
d75e8b345f | ||
|
|
a237217f8b | ||
|
|
c169d23714 | ||
|
|
109941fcf8 | ||
|
|
7cebb82e1c | ||
|
|
11aa9e64f1 | ||
|
|
0a72fccb97 | ||
|
|
b714aa420f | ||
|
|
827384cc95 | ||
|
|
57d3cf8f4a | ||
|
|
b74245979e | ||
|
|
5982c1b2ee | ||
|
|
46fb8dfc10 | ||
|
|
7f7ba8924d | ||
|
|
cb4c70c822 | ||
|
|
0ec69bc4fc | ||
|
|
37f79ffde3 | ||
|
|
47ac12b4d1 | ||
|
|
d48338a989 | ||
|
|
397c1ad86b | ||
|
|
fbee8cb64c | ||
|
|
aac3bd0bbe | ||
|
|
fec0d82f6f | ||
|
|
5593c3ae84 | ||
|
|
51426632ca | ||
|
|
b614ce192f | ||
|
|
416037f3f0 | ||
|
|
644a0288d7 | ||
|
|
f5145ae8ee | ||
|
|
abe8fcd90b | ||
|
|
eda919657e | ||
|
|
88bfe29365 | ||
|
|
76b0508c9e | ||
|
|
30067f46b6 | ||
|
|
799c0cfd57 | ||
|
|
2b27a86723 | ||
|
|
e230c1d4e2 | ||
|
|
c1b8544c5a | ||
|
|
278704bb91 | ||
|
|
837a3f63fb | ||
|
|
2bc008d298 | ||
|
|
5fa0c9ccfb | ||
|
|
789f68521e | ||
|
|
eabc42bf64 | ||
|
|
aef795bffa | ||
|
|
628e74da95 | ||
|
|
571ce1723c | ||
|
|
830fa56d38 | ||
|
|
b85431a4dc | ||
|
|
0d382a7dd8 | ||
|
|
6f585a2836 | ||
|
|
a4bbc65508 | ||
|
|
fa2795dd96 | ||
|
|
0477fe4b44 | ||
|
|
88a56f14ea | ||
|
|
d9b6c01ac7 | ||
|
|
d44646aa60 | ||
|
|
00eae9702a | ||
|
|
1692de6b7d | ||
|
|
fbcc556558 | ||
|
|
a44f9a1f84 | ||
|
|
a44feda52f | ||
|
|
8f119b814f | ||
|
|
ac43959c0c | ||
|
|
14487ebf05 | ||
|
|
602bf45d1b | ||
|
|
687dbaa82a | ||
|
|
d13b1d40a4 | ||
|
|
941fcad063 | ||
|
|
4bd7fa25ac | ||
|
|
da1a6420b3 | ||
|
|
036cba29c3 | ||
|
|
1a949719eb | ||
|
|
f8960eb475 | ||
|
|
85ebf42a79 | ||
|
|
bed5b4621d | ||
|
|
95137ec5b0 | ||
|
|
784467969a | ||
|
|
61730878e4 | ||
|
|
40f3445bd6 | ||
|
|
8906e5c249 | ||
|
|
d7b8ed8814 | ||
|
|
d304bcb8c7 | ||
|
|
88d4f2da0c | ||
|
|
aec8d05747 | ||
|
|
87cb368c09 | ||
|
|
29423dc85b | ||
|
|
812a7296ee | ||
|
|
ecb237ccd7 | ||
|
|
66f451b23f | ||
|
|
99303d2f95 | ||
|
|
22b31929a3 | ||
|
|
97f386e3bb | ||
|
|
5c112d8948 | ||
|
|
a332039673 | ||
|
|
e352be4f73 | ||
|
|
bec08ac617 | ||
|
|
ae40acd4f7 | ||
|
|
76b89dfb36 | ||
|
|
2cb1d7b34c | ||
|
|
f3b099d212 | ||
|
|
e9cba726a6 | ||
|
|
93bd4f2ff8 | ||
|
|
395b8564d4 | ||
|
|
231018c34c | ||
|
|
37bfe86823 | ||
|
|
7cecdb70f3 | ||
|
|
bfdeb08efe | ||
|
|
7fe25e6c46 | ||
|
|
93fb5fb85f | ||
|
|
650681bfcf | ||
|
|
50f8242b21 | ||
|
|
52c3ec8cc6 | ||
|
|
babdc4e93a | ||
|
|
8728167044 | ||
|
|
9cb9717793 | ||
|
|
08a0f80918 | ||
|
|
b06c518ee7 | ||
|
|
a243646860 | ||
|
|
4d7999cadb | ||
|
|
e63b596ff5 | ||
|
|
54a7038873 | ||
|
|
37c09c866e | ||
|
|
48aec019e7 | ||
|
|
190c273673 | ||
|
|
ea491af4d9 | ||
|
|
6b043d8622 | ||
|
|
efdaaa56b9 | ||
|
|
d79cede03a | ||
|
|
ee24389aca | ||
|
|
0299a26ebd | ||
|
|
39b477064e | ||
|
|
a7c76e1a73 | ||
|
|
43ab280e98 | ||
|
|
9ee23dabd6 | ||
|
|
d05c773be3 | ||
|
|
0a52b9189e | ||
|
|
7fc4c4ee22 | ||
|
|
3fe003b83b | ||
|
|
5af95b116f | ||
|
|
97d0ea66a0 | ||
|
|
ad44435308 | ||
|
|
0d53bb48c2 | ||
|
|
7c0a7771d2 | ||
|
|
b61be09fe2 | ||
|
|
fd5777badb | ||
|
|
9ef2bfc165 | ||
|
|
fd54e9c9d9 | ||
|
|
046aa3b993 | ||
|
|
86f2ed56e0 | ||
|
|
93814fa5b8 | ||
|
|
0c6ac337f5 | ||
|
|
9afba087bd | ||
|
|
216e977efe | ||
|
|
7ec2a1e03b | ||
|
|
4c1bfd5f61 | ||
|
|
e886dfc724 | ||
|
|
1c6e90a37d | ||
|
|
232361bd45 | ||
|
|
49c70ab8ed | ||
|
|
026647c93e | ||
|
|
4db14e71da | ||
|
|
c906a5dcee | ||
|
|
9e4a7025de | ||
|
|
0baae26168 | ||
|
|
d5d8cbded9 | ||
|
|
8e4418c1c7 | ||
|
|
dbbaf11275 | ||
|
|
40fcbc310f | ||
|
|
9eafd7d3e1 | ||
|
|
abe3885ae6 | ||
|
|
7e44247319 | ||
|
|
b0c1296ecc | ||
|
|
773442425e | ||
|
|
7180245f8c | ||
|
|
a740b63cdf | ||
|
|
88e9856a72 | ||
|
|
08cd41cd20 | ||
|
|
c25394e360 | ||
|
|
f665c52bf2 | ||
|
|
c6d2246a87 | ||
|
|
0e8c2a9325 | ||
|
|
51189281ea | ||
|
|
470d4920a6 | ||
|
|
915107e0e5 | ||
|
|
22bfb93504 | ||
|
|
cef6af6cca | ||
|
|
dac5dd3464 | ||
|
|
00b9bf6061 | ||
|
|
08dc52c653 | ||
|
|
2fbcb91417 | ||
|
|
76caa758d0 | ||
|
|
aec552a068 | ||
|
|
67b4e7ebc3 | ||
|
|
e7727a4033 | ||
|
|
a1435c7358 | ||
|
|
e2b6541e6e | ||
|
|
86ad9bbe46 | ||
|
|
df34097450 | ||
|
|
f612948ba4 | ||
|
|
4b9b8d279a | ||
|
|
c9811c6a76 | ||
|
|
29654c5f99 | ||
|
|
539d6f6581 | ||
|
|
ae6396e31b | ||
|
|
7c6bfd3471 | ||
|
|
93a72f63d1 | ||
|
|
6f3f883f75 | ||
|
|
1e3829c1d8 | ||
|
|
bae1d1004d | ||
|
|
7bb708a8c3 | ||
|
|
58019de21b | ||
|
|
e6f8817db3 | ||
|
|
b9b7ab73bb | ||
|
|
fc61ad1440 | ||
|
|
d02e5b1d37 | ||
|
|
e73d48eda3 | ||
|
|
0e9cda6547 | ||
|
|
141db9dc34 | ||
|
|
a76a3b28fd | ||
|
|
731835ef70 | ||
|
|
09c53aed19 | ||
|
|
fd3eed6bd1 | ||
|
|
82eb31e4ec | ||
|
|
d341800ec5 | ||
|
|
2860ad46af | ||
|
|
be55d23c34 | ||
|
|
388a4b0dd7 | ||
|
|
2c7fea8baf | ||
|
|
d9b246c590 | ||
|
|
ab1112ab89 | ||
|
|
d23cf986e0 | ||
|
|
91a5b5c7b3 | ||
|
|
336f9c3880 | ||
|
|
5bd4d6ee77 | ||
|
|
f705c84d4d | ||
|
|
c304d1ed27 | ||
|
|
332156b590 | ||
|
|
df527b1fd4 | ||
|
|
576a2cc643 | ||
|
|
27c0a3ef43 | ||
|
|
377032b92a | ||
|
|
37160efe9f | ||
|
|
81abd524b4 | ||
|
|
9f84439099 | ||
|
|
66c398c884 | ||
|
|
c15ec9ce8d | ||
|
|
d7ff892b8f | ||
|
|
da8d9a4b88 | ||
|
|
a1706de879 | ||
|
|
b563404324 | ||
|
|
782802136a | ||
|
|
fdfeac6ae5 | ||
|
|
a97a048d9c | ||
|
|
7c879a6546 | ||
|
|
790092f776 | ||
|
|
f0f28a397c | ||
|
|
c5515f5054 | ||
|
|
34c3fd61fb | ||
|
|
52419b8b73 | ||
|
|
6d8dc886ca | ||
|
|
8435f3c1a2 | ||
|
|
666db3dfcc | ||
|
|
29c120c9dd | ||
|
|
384209d2aa | ||
|
|
ac60654cc9 | ||
|
|
ecd88553e4 | ||
|
|
784aff8ded | ||
|
|
b812a68777 | ||
|
|
d7ddbc2c62 | ||
|
|
a50cd33b38 | ||
|
|
a5d7424fb8 | ||
|
|
59e75176fe | ||
|
|
8b4cf87368 | ||
|
|
239f6467fe | ||
|
|
9ff4ff75ff | ||
|
|
da8eb2e508 | ||
|
|
71c01670ac | ||
|
|
60b2998b65 | ||
|
|
5019b1a01f | ||
|
|
027f754209 | ||
|
|
b779042694 | ||
|
|
610f9b94e7 | ||
|
|
a549c0e6df | ||
|
|
5cd81ddebb | ||
|
|
0d8febc902 | ||
|
|
9bb7821553 | ||
|
|
7b5a64f434 | ||
|
|
198a2908d2 | ||
|
|
82cb106051 | ||
|
|
dd00296c0a | ||
|
|
f43f496241 | ||
|
|
833e149921 | ||
|
|
b238874ddb | ||
|
|
637d77fdcb | ||
|
|
c2bf923e3e | ||
|
|
cdb6e7c6c6 | ||
|
|
74b87026ca | ||
|
|
8f714a9fa9 | ||
|
|
8f08296e7b | ||
|
|
344e738c48 | ||
|
|
859109c378 | ||
|
|
ffaf01c637 | ||
|
|
c3ac4a623a | ||
|
|
87c958638d | ||
|
|
014b2f1d1f | ||
|
|
6930f76f2f | ||
|
|
60972cd0ba | ||
|
|
e0fbac66d1 | ||
|
|
d339a250fe | ||
|
|
6d8aebb411 | ||
|
|
c2da6512e4 | ||
|
|
cfb1278c7e | ||
|
|
1f2b5b6d29 | ||
|
|
c14634dafa | ||
|
|
862bb43d93 | ||
|
|
2f6a1d4e76 | ||
|
|
a7437a3ada | ||
|
|
30eb32f888 | ||
|
|
75f9c47e2b | ||
|
|
86144aa54a | ||
|
|
a574aa2c9f | ||
|
|
243e5c01fa | ||
|
|
5b5b6fd785 | ||
|
|
198538df4f | ||
|
|
96a1b68221 | ||
|
|
ba2f2fc455 | ||
|
|
28f9f32d91 | ||
|
|
3762f90ada | ||
|
|
e0abb02df0 | ||
|
|
486f983d4b | ||
|
|
20856b1589 | ||
|
|
b15f5538e1 | ||
|
|
d2e6df4dde | ||
|
|
d97b3f344d | ||
|
|
9c6f10cc1c | ||
|
|
e442979ff2 | ||
|
|
96bd7cc044 | ||
|
|
ddcc5921b9 | ||
|
|
7bfc960f9b | ||
|
|
bd2fbe605c | ||
|
|
cee79dc0cc | ||
|
|
3b44c785ca | ||
|
|
6fa0c226b0 | ||
|
|
d1e59b1d7b | ||
|
|
74ec57b931 | ||
|
|
e9c9b785c4 | ||
|
|
0c493dff14 | ||
|
|
13447a5f24 | ||
|
|
03fa9f9fb7 | ||
|
|
4c71139055 | ||
|
|
24fc48ad85 | ||
|
|
cf76d98546 | ||
|
|
e2835ec85c | ||
|
|
2812f007a1 | ||
|
|
f77c886e51 | ||
|
|
7e83a1074e | ||
|
|
6fa16ebb7e | ||
|
|
0c9a2d2c5d | ||
|
|
0ec1cc3823 | ||
|
|
64c7804611 | ||
|
|
4c8a81e2d3 | ||
|
|
7a11022b42 | ||
|
|
0f53854c91 | ||
|
|
d59f975715 | ||
|
|
60fdd18e41 | ||
|
|
b0eac5ffc3 | ||
|
|
d5ad65b93b | ||
|
|
a36d15b4e6 | ||
|
|
e6bbd5335d | ||
|
|
aa441f8212 | ||
|
|
5d86387e8e | ||
|
|
e1bd1b6f55 | ||
|
|
bd4f25df15 | ||
|
|
690b41f8d6 | ||
|
|
e9185784a7 | ||
|
|
2aff8ce165 | ||
|
|
d2d3429183 | ||
|
|
54d836ba07 | ||
|
|
f16fd37b61 | ||
|
|
4fad1c3305 | ||
|
|
f8d94be59d | ||
|
|
d41195c6a0 | ||
|
|
12487ccbca | ||
|
|
9c2bd2afae | ||
|
|
da1232d615 | ||
|
|
595c9108fd | ||
|
|
ef008c31cb | ||
|
|
eecf7c7751 | ||
|
|
24bf20b9d7 | ||
|
|
2abe2ceb99 | ||
|
|
65626120df | ||
|
|
0b69f778cf | ||
|
|
5e97ba1e71 | ||
|
|
ba550c7f03 | ||
|
|
9dc07de628 | ||
|
|
4aee439590 | ||
|
|
c5def4a5ec | ||
|
|
331fd3fe17 | ||
|
|
e2e7e4bb49 | ||
|
|
ac65a6db76 | ||
|
|
bccc228fa0 | ||
|
|
96177c8531 | ||
|
|
fb54b4f1dc | ||
|
|
1b7eea2fc2 | ||
|
|
f2e5dba492 | ||
|
|
48df2e026d | ||
|
|
a2ac5ab994 | ||
|
|
d1bb4ef185 | ||
|
|
d267988348 | ||
|
|
1778696c0b | ||
|
|
9accfba904 | ||
|
|
191fceb191 | ||
|
|
2df869c4cb | ||
|
|
abcaeb08a4 | ||
|
|
8e227d7f3e | ||
|
|
45f93f7b69 | ||
|
|
7531cf8168 | ||
|
|
65293a7402 | ||
|
|
ea19bd901a | ||
|
|
dd8d35aec6 | ||
|
|
53a35e0f1c | ||
|
|
5c7d4e982b | ||
|
|
6f2f9469b1 | ||
|
|
d7d409582f | ||
|
|
79d50b3f32 | ||
|
|
2b0702c2dd | ||
|
|
0822f6d076 | ||
|
|
b8aa5fa974 | ||
|
|
adc6c032c7 | ||
|
|
490161d649 | ||
|
|
085a0fc33d | ||
|
|
e12aa94320 | ||
|
|
4b02dad51f | ||
|
|
de2782cfda | ||
|
|
9b18be1333 | ||
|
|
2ef64bebcb | ||
|
|
930360002b | ||
|
|
c12583d39e | ||
|
|
fd719be2a2 | ||
|
|
6c6a619c73 | ||
|
|
fbe2303ede | ||
|
|
2d5fcfb41b | ||
|
|
2b3d43273a | ||
|
|
7cdd5d4d1b | ||
|
|
76b740786a | ||
|
|
615987366f | ||
|
|
f42d681f85 | ||
|
|
c2773615ce | ||
|
|
4439b9a6de | ||
|
|
383308cd73 | ||
|
|
8f9207f4fc | ||
|
|
87508db11e | ||
|
|
94fb991c14 | ||
|
|
304325ac02 | ||
|
|
739929df22 | ||
|
|
b74c66261f | ||
|
|
6f99146f5b | ||
|
|
0afa9f8123 | ||
|
|
94178eb68d | ||
|
|
1c070ab58b | ||
|
|
24130cf716 | ||
|
|
34ce26e67b | ||
|
|
9520f67fb7 | ||
|
|
2eb1469bf7 | ||
|
|
749525ba51 | ||
|
|
12115ca946 | ||
|
|
27860d8c11 | ||
|
|
240d6ede75 | ||
|
|
40e0e52e6b | ||
|
|
dbaa5cd115 | ||
|
|
080d68c169 | ||
|
|
90c411f554 | ||
|
|
22caf75653 | ||
|
|
7bd07b53fc | ||
|
|
9bbd99bcd9 | ||
|
|
7c4a458dbb | ||
|
|
5563d2e747 | ||
|
|
28ebcfa2d8 | ||
|
|
e901f3d914 | ||
|
|
ec1f97379e | ||
|
|
2fe94bb9fa | ||
|
|
9a4a3a87fe | ||
|
|
176d577142 | ||
|
|
9dda1d9035 | ||
|
|
9ee65cad7f | ||
|
|
d8b8dee509 | ||
|
|
c1d7acb6e3 | ||
|
|
de8c690934 | ||
|
|
b81c8be616 | ||
|
|
ed58ed667e | ||
|
|
7a94f7679b | ||
|
|
bb09910ae7 | ||
|
|
61fdfaa2db | ||
|
|
571002660b | ||
|
|
3094a940e1 | ||
|
|
1cc1f8f819 | ||
|
|
58f027db60 | ||
|
|
2d95824535 | ||
|
|
e3aab5c0f9 | ||
|
|
93b56a5bcc | ||
|
|
c24a3f935e | ||
|
|
e0e95af092 | ||
|
|
5b43299c41 | ||
|
|
af441349ad | ||
|
|
469f8ebdcb | ||
|
|
6a8e08db38 | ||
|
|
82baf564c6 | ||
|
|
08d68e7993 | ||
|
|
c2d7ce94b1 | ||
|
|
db0c5be74f | ||
|
|
16196a3260 | ||
|
|
f96725de55 | ||
|
|
235f77ec70 | ||
|
|
e3a173a2cd | ||
|
|
fb0070a4ea | ||
|
|
db13cd1702 | ||
|
|
15156b326b | ||
|
|
80488d0f96 | ||
|
|
a65031dab5 | ||
|
|
35a4a60d42 | ||
|
|
b3bcb274a0 | ||
|
|
895a5c7e76 | ||
|
|
1792599411 | ||
|
|
7e3e3af503 | ||
|
|
c771177666 | ||
|
|
3d5fa93be0 | ||
|
|
a4da16d8a1 | ||
|
|
09eb1b20de | ||
|
|
fac274c9c2 | ||
|
|
9333f3c0b7 | ||
|
|
5b349cb010 | ||
|
|
80e236723b | ||
|
|
675e1d3df7 | ||
|
|
ce0082ee3f | ||
|
|
1c2a89e3e8 | ||
|
|
ccc26f9566 | ||
|
|
98c387fbd0 | ||
|
|
4d8460ad8a | ||
|
|
01b6ff168e | ||
|
|
83fd8ab5cf | ||
|
|
ed517b24f3 | ||
|
|
e89959b71b | ||
|
|
2ee59df866 | ||
|
|
8e829612af | ||
|
|
738e304545 | ||
|
|
a697b74157 | ||
|
|
da48d2c28a | ||
|
|
520d6cc3af | ||
|
|
97ae34a06d | ||
|
|
007b8c10ab | ||
|
|
5adffd4e75 | ||
|
|
6a7ca922f0 | ||
|
|
71a3e16a01 | ||
|
|
9bcf7574bf | ||
|
|
0d40316305 | ||
|
|
34ebf6a263 | ||
|
|
c8129b1f5f | ||
|
|
a7b7195370 | ||
|
|
b6fcf977e5 | ||
|
|
e3505d05ec | ||
|
|
ea49395c23 | ||
|
|
0050fe4eef | ||
|
|
085d32e214 | ||
|
|
c5bce945c4 | ||
|
|
83a6f7e072 | ||
|
|
a5b88d3683 | ||
|
|
5dbceb5584 | ||
|
|
95cf290e2c | ||
|
|
021c75c665 | ||
|
|
a5280870c2 | ||
|
|
0717f346b0 | ||
|
|
afac6e7667 | ||
|
|
41facf623a | ||
|
|
8425cd6f7e | ||
|
|
ebd5016990 | ||
|
|
1d23735344 | ||
|
|
50ad0d9bf6 | ||
|
|
55a6720a84 | ||
|
|
0ff0892b25 | ||
|
|
38426ed32f | ||
|
|
6cbe1301ca | ||
|
|
ffc71ea8b3 | ||
|
|
663a5d5b3b | ||
|
|
1a117c7fb7 | ||
|
|
af49370870 | ||
|
|
8ff1997dda | ||
|
|
9f22085eef | ||
|
|
2b123799de | ||
|
|
892a7f77ae | ||
|
|
ef33a780e0 | ||
|
|
9bcdb01b79 | ||
|
|
c3f337898d | ||
|
|
cb23f94cdf | ||
|
|
fa1ee6fec0 | ||
|
|
04cad6365c | ||
|
|
0870d8228b | ||
|
|
a6f6637789 | ||
|
|
3c83334e30 | ||
|
|
22f009d0f7 | ||
|
|
3e6632dfdc | ||
|
|
eaf0293dcf | ||
|
|
5d02ed4d08 | ||
|
|
4b457aa567 | ||
|
|
6823122793 | ||
|
|
d5ddd22861 | ||
|
|
8d4ce81c34 | ||
|
|
895702cb53 | ||
|
|
6fd0854ac5 | ||
|
|
28a3e209ab | ||
|
|
dcf568ead5 | ||
|
|
7ccab82fd4 | ||
|
|
568611927b | ||
|
|
d028f54c27 | ||
|
|
4a3cdc3a5c | ||
|
|
e2e9c074b7 | ||
|
|
a3822a1836 | ||
|
|
89aeb8ad7c | ||
|
|
ffb5fc8286 | ||
|
|
8c8befabdd | ||
|
|
94ec7ca47f | ||
|
|
bc1d4cbb46 | ||
|
|
a359a171d3 | ||
|
|
b513730978 | ||
|
|
40d76b3476 | ||
|
|
11ca6772ef | ||
|
|
60edd51464 | ||
|
|
be332192e4 | ||
|
|
d6af3c629a | ||
|
|
878d6fa0c1 | ||
|
|
fb48221db5 | ||
|
|
503c7c7594 | ||
|
|
0ff1843545 | ||
|
|
19b3553705 | ||
|
|
a234c76326 | ||
|
|
b7e582928a | ||
|
|
482b9fe9e9 | ||
|
|
9731b2f1dc | ||
|
|
1d7f50478c | ||
|
|
fe27445e9e | ||
|
|
a5ac14ea3f | ||
|
|
460e0b3a26 | ||
|
|
bf981a1e8f | ||
|
|
70cb939611 | ||
|
|
c2a0ceb22e | ||
|
|
d1cf15b3eb | ||
|
|
b849352b3a | ||
|
|
0e060aec46 | ||
|
|
29c3746163 | ||
|
|
8650e9acb5 | ||
|
|
2998fe0611 | ||
|
|
7f57336d86 | ||
|
|
ef54f946a8 | ||
|
|
5651b3b4df | ||
|
|
d8be649107 | ||
|
|
4b984cd600 | ||
|
|
c9dcda3a5c | ||
|
|
11a9d87701 | ||
|
|
4e8676882f | ||
|
|
f29fd24c53 | ||
|
|
55709c3cdf | ||
|
|
92604246c2 | ||
|
|
fd81ba7a6d | ||
|
|
b37b006918 | ||
|
|
406d0fd183 | ||
|
|
7cd651638a | ||
|
|
ab9dee0a56 | ||
|
|
2d3f8fafe9 | ||
|
|
5d8235aebf | ||
|
|
93a6aae9c2 | ||
|
|
631c41c4a2 |
10
.coveragerc
10
.coveragerc
@@ -1,10 +0,0 @@
|
||||
[run]
|
||||
source=
|
||||
mayan
|
||||
omit=
|
||||
mayan/bin/mayan-edms.py
|
||||
mayan/wsgi.py
|
||||
mayan/settings/*
|
||||
tests.py
|
||||
mayan/apps/*/tests/*
|
||||
*migrations*
|
||||
@@ -1,10 +0,0 @@
|
||||
.git
|
||||
.gitignore
|
||||
HISTORY.md
|
||||
mayan/media
|
||||
db.sqlite*
|
||||
docker
|
||||
!docker/rootfs
|
||||
./.*
|
||||
docs
|
||||
|
||||
3
.flake8
3
.flake8
@@ -1,3 +0,0 @@
|
||||
[flake8]
|
||||
exclude = node_modules,static,templates
|
||||
ignore = E501, N801, N802, N804, N805, N806
|
||||
38
.gitignore
vendored
38
.gitignore
vendored
@@ -1,35 +1,17 @@
|
||||
*.orig
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.sql
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
*egg-info*
|
||||
.coverage
|
||||
.coverage.tox*
|
||||
.idea/
|
||||
*.swp
|
||||
.tox/
|
||||
.vagrant
|
||||
_build/
|
||||
/build/
|
||||
coverage.xml
|
||||
document_storage/
|
||||
gpg_home/
|
||||
htmlcov/
|
||||
mayan/media/
|
||||
mayan/media/document_cache/
|
||||
mayan/settings/local.py
|
||||
mayan/error.log
|
||||
settings_local.py
|
||||
static_collected/
|
||||
/settings_local.py
|
||||
/celerybeat-schedule
|
||||
/fabfile_install
|
||||
/dist/
|
||||
/document_storage/
|
||||
/misc/mayan.geany
|
||||
/mayan/media/static/
|
||||
/venv/
|
||||
/venv3/
|
||||
/image_cache/
|
||||
build/
|
||||
_build/
|
||||
/gpg_home/
|
||||
/static/
|
||||
/whoosh_index/
|
||||
google_fonts/
|
||||
node_modules/
|
||||
docs/build/
|
||||
/fabfile_install
|
||||
/server_config.yaml
|
||||
|
||||
231
.gitlab-ci.yml
231
.gitlab-ci.yml
@@ -1,231 +0,0 @@
|
||||
stages:
|
||||
- test
|
||||
- build_python
|
||||
- build_docker
|
||||
- build_documentation
|
||||
- push_python
|
||||
- push_docker
|
||||
- push_documentation
|
||||
- deploy
|
||||
|
||||
job_docker_build:
|
||||
stage: build_docker
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||
script:
|
||||
- docker build --pull -t "$CI_REGISTRY_IMAGE" -f docker/Dockerfile .
|
||||
- VERSION=`cat docker/rootfs/version`
|
||||
- docker tag "$CI_REGISTRY_IMAGE" "$CI_REGISTRY_IMAGE:$VERSION"
|
||||
- docker run --rm "$CI_REGISTRY_IMAGE:$VERSION" run_tests
|
||||
- docker push "$CI_REGISTRY_IMAGE:$VERSION"
|
||||
- docker push "$CI_REGISTRY_IMAGE:latest"
|
||||
- docker tag "$CI_REGISTRY_IMAGE:$VERSION" registry-1.docker.io/mayanedms/mayanedms:"$VERSION"
|
||||
- docker tag "$CI_REGISTRY_IMAGE:$VERSION" registry-1.docker.io/mayanedms/mayanedms:latest
|
||||
- docker logout
|
||||
only:
|
||||
- releases/all
|
||||
- releases/docker
|
||||
|
||||
job_docker_push:
|
||||
stage: push_docker
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||
script:
|
||||
- VERSION=`cat docker/rootfs/version`
|
||||
- docker pull "$CI_REGISTRY_IMAGE:$VERSION"
|
||||
- docker tag "$CI_REGISTRY_IMAGE:$VERSION" registry-1.docker.io/mayanedms/mayanedms:"$VERSION"
|
||||
- docker tag "$CI_REGISTRY_IMAGE:$VERSION" registry-1.docker.io/mayanedms/mayanedms:latest
|
||||
- docker logout
|
||||
- docker login -u "$DOCKER_HUB_USERNAME" -p "$DOCKER_HUB_PASSWORD" https://registry-1.docker.io
|
||||
- docker push registry-1.docker.io/mayanedms/mayanedms:"$VERSION"
|
||||
- docker push registry-1.docker.io/mayanedms/mayanedms:latest
|
||||
only:
|
||||
- releases/all
|
||||
- releases/docker
|
||||
|
||||
job_docker_nightly:
|
||||
stage: build_docker
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||
script:
|
||||
- docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" -f docker/Dockerfile .
|
||||
- docker run --rm "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" run_tests
|
||||
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
|
||||
only:
|
||||
- nightly
|
||||
- staging
|
||||
|
||||
job_documentation_build:
|
||||
stage: build_documentation
|
||||
image: ubuntu:18.04
|
||||
artifacts:
|
||||
expire_in: 1 hr
|
||||
paths:
|
||||
- docs
|
||||
before_script:
|
||||
- apt-get -qq update
|
||||
- apt-get install -qq locales make python-pip enchant
|
||||
- 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
|
||||
script:
|
||||
- pip install -r requirements/documentation.txt
|
||||
- cd docs
|
||||
- make html
|
||||
only:
|
||||
- releases/all
|
||||
- releases/documentation
|
||||
|
||||
job_documentation_push:
|
||||
stage: push_documentation
|
||||
image: ubuntu:18.04
|
||||
before_script:
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
- echo "$DOCUMENTATION_SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client rsync -y )'
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$DOCUMENTATION_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
|
||||
script:
|
||||
- rsync -avzP --progress -e ssh docs/_build/html/* mayandocs@docs.mayan-edms.com:/home/rosarior/webapps/mayan_docs
|
||||
only:
|
||||
- releases/all
|
||||
- releases/documentation
|
||||
|
||||
job_build_python:
|
||||
stage: build_python
|
||||
image: ubuntu:18.04
|
||||
artifacts:
|
||||
expire_in: 1 hr
|
||||
paths:
|
||||
- dist
|
||||
before_script:
|
||||
- apt-get -qq update
|
||||
- apt-get install -qq locales make python-pip
|
||||
script:
|
||||
- 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
|
||||
- pip install -r requirements/build.txt
|
||||
- make python-wheel
|
||||
only:
|
||||
- releases/all
|
||||
- releases/python
|
||||
|
||||
job_push_python:
|
||||
stage: push_python
|
||||
image: ubuntu:18.04
|
||||
before_script:
|
||||
- apt-get -qq update
|
||||
- apt-get install -qq python-pip
|
||||
script:
|
||||
- pip install -r requirements/build.txt
|
||||
- echo "$PYPIRC" > ~/.pypirc
|
||||
- twine upload dist/* -r pypi
|
||||
only:
|
||||
- releases/all
|
||||
- releases/python
|
||||
|
||||
.test_base: &test_base
|
||||
stage: test
|
||||
image: ubuntu:18.04
|
||||
cache:
|
||||
paths:
|
||||
- ~/.cache/pip/
|
||||
- /var/cache/apt/archives/
|
||||
before_script:
|
||||
- apt-get -qq update
|
||||
- apt-get install -qq locales
|
||||
- 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
|
||||
- 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-virtualenv python3-dev tesseract-ocr tesseract-ocr-deu
|
||||
- virtualenv venv -p /usr/bin/python3
|
||||
- . venv/bin/activate
|
||||
- pip install -r requirements.txt -r requirements/testing-base.txt
|
||||
only:
|
||||
- releases/all
|
||||
- releases/docker
|
||||
- releases/python
|
||||
- staging
|
||||
- nightly
|
||||
|
||||
test-mysql:
|
||||
<<: *test_base
|
||||
variables:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: "mayan_edms"
|
||||
services:
|
||||
- mysql:8.0.3
|
||||
script:
|
||||
- apt-get install -qq libmysqlclient-dev mysql-client
|
||||
- . venv/bin/activate
|
||||
- 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:
|
||||
- mysql
|
||||
|
||||
test-postgres:
|
||||
<<: *test_base
|
||||
variables:
|
||||
POSTGRES_DB: "mayan_edms"
|
||||
POSTGRES_PASSWORD: "postgres"
|
||||
services:
|
||||
- postgres
|
||||
script:
|
||||
- apt-get install -qq libpq-dev
|
||||
- . venv/bin/activate
|
||||
- pip install psycopg2
|
||||
- python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci.db_postgres --nomigrations
|
||||
tags:
|
||||
- postgres
|
||||
|
||||
test-sqlite:
|
||||
<<: *test_base
|
||||
script:
|
||||
- . venv/bin/activate
|
||||
- python manage.py test --mayan-apps --settings=mayan.settings.testing.gitlab-ci --nomigrations
|
||||
|
||||
deploy_demo:
|
||||
environment:
|
||||
name: demo
|
||||
stage: deploy
|
||||
before_script:
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "${DEMO_SSH_KNOWN_HOST}" > ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- echo "${DEMO_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
script:
|
||||
- scp contrib/scripts/install/docker.sh root@$DEMO_IP_ADDRESS:~
|
||||
- ssh root@$DEMO_IP_ADDRESS "DELETE_VOLUMES=true ./docker.sh"
|
||||
when: manual
|
||||
|
||||
deploy_staging:
|
||||
environment:
|
||||
name: staging
|
||||
stage: deploy
|
||||
before_script:
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "${STAGING_SSH_KNOWN_HOST}" > ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- echo "${STAGING_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
script:
|
||||
- scp contrib/scripts/install/docker.sh root@$STAGING_IP_ADDRESS:~
|
||||
- ssh root@$STAGING_IP_ADDRESS "DOCKER_MAYAN_IMAGE=registry.gitlab.com/mayan-edms/mayan-edms:staging ./docker.sh"
|
||||
when: manual
|
||||
21
.magnum.yml
21
.magnum.yml
@@ -1,21 +0,0 @@
|
||||
language: python
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-dev gcc tesseract-ocr tesseract-ocr-deu unpaper ghostscript libjpeg-dev libpng-dev poppler-utils
|
||||
install:
|
||||
- pip install -r requirements/testing.txt
|
||||
- pip install -q mysql-python
|
||||
- pip install -q psycopg2
|
||||
before_script:
|
||||
- mysql -u root -e 'create database mayan_edms;'
|
||||
- psql -c 'create database mayan_edms;' -U postgres
|
||||
script:
|
||||
- export TEST_APPS="acls authentication django_gpg document_indexing document_signatures documents dynamic_search folders lock_manager ocr permissions sources tags"
|
||||
- coverage run manage.py test $TEST_APPS --settings=mayan.settings.testing.base
|
||||
- coverage run manage.py test $TEST_APPS --settings=mayan.settings.magnum.db_mysql
|
||||
- coverage run manage.py test $TEST_APPS --settings=mayan.settings.magnum.db_postgres
|
||||
after_script:
|
||||
- coveralls
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
36
.travis.yml
36
.travis.yml
@@ -1,36 +0,0 @@
|
||||
dist: trusty
|
||||
sudo: required
|
||||
language: python
|
||||
python:
|
||||
- 2.7
|
||||
env:
|
||||
matrix:
|
||||
- DB=mysql
|
||||
- DB=postgres
|
||||
- DB=sqlite
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-dev python-pip gcc tesseract-ocr tesseract-ocr-deu ghostscript libjpeg-dev libpng-dev libtiff-dev poppler-utils libreoffice
|
||||
install:
|
||||
- "pip install -r requirements/testing.txt"
|
||||
- if [[ $DB == mysql ]]; then pip install -q mysql-python; fi
|
||||
- if [[ $DB == postgres ]]; then pip install -q psycopg2; fi
|
||||
before_script:
|
||||
- mysql -e 'create database mayan_edms;'
|
||||
- psql -c 'create database mayan_edms;' -U postgres
|
||||
script:
|
||||
- if [[ $DB == mysql ]]; then coverage run manage.py test --mayan-apps --settings=mayan.settings.testing.travis.db_mysql --nomigrations; fi
|
||||
- if [[ $DB == postgres ]]; then coverage run manage.py test --mayan-apps --settings=mayan.settings.testing.travis.db_postgres --nomigrations; fi
|
||||
- if [[ $DB == sqlite ]]; then coverage run manage.py test --mayan-apps --settings=mayan.settings.testing.base --nomigrations; fi
|
||||
after_success:
|
||||
- coveralls
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- development
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- roberto.rosario@mayan-edms.com
|
||||
on_success: never
|
||||
on_failure: always
|
||||
237
.tx/config
237
.tx/config
@@ -1,237 +1,218 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
host = https://www.transifex.net
|
||||
|
||||
[mayan-edms.acls-2-0]
|
||||
file_filter = mayan/apps/acls/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-acls]
|
||||
file_filter = apps/acls/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/acls/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/acls/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.appearance-2-0]
|
||||
file_filter = mayan/apps/appearance/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-bootstrap]
|
||||
file_filter = apps/bootstrap/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/appearance/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/bootstrap/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.authentication-2-0]
|
||||
file_filter = mayan/apps/authentication/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-converter]
|
||||
file_filter = apps/converter/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/authentication/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/converter/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.autoadmin-2-0]
|
||||
file_filter = mayan/apps/autoadmin/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-common]
|
||||
file_filter = apps/common/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/autoadmin/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/common/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.cabinets-2-0]
|
||||
file_filter = mayan/apps/cabinets/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-checkouts]
|
||||
file_filter = apps/checkouts/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/cabinets/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/checkouts/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.checkouts-2-0]
|
||||
file_filter = mayan/apps/checkouts/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-clustering]
|
||||
file_filter = apps/clustering/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/checkouts/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/clustering/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.common-2-0]
|
||||
file_filter = mayan/apps/common/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-django_gpg]
|
||||
file_filter = apps/django_gpg/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/common/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/django_gpg/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.converter-2-0]
|
||||
file_filter = mayan/apps/converter/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-diagnostics]
|
||||
file_filter = apps/diagnostics/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/converter/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/diagnostics/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.dashboards-2-0]
|
||||
file_filter = mayan/apps/dashboards/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-documents]
|
||||
file_filter = apps/documents/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/dashboards/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/documents/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.dependencies-3-0]
|
||||
file_filter = mayan/apps/dependencies/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-document_comments]
|
||||
file_filter = apps/document_comments/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/dependencies/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/document_comments/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
|
||||
[mayan-edms.apps-document_indexing]
|
||||
file_filter = apps/document_indexing/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/django_gpg/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/document_indexing/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
|
||||
[mayan-edms.apps-document_signatures]
|
||||
file_filter = apps/document_signatures/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_comments/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/document_signatures/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.document_indexing-2-0]
|
||||
file_filter = mayan/apps/document_indexing/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-dynamic_search]
|
||||
file_filter = apps/dynamic_search/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_indexing/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/dynamic_search/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.document_parsing-2-0]
|
||||
file_filter = mayan/apps/document_parsing/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-folders]
|
||||
file_filter = apps/folders/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_parsing/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/folders/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.document_signatures-2-0]
|
||||
file_filter = mayan/apps/document_signatures/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-history]
|
||||
file_filter = apps/history/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_signatures/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/history/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.document_states-2-0]
|
||||
file_filter = mayan/apps/document_states/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-installation]
|
||||
file_filter = apps/installation/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/document_states/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/installation/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.documents-2-0]
|
||||
file_filter = mayan/apps/documents/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-job_processor]
|
||||
file_filter = apps/job_processor/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/documents/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/job_processor/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
|
||||
[mayan-edms.apps-linking]
|
||||
file_filter = apps/linking/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/dynamic_search/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/linking/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.events-2-0]
|
||||
file_filter = mayan/apps/events/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-lock_manager]
|
||||
file_filter = apps/lock_manager/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/events/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/lock_manager/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.file_caching-3-0]
|
||||
file_filter = mayan/apps/file_caching/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-main]
|
||||
file_filter = apps/main/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/file_caching/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/main/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.file_metadata-3-0]
|
||||
file_filter = mayan/apps/file_metadata/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-maintenance]
|
||||
file_filter = apps/maintenance/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/file_metadata/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/maintenance/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.linking-2-0]
|
||||
file_filter = mayan/apps/linking/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-metadata]
|
||||
file_filter = apps/metadata/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/linking/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/metadata/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.lock_manager-2-0]
|
||||
file_filter = mayan/apps/lock_manager/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-navigation]
|
||||
file_filter = apps/navigation/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/lock_manager/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/navigation/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.mailer-2-0]
|
||||
file_filter = mayan/apps/mailer/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-ocr]
|
||||
file_filter = apps/ocr/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/mailer/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/ocr/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.metadata-2-0]
|
||||
file_filter = mayan/apps/metadata/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-permissions]
|
||||
file_filter = apps/permissions/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/metadata/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/permissions/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.mirroring-2-0]
|
||||
file_filter = mayan/apps/mirroring/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-project_setup]
|
||||
file_filter = apps/project_setup/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/mirroring/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/project_setup/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.motd-2-0]
|
||||
file_filter = mayan/apps/motd/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-project_tools]
|
||||
file_filter = apps/project_tools/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/motd/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/project_tools/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.ocr-2-0]
|
||||
file_filter = mayan/apps/ocr/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-registration]
|
||||
file_filter = apps/registration/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/ocr/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/registration/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.permissions-2-0]
|
||||
file_filter = mayan/apps/permissions/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-scheduler]
|
||||
file_filter = apps/scheduler/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/permissions/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/scheduler/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.platform-2-0]
|
||||
file_filter = mayan/apps/platform/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-smart_settings]
|
||||
file_filter = apps/smart_settings/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/platform/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/smart_settings/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
|
||||
[mayan-edms.apps-sources]
|
||||
file_filter = apps/sources/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/rest_api/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/sources/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.smart_settings-2-0]
|
||||
file_filter = mayan/apps/smart_settings/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-statistics]
|
||||
file_filter = apps/statistics/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/smart_settings/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/statistics/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.sources-2-0]
|
||||
file_filter = mayan/apps/sources/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-tags]
|
||||
file_filter = apps/tags/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/sources/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/tags/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.statistics-2-0]
|
||||
file_filter = mayan/apps/mayan_statistics/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-trash]
|
||||
file_filter = apps/trash/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/mayan_statistics/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/trash/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.storage-2-0]
|
||||
file_filter = mayan/apps/storage/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-user_management]
|
||||
file_filter = apps/user_management/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/storage/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/user_management/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.tags-2-0]
|
||||
file_filter = mayan/apps/tags/locale/<lang>/LC_MESSAGES/django.po
|
||||
[mayan-edms.apps-web_theme]
|
||||
file_filter = apps/web_theme/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/tags/locale/en/LC_MESSAGES/django.po
|
||||
source_file = apps/web_theme/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.task_manager-2-0]
|
||||
file_filter = mayan/apps/task_manager/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/task_manager/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.user_management-2-0]
|
||||
file_filter = mayan/apps/user_management/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/user_management/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
[mayan-edms.weblink-3-0]
|
||||
file_filter = mayan/apps/weblinks/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
source_file = mayan/apps/weblinks/locale/en/LC_MESSAGES/django.po
|
||||
type = PO
|
||||
|
||||
|
||||
43
3rd_party_apps/filetransfers/api.py
Normal file
43
3rd_party_apps/filetransfers/api.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from django.conf import settings
|
||||
from django.utils.importlib import import_module
|
||||
import mimetypes
|
||||
|
||||
PREPARE_UPLOAD_BACKEND = getattr(settings,
|
||||
'PREPARE_UPLOAD_BACKEND',
|
||||
'filetransfers.backends.default.prepare_upload')
|
||||
SERVE_FILE_BACKEND = getattr(settings,
|
||||
'SERVE_FILE_BACKEND',
|
||||
'filetransfers.backends.default.serve_file')
|
||||
PUBLIC_DOWNLOAD_URL_BACKEND = getattr(settings,
|
||||
'PUBLIC_DOWNLOAD_URL_BACKEND',
|
||||
'filetransfers.backends.default.public_download_url')
|
||||
|
||||
_backends_cache = {}
|
||||
|
||||
# Public API
|
||||
def prepare_upload(request, url, private=False, backend=None):
|
||||
handler = _load_backend(backend, PREPARE_UPLOAD_BACKEND)
|
||||
return handler(request, url, private=private)
|
||||
|
||||
def serve_file(request, file, backend=None, save_as=False, content_type=None):
|
||||
# Backends are responsible for handling range requests.
|
||||
handler = _load_backend(backend, SERVE_FILE_BACKEND)
|
||||
filename = file.name.rsplit('/')[-1]
|
||||
if save_as is True:
|
||||
save_as = filename
|
||||
if not content_type:
|
||||
content_type = mimetypes.guess_type(filename)[0]
|
||||
return handler(request, file, save_as=save_as, content_type=content_type)
|
||||
|
||||
def public_download_url(file, backend=None):
|
||||
handler = _load_backend(backend, PUBLIC_DOWNLOAD_URL_BACKEND)
|
||||
return handler(file)
|
||||
|
||||
# Internal utilities
|
||||
def _load_backend(backend, default_backend):
|
||||
if backend is None:
|
||||
backend = default_backend
|
||||
if backend not in _backends_cache:
|
||||
module_name, func_name = backend.rsplit('.', 1)
|
||||
_backends_cache[backend] = getattr(import_module(module_name), func_name)
|
||||
return _backends_cache[backend]
|
||||
7
3rd_party_apps/filetransfers/backends/base_url.py
Normal file
7
3rd_party_apps/filetransfers/backends/base_url.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.conf import settings
|
||||
|
||||
def public_download_url(file, **kwargs):
|
||||
"""
|
||||
Directs downloads to a handler at settings.PUBLIC_DOWNLOADS_URL_BASE
|
||||
"""
|
||||
return settings.PUBLIC_DOWNLOADS_URL_BASE + file.name
|
||||
30
3rd_party_apps/filetransfers/backends/default.py
Normal file
30
3rd_party_apps/filetransfers/backends/default.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from django.http import HttpResponse
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
def prepare_upload(request, url, **kwargs):
|
||||
"""Directly uploads to the given URL"""
|
||||
return url, {}
|
||||
|
||||
def serve_file(request, file, save_as, content_type, **kwargs):
|
||||
"""
|
||||
Serves the file in chunks for efficiency reasons, but the transfer still
|
||||
goes through Django itself, so it's much worse than using the web server,
|
||||
but at least it works with all configurations.
|
||||
"""
|
||||
response = HttpResponse(ChunkedFile(file), content_type=content_type)
|
||||
if save_as:
|
||||
response['Content-Disposition'] = smart_str(u'attachment; filename=%s' % save_as)
|
||||
if file.size is not None:
|
||||
response['Content-Length'] = file.size
|
||||
return response
|
||||
|
||||
def public_download_url(file, **kwargs):
|
||||
"""No public download URL"""
|
||||
return None
|
||||
|
||||
class ChunkedFile(object):
|
||||
def __init__(self, file):
|
||||
self.file = file
|
||||
|
||||
def __iter__(self):
|
||||
return self.file.chunks()
|
||||
11
3rd_party_apps/filetransfers/backends/delegate.py
Normal file
11
3rd_party_apps/filetransfers/backends/delegate.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from django.conf import settings
|
||||
|
||||
from filetransfers.api import prepare_upload as delegate
|
||||
|
||||
def prepare_upload(*args, **kwargs):
|
||||
"""Delegates uploads to other backends based on private=False or True"""
|
||||
if kwargs['private']:
|
||||
kwargs['backend'] = settings.PRIVATE_PREPARE_UPLOAD_BACKEND
|
||||
else:
|
||||
kwargs['backend'] = settings.PUBLIC_PREPARE_UPLOAD_BACKEND
|
||||
return delegate(*args, **kwargs)
|
||||
10
3rd_party_apps/filetransfers/backends/url.py
Normal file
10
3rd_party_apps/filetransfers/backends/url.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
def serve_file(request, file, **kwargs):
|
||||
"""Serves files by redirecting to file.url (e.g., useful for Amazon S3)"""
|
||||
return HttpResponseRedirect(smart_str(file.url))
|
||||
|
||||
def public_download_url(file, **kwargs):
|
||||
"""Directs downloads to file.url (useful for normal file system storage)"""
|
||||
return file.url
|
||||
12
3rd_party_apps/filetransfers/backends/xsendfile.py
Normal file
12
3rd_party_apps/filetransfers/backends/xsendfile.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.http import HttpResponse
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
def serve_file(request, file, save_as, content_type, **kwargs):
|
||||
"""Lets the web server serve the file using the X-Sendfile extension"""
|
||||
response = HttpResponse(content_type=content_type)
|
||||
response['X-Sendfile'] = file.path
|
||||
if save_as:
|
||||
response['Content-Disposition'] = smart_str(u'attachment; filename=%s' % save_as)
|
||||
if file.size is not None:
|
||||
response['Content-Length'] = file.size
|
||||
return response
|
||||
17
3rd_party_apps/filetransfers/templatetags/filetransfers.py
Normal file
17
3rd_party_apps/filetransfers/templatetags/filetransfers.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.template import Library
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..api import public_download_url
|
||||
|
||||
register = Library()
|
||||
|
||||
_hidden_data_field = '<input type="hidden" name="%s" value="%s" />'
|
||||
|
||||
@register.simple_tag
|
||||
def render_upload_data(data):
|
||||
inputs = ''.join(_hidden_data_field % item for item in data.items())
|
||||
if inputs:
|
||||
return mark_safe('<div style="display:none">%s</div>' % inputs)
|
||||
return ''
|
||||
|
||||
register.filter(public_download_url)
|
||||
@@ -1,79 +0,0 @@
|
||||
Contributing to Mayan EDMS
|
||||
==========================
|
||||
|
||||
Issues
|
||||
------
|
||||
|
||||
- Before submitting a new issue, check for **open issues** first and join the
|
||||
discussion.
|
||||
- If your issue is not attended in a while, **be patient**, the core team is
|
||||
small and the codebase big.
|
||||
- Try to reproduce the issue using a **separate, clean installation**, sometimes
|
||||
the issue can be caused by an error in a configuration file and not with the
|
||||
code itself.
|
||||
- **Do not upload** sensitive, private or classified information or files with
|
||||
your issue. If the issue is triggered by a user file, create a dummy file with the
|
||||
same properties that can trigger the issue and upload that file instead.
|
||||
- Add steps that trigger the issue in a **repeatable manner**.
|
||||
- **Screenshots** go a long way in helping understand problems.
|
||||
- The issue must be related to the code only, do not open issues for problems
|
||||
with deployments, webservers, cloud providers, etc.
|
||||
- Do not open issues asking for **support or consulting**.
|
||||
|
||||
Code
|
||||
----
|
||||
|
||||
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:
|
||||
|
||||
a. **master:** Current stable version.
|
||||
a. **series/X.Y:** There will be a **series** branch for each major version
|
||||
release (1.0, 2.0). The **master** branch will be in sync with the latest
|
||||
**series** branch.
|
||||
a. **development:** Unstable branch where the development for the next minor or
|
||||
major release is happening.
|
||||
a. **feature/X:** These are branches dealing with a specific bug or feature
|
||||
that is not yet ready to be merged.
|
||||
a. The **master** and **series** branches are stable and not braking changes
|
||||
must be submitted or merged. The **development** and **feature** branches
|
||||
are unstable and should not be used in production.
|
||||
|
||||
1. Start making your changes in your own separate branch.
|
||||
1. Write a test which shows that the bug was fixed or that the feature works as
|
||||
expected.
|
||||
1. Sign your work. Your signature certifies your submission according to the
|
||||
articles of the [Developer Certificate of Origin](https://gitlab.com/mayan-edms/mayan-edms/blob/master/DCO).
|
||||
The sign-off should be in the form:
|
||||
|
||||
````
|
||||
Signed-off-by: John Doe <john.doe@example.com>
|
||||
````
|
||||
|
||||
You must use your real name and email, pseudonyms or anonymous contributions
|
||||
are not allowed. If you set your user.name and user.email git configs, you can
|
||||
sign your commit automatically with git commit -s.
|
||||
1. Submit a merge request for your changes.
|
||||
|
||||
Feature requests
|
||||
----------------
|
||||
|
||||
- Opening issues to start a discussion around a new feature or idea are welcomed.
|
||||
- Be explicit about your idea and provide a simple scenario, others need to really
|
||||
understand the concepts behind your idea if it is to be implemented.
|
||||
- Be realistic in your expectation and scope of your idea.
|
||||
|
||||
Translations
|
||||
------------
|
||||
- Translations are handled using [Transifex](https://www.transifex.com/rosarior/mayan-edms/).
|
||||
- Join an existing team for the language to which you wish to contribute,
|
||||
if there is no team for your language, request for one to be created.
|
||||
- Don't request the creation of a new language and expect others to do all the
|
||||
work. If you request the creation of a new language try to do some of the
|
||||
translation. Language teams that don't see activity for a while are deleted.
|
||||
|
||||
Code style
|
||||
----------
|
||||
- Refer to the [Development](https://docs.mayan-edms.com/topics/development.html)
|
||||
chapter for information and examples of the code style.
|
||||
36
DCO
36
DCO
@@ -1,36 +0,0 @@
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
660 York Street, Suite 102,
|
||||
San Francisco, CA 94110 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
1215
HISTORY.rst
1215
HISTORY.rst
File diff suppressed because it is too large
Load Diff
@@ -1,60 +0,0 @@
|
||||
1.1.1 (2015-05-21)
|
||||
==================
|
||||
|
||||
- Update to Django 1.6.11
|
||||
- Fix make_dist.sh script
|
||||
- Add test for issue #163
|
||||
- Activate tests for the sources app
|
||||
- Removal of the registration app
|
||||
- New simplified official project description
|
||||
- Improvements to the index admin interface
|
||||
- Removal of installation statistics gathering
|
||||
- Remove unused folder tag
|
||||
- Fix usage of ugettext to ugettext_lazy
|
||||
- Increase size of the lock name field
|
||||
- New style documentation
|
||||
|
||||
|
||||
1.1 (2015-02-10)
|
||||
================
|
||||
- Uses Celery for background tasks
|
||||
- Removal of the splash screen
|
||||
- Adds a home view with common function buttons
|
||||
- Support for sending and receiving documents via email
|
||||
- Removed custom logging app in favor of django-actvity-stream
|
||||
- Adds watch folders
|
||||
- Includes Vagrant file for unified development and testing environments
|
||||
- Per user locale profile (language and timezone)
|
||||
- Includes news document workflow app
|
||||
- Optional and required metadata types
|
||||
- Improved testings. Automated tests against SQLite, MySQL, PostgreSQL
|
||||
- Many new REST API endpoints added
|
||||
- Simplified text messages
|
||||
- Improved method for custom settings
|
||||
- Addition of CORS support to the REST API
|
||||
- Per document language setting instead of per installation language setting
|
||||
- Metadata validation and parsing support
|
||||
- Start of code updates towards Python 3 support
|
||||
- Simplified UI
|
||||
- Stable PDF previews generation
|
||||
- More technical documentation
|
||||
|
||||
|
||||
1.0 (2014-08-27)
|
||||
================
|
||||
- New home @ https://github.com/mayan-edms/mayan-edms
|
||||
- Updated to use Django 1.6
|
||||
- Translation updates
|
||||
- Custom model properties removal
|
||||
- Source code improvements
|
||||
- Removal of included 3rd party modules
|
||||
- Automatic testing and code coverage check
|
||||
- Update of required modules and libraries versions
|
||||
- Database connection leaks fixes
|
||||
- Support for deletion of detached signatures
|
||||
- Removal of Fabric based installations script
|
||||
- Pluggable OCR backends
|
||||
- OCR improvements
|
||||
- License change, Mayan EDMS in now licensed under the Apache 2.0 License
|
||||
- PyPI package, Mayan EDMS in now available on PyPI: https://pypi.python.org/pypi/mayan-edms/
|
||||
- New REST API
|
||||
435
HISTORY_2_x.rst
435
HISTORY_2_x.rst
@@ -1,435 +0,0 @@
|
||||
2.7.3 (2017-09-11)
|
||||
==================
|
||||
- Fix task manager queue list view. Thanks to LeVon Smoker for
|
||||
the report.
|
||||
- Fix resolved link class URL mangling when the keep_query argument is
|
||||
used. Thanks to Nick Douma (LordGaav) for the report and diagnostic
|
||||
information. Fixes source navigation on the document upload wizard.
|
||||
|
||||
2.7.2 (2017-09-06)
|
||||
==================
|
||||
- Fix new mailer creation view. GitLab issue #431.
|
||||
Thanks to Robert Schöftner (@robert.schoeftner) for the
|
||||
report and the solution.
|
||||
- Consolidate intial document created event and the first
|
||||
document properties edited events. Preserve the user that
|
||||
initially creates the document. GitLab issue #433. Thanks
|
||||
to Jesaja Everling (@jeverling) for the report.
|
||||
- Sort the list of root cabinets. Thanks to Thomas Plotkowiak
|
||||
for the request.
|
||||
- Sort the list of a document's cabinets.
|
||||
- Display a document's cabinet list in italics. GitLab issue #435.
|
||||
Thanks to LeVon Smoker for the request.
|
||||
- Install mock by default to allow easier testing of deployed
|
||||
instances.
|
||||
|
||||
2.7.1 (2017-09-03)
|
||||
==================
|
||||
- Support unicode in URL querystring. GitLab issue #423.
|
||||
Thanks to Gustavo Teixeira (@gsteixei) for the find.
|
||||
- Import errors during initialization are only ignored
|
||||
if they are cause by a missing local.py. Thanks to
|
||||
MacRobb Simpson for the report and solution.
|
||||
- Make sure the local.py created used unicode for strings
|
||||
by default. GitLab issue #424. Thanks to Gustavo Teixeira
|
||||
(@gsteixei) for the find.
|
||||
|
||||
2.7 (2017-08-30)
|
||||
================
|
||||
- Add workaround for PDF with IndirectObject as the
|
||||
rotation value. GitHub #261.
|
||||
- Add ACL list link with icon and use it for the document facet menu.
|
||||
- Fix mailing app permissions labels.
|
||||
- Add ACLs link and ACLs permissions to the mailer profile model.
|
||||
- Improve mailer URL regex.
|
||||
- Add ordering support to the SourceColumn class. GitLab issue #417.
|
||||
- Shows the cabinets in the document list. GitLab #417 @corneliusludmann
|
||||
- Add workaround for pycountry versions without the bibliographical key.
|
||||
GitHub issue #250.
|
||||
- Skip UUID migration on Oracle backends. GitHub issue #251.
|
||||
- Allow changing the output format, DPI of the pdftoppm command, and
|
||||
the output format of the converter via the CONVERTER_GRAPHICS_BACKEND_CONFIG
|
||||
setting. GitHub issues #256 #257 GitLab issue #416.
|
||||
- Add support for workflow triggers.
|
||||
- Add support for workflow actions.
|
||||
- Add support for rendering workflows.
|
||||
- Add support for unbinding sub menus.
|
||||
- Fix mailing profile test view.
|
||||
- Disregard the last 3 dots that mark the end of the YAML document.
|
||||
- Add support for multiple dashboards.
|
||||
- Add support for removing dashboard widgets.
|
||||
- Convert document version view to item list view.
|
||||
- Add support for browsing individual document versions.
|
||||
- Add support for dropdown menus to the item list view template.
|
||||
- Add support for preserving the file extension when downloading a document
|
||||
version. GitLab #415.
|
||||
- Split OCR app into OCR and parsing.
|
||||
- Remove Folders app.
|
||||
- Use the literal 'System' instead of the target name when
|
||||
the action user in unknown.
|
||||
- Remove the view to submit all document for OCR.
|
||||
- When changing document types, don't delete the old metadata that is
|
||||
also found in the new document type. GitLab issue #421.
|
||||
- Add tag attach and tag remove events.
|
||||
- Change the permission needed to attach and remove tags.
|
||||
- Add HTTP POST workflow state action.
|
||||
- Add access control grant workflow state action.
|
||||
- Beta Python 3 support.
|
||||
|
||||
2.6.4 (2017-07-26)
|
||||
==================
|
||||
- Add missing replacements of reverse to resolve_url.
|
||||
|
||||
2.6.3 (2017-07-25)
|
||||
==================
|
||||
- Add makefile target to launch a PostgreSQL container.
|
||||
- Use resolve_url instead of redirect to resolve the post login URL.
|
||||
- Make the intialsetup and performupgrade management tasks work
|
||||
with signals to allow customization from 3rd party apps.
|
||||
- PEP8 cleanups.
|
||||
- Add tag_ids keyword argument to the Source.handle_upload
|
||||
model method. GitLab issue #413.
|
||||
- Add overflow wrapping so wrap long titles in Firefox too.
|
||||
- Makes Roles searchable. GitLab issue #402.
|
||||
- Add line numbers to the debug and production loggers.
|
||||
Add date and time to the production logger.
|
||||
- Add support for generating setup.py from a template. GitLab
|
||||
#149 #200.
|
||||
- Add fade in animation to document images.
|
||||
|
||||
2.6.2 (2017-07-19)
|
||||
==================
|
||||
- Fix deprecation warning to prepare upgrade to Django 1.11 and 2.0.
|
||||
- Fix document page zoom.
|
||||
- Add support to run tests against a MySQL, Postgres or Oracle container.
|
||||
- Improve tag widget customization by moving the markup to its own template.
|
||||
- Fix document page widget appearance in the document page list view.
|
||||
- Make document version order deterministic.
|
||||
- Allow total page number instrospection of encrypted PDF with non ASCII user properties. GitLab issue #411.
|
||||
- Oracle database compatibility update in the cabinets app. GitHub #258.
|
||||
|
||||
2.6.1 (2017-07-18)
|
||||
==================
|
||||
- Fix issue when editing or removing metadata from multiple documents.
|
||||
|
||||
2.6 (2017-07-18)
|
||||
================
|
||||
- Fix HTML mark up in window title. GitLab #397.
|
||||
- Add support for emailing documents to a recipient list. GitLab #396.
|
||||
- Backport metadata widget changes from @Macrobb. GitLab #377.
|
||||
- Make users and group searchable.
|
||||
- Add support for logging errors during in production mode.
|
||||
Add COMMON_PRODUCTION_ERROR_LOG_PATH to control path of log file.
|
||||
Defaults to mayan/error.log.
|
||||
- Add support logging request exceptions.
|
||||
- Add document list item view.
|
||||
- Sort setting by namespace label and by global name second.
|
||||
- Sort indexes by label.
|
||||
- Fix cabinets permission and access control checking.
|
||||
- The permission to add or remove documents to cabinets now applies to documents too.
|
||||
- Equalize dashboard widgets heights.
|
||||
- Switch the order of the DEFAULT_AUTHENTICATION_CLASSES of DRF. GitLab #400.
|
||||
- Backport document's version list view permission.
|
||||
- Improve code to unbind menu entries.
|
||||
- Renamed the document type permission namespace from "Document setup" to "Document types".
|
||||
- Add support for granting the document type edit, document type delete, and document type view
|
||||
permissions to individual document type instances.
|
||||
- Improved tests by testing for accesses.
|
||||
- Increase the size of the mailing profile label field to 128 characters.
|
||||
|
||||
2.5.2 (2017-07-08)
|
||||
==================
|
||||
- Improve new document creation signal handling.
|
||||
Fixes issue with duplicate scanning at upload.
|
||||
|
||||
2.5.1 (2017-07-08)
|
||||
==================
|
||||
- Update release target due to changes in PyPI.
|
||||
|
||||
2.5 (2017-07-07)
|
||||
================
|
||||
- Add view to download a document's OCR text. GitLab #215
|
||||
- Add user configurable mailer. GitLab #286.
|
||||
- Use Toasts library for screen messages.
|
||||
- Reduce verbosity of some debug messages.
|
||||
- Add new lineart transformation.
|
||||
- Fix SANE source resolution field.
|
||||
- About and Profile menu reorganization.
|
||||
- PDF compatibility improvements.
|
||||
- Office document coversion improvements.
|
||||
- New metadata type setup UI.
|
||||
- Duplicated document scan support.
|
||||
- "Remember me" login support.
|
||||
- Forgotten password restore via email.
|
||||
- Document cache disabling.
|
||||
- Translation improvements.
|
||||
- Image loading improvements.
|
||||
- Lower JavaScript memory utilization.
|
||||
- HTML reponsive layout improvements.
|
||||
- Make document deletion a background task.
|
||||
- Unicode handling improvements.
|
||||
- Python3 compatilibyt improvements.
|
||||
- New screen messages using Toastr.
|
||||
|
||||
2.4 (2017-06-23)
|
||||
================
|
||||
- Add Django-mathfilters.
|
||||
- Improve render of documents with no pages.
|
||||
- Add SANE scanner document source.
|
||||
- Added PDF orientation detection. GitLab issue #387.
|
||||
- Fix repeated permission list API URL. GitLab issue #389.
|
||||
- Fix role creation API endpoint not returning id. GitLab issue #390.
|
||||
- Make tags, metadata types and cabinets searchable via the dynamic search API. GitLab issue #344.
|
||||
- Add support for updating configuration options from environment variables.
|
||||
- Add purgelocks management command. GitLab issue #221.
|
||||
- Fix index rebuilding for multi value first levels. GitLab issue #391.
|
||||
- Truncate views titles via the APPEARANCE_MAXIMUM_TITLE_LENGTH setting. GitLab issue #217.
|
||||
- Add background task manager app. GitLab issue #132.
|
||||
- Add link to show a document's OCR errors. GitLab issue #291.
|
||||
|
||||
2.3 (2017-06-08)
|
||||
================
|
||||
- Allow for bigger indexing expression templates.
|
||||
- Auto select checkbox when updating metadata values. GitLab issue #371.
|
||||
- Added support for passing the options allow-other and allow-root to the
|
||||
FUSE index mirror. GitLab issue #385
|
||||
- Add support for check for the latest released version of Mayan from the
|
||||
About menu.
|
||||
- Support for rebuilding specific indexes. GitLab issue #372.
|
||||
- Rewrite document indexing code to be faster and use less locking.
|
||||
- Use a predefined file path for the file lock.
|
||||
- Catch documents with not document version when displaying their thumbnails.
|
||||
- Document page navigation fix when using Mayan as a sub URL app.
|
||||
- Add support for indexing on workflow state changes.
|
||||
- Add search model list API endpoint.
|
||||
|
||||
2.2 (2017-04-26)
|
||||
================
|
||||
- Remove the installation app (GitLab #301).
|
||||
- Add support for document page search
|
||||
- Remove recent searches feature
|
||||
- Remove dependency on the django-filetransfer library
|
||||
- Fix height calculation in resize transformation
|
||||
- Improve upgrade instructions
|
||||
- New image caching pipeline
|
||||
- New drop down menus for the documents, folders and tags app as well as for
|
||||
the user links.
|
||||
- New Dashboard view
|
||||
- Moved licenses to their own module in every app
|
||||
- Update project to work with Django 1.10.4.
|
||||
- Tags are alphabetically ordered by label (GitLab #342).
|
||||
- Stop loading theme fonts from the web (GitLab #343).
|
||||
- Add support for attaching multiple tags (GitLab #307).
|
||||
- Integrate the Cabinets app.
|
||||
|
||||
2.1.11 (2017-03-14)
|
||||
===================
|
||||
- Added a quick rename serializer to the document type API serializer.
|
||||
- Added per document type, workflow list API view.
|
||||
- Mayan EDMS was adopted a version 1.1 of the Linux Foundation Developer Certificate of Origin.
|
||||
- Added the detail url of a permission in the permission serializer.
|
||||
- Added endpoints for the ACL app API.
|
||||
- Implemented document workflows transition ACLs. GitLab issue #321.
|
||||
- Add document comments API endpoints. GitHub issue #249.
|
||||
- Add support for overriding the Celery class.
|
||||
- Changed the document upload view in source app to not use the HTTP referer
|
||||
URL blindly, but instead recompose the URL using known view name. Needed
|
||||
when integrating Mayan EDMS into other app via using iframes.
|
||||
- Addes size field to the document version serializer.
|
||||
- Removed the serializer from the deleted document restore API endpoint.
|
||||
- Added support for adding or editing document types to smart links via the
|
||||
API.
|
||||
|
||||
2.1.10 (2017-02-13)
|
||||
===================
|
||||
- Update Makefile to use twine for releases.
|
||||
- Add Makefile target to make test releases.
|
||||
|
||||
2.1.9 (2017-02-13)
|
||||
==================
|
||||
- Update make file to Workaround long standing pypa wheel bug #99
|
||||
|
||||
2.1.8 (2017-02-12)
|
||||
==================
|
||||
- Fixes in the trashed document API endpoints.
|
||||
- Improved tags API PUT and PATCH endpoints.
|
||||
- Bulk document adding when creating and editing tags.
|
||||
- The version of django-mptt is preserved in case mayan-cabinets is installed.
|
||||
- Add Django GPG API endpoints for singing keys.
|
||||
- Add API endpoints for the document states (workflows) app.
|
||||
- Add API endpoints for the messsage of the day (MOTD) app.
|
||||
- Add Smart link API endpoints.
|
||||
- Add writable versions of the Document and Document Type serializers (GitLab issues #348 and #349).
|
||||
- Close GitLab issue #310 "Metadata's lookup with chinese messages when new document"
|
||||
|
||||
2.1.7 (2017-02-01)
|
||||
==================
|
||||
- Improved user management API endpoints.
|
||||
- Improved permissions API endpoints.
|
||||
- Improvements in the API tests of a few apps.
|
||||
- Addition Content type list API view to the common app.
|
||||
- Add API endpoints to the events app.
|
||||
- Enable the parser and validation fields of the metadata serializer.
|
||||
|
||||
2.1.6 (2016-11-23)
|
||||
==================
|
||||
- Fix variable name typo in the rotation transformation class.
|
||||
- Update translations
|
||||
|
||||
2.1.5 (2016-11-08)
|
||||
==================
|
||||
- Backport resize transformation math operation fix (GitLab #319).
|
||||
- Update Pillow to 3.1.2 (Security fix).
|
||||
- Backport zoom transformation performance improvement (GitLab #334).
|
||||
- Backport trash can navigation link resolution fix (GitLab #331).
|
||||
- Improve documentation regarding the use of GPG version 1 (GitLab #333).
|
||||
- Fix ACL create view HTML response type. (GitLab #335).
|
||||
- Expland staging folder and watch folder explanation.
|
||||
|
||||
2.1.4 (2016-10-28)
|
||||
==================
|
||||
- Add missing link to the 2.1.3 release notes in the index file.
|
||||
- Improve TempfileCheckMixin.
|
||||
- Fix statistics namespace list display view.
|
||||
- Fix events list display view.
|
||||
- Update required Django version to 1.8.15.
|
||||
- Update required python-gnupg version to 0.3.9.
|
||||
- Improved orphaned temporary files test mixin.
|
||||
- Re-enable and improve GitLab CI MySQL testing.
|
||||
- Improved GPG handling.
|
||||
- New GPG backend system.
|
||||
- Minor documentation updates.
|
||||
|
||||
2.1.3 (2016-06-29)
|
||||
==================
|
||||
- Add help message when initialsetup migration phase fails. Relates to GitLab issue #296.
|
||||
- Start using self.setdout instead of print as per documentation.
|
||||
- Fix GitLab issue #295, "When editing a user the top bar jumps to the name of the user".
|
||||
- Normalize handling of temporary file and directory creation.
|
||||
- Fix GitLab issue #309, "Temp files quickly filling-up my /tmp (1GB tmpfs)".
|
||||
- Explicitly check for residual temporary files in tests.
|
||||
- Add missing temporary file cleanup for office documents.
|
||||
- Fix file descriptor leak in the document signature download test.
|
||||
|
||||
2.1.2 (2016-05-20)
|
||||
==================
|
||||
- Sort document languages and user profile locale language lists. GitLab issue #292.
|
||||
- Fix metadata lookup for {{ users }} and {{ group }}. Fixes GitLab #290.
|
||||
- Add Makefile for common development tasks
|
||||
|
||||
2.1.1 (2016-05-17)
|
||||
==================
|
||||
- Fix navigation issue that make it impossible to add new sources. GitLab issue #288.
|
||||
- The Tesseract OCR backend now reports if the requested language file is missing. GitLab issue #289.
|
||||
- Ensure the automatic default index is created after the default document type.
|
||||
|
||||
2.1 (2016-05-14)
|
||||
================
|
||||
- Upgrade to use Django 1.8.13. Issue #246.
|
||||
- Upgrade requirements.
|
||||
- Remove remaining references to Django's User model. GitLab issue #225
|
||||
- Rename 'Content' search box to 'OCR'.
|
||||
- Remove included login required middleware using django-stronghold instead (http://mikegrouchy.com/django-stronghold/).
|
||||
- Improve generation of success and error messages for class based views.
|
||||
- Remove ownership concept from folders.
|
||||
- Replace strip_spaces middleware with the spaceless template tag. GitLab issue #255
|
||||
- Deselect the update checkbox for optional metadata by default.
|
||||
- Silence all Django 1.8 model import warnings.
|
||||
- Implement per document type document creation permission. Closes GitLab issue #232.
|
||||
- Add icons to the document face menu links.
|
||||
- Increase icon to text spacing to 3px.
|
||||
- Make document type delete time period optional.
|
||||
- Fixed date locale handling in document properties, checkout and user detail views.
|
||||
- Add new permission: checkout details view.
|
||||
- Add HTML5 upload widget. Issue #162.
|
||||
- Add Message of the Day app. Issue #222
|
||||
- Update Document model's uuid field to use Django's native UUIDField class.
|
||||
- Add new split view index navigation
|
||||
- Newly uploaded documents appear in the Recent document list of the user.
|
||||
- Document indexes now have ACL support.
|
||||
- Remove the document index setup permission.
|
||||
- Status messages now display the object class on which they operate not just the word "Object".
|
||||
- More tests added.
|
||||
- Handle unicode filenames in staging folders.
|
||||
- Add staging file deletion permission.
|
||||
- New document_signature_view permission.
|
||||
- Add support for signing documents.
|
||||
- Instead of multiple keyservers only one keyserver is now supported.
|
||||
- Replace document type selection widget with an opened selection list.
|
||||
- Add mailing documentation chapter.
|
||||
- Add roadmap documentation chapter.
|
||||
- API updates.
|
||||
|
||||
|
||||
2.0.2 (2016-02-09)
|
||||
==================
|
||||
- Install testing dependencies when installing development dependencies.
|
||||
- Fix GitLab issue #250 "Empty optional lookup metadata trigger validation error".
|
||||
- Fix OCR API test.
|
||||
- Move metadata form value validation to .clean() method.
|
||||
- Only extract validation error messages from ValidationError exception instances.
|
||||
- Don't store empty metadata value if the update checkbox is not checked.
|
||||
- Add 2 second delay to document version tests to workaround MySQL limitation.
|
||||
- Strip HTML tags from the browser title.
|
||||
- Remove Docker and Docker Compose files.
|
||||
|
||||
|
||||
2.0.1 (2016-01-22)
|
||||
==================
|
||||
- Fix GitLab issue #243, "System allows a user to skip entering values for a required metadata field while uploading a new document"
|
||||
- Fix GitLab issue #245, "Add multiple metadata not possible"
|
||||
- Updated Vagrantfile to provision a production box too.
|
||||
|
||||
|
||||
2.0 (2015-12-04)
|
||||
================
|
||||
- New source homepage: https://gitlab.com/mayan-edms/mayan-edms
|
||||
- Update to Django 1.7
|
||||
- New Bootstrap Frontend UI
|
||||
- Easier theming and rebranding
|
||||
- Improved page navigation interface
|
||||
- Menu reorganization
|
||||
- Removal of famfam icon set
|
||||
- Improved document preview generation
|
||||
- Document submission for OCR changed to POST
|
||||
- New YAML based settings system
|
||||
- Removal of auto admin creation as separate app
|
||||
- Removal of dependencies
|
||||
- ACL system refactor
|
||||
- Object access control inheritance
|
||||
- Removal of anonymous user support
|
||||
- Metadata validators refactor
|
||||
- Trash can support
|
||||
- Retention policies
|
||||
- Support for sharing indexes as FUSE filesystems
|
||||
- Clickable preview images titles
|
||||
- Removal of eval
|
||||
- Smarter OCR, per page parsing or OCR fallback
|
||||
- Improve failure tolerance (not all Operational Errors are critical now)
|
||||
- RGB tags
|
||||
- Default document type and default document source
|
||||
- Link unbinding
|
||||
- Statistics refactor
|
||||
- Apps merge
|
||||
- New signals
|
||||
- Test improvements
|
||||
- Indexes recalculation after document creation too
|
||||
- Upgrade command
|
||||
- OCR data moved to ocr app from documents app
|
||||
- New internal document creation workflow return a document stub
|
||||
- Auto console debug logging during development and info during production
|
||||
- New class based and menu based navigation system
|
||||
- New class based transformations
|
||||
- Usage of Font Awesome icons set
|
||||
- Management command to remove obsolete permissions: `purgepermissions`
|
||||
- Normalization of 'title' and 'name' fields to 'label'
|
||||
- Improved API, now at version 1
|
||||
- Invert page title/project name order in browser title
|
||||
- Django's class based views pagination
|
||||
- Reduction of text strings
|
||||
- Removal of the CombinedSource class
|
||||
- Removal of default class ACLs
|
||||
- Removal of the ImageMagick and GraphicsMagick converter backends
|
||||
- Remove support for applying roles to new users automatically
|
||||
- Removal of the DOCUMENT_RESTRICTIONS_OVERRIDE permission
|
||||
- Removed the page_label field
|
||||
13
LICENSE
13
LICENSE
@@ -1,13 +0,0 @@
|
||||
Copyright 2011 Roberto Rosario
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,6 +0,0 @@
|
||||
include README.md LICENSE HISTORY.rst mayan/LICENSE
|
||||
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/*
|
||||
324
Makefile
324
Makefile
@@ -1,324 +0,0 @@
|
||||
.PHONY: clean-pyc clean-build
|
||||
|
||||
DOCKER_MYSQL_IMAGE = mysql:8.0
|
||||
DOCKER_ORACLE_IMAGE = wnameless/oracle-xe-11g
|
||||
DOCKER_POSTGRES_IMAGE = postgres:9.6-alpine
|
||||
DOCKER_REDIS_IMAGE = redis:5.0-alpine
|
||||
|
||||
PYTHON_MYSQL_VERSION = 1.4.4
|
||||
PYTHON_PSYCOPG2_VERSION = 2.8.3
|
||||
PYTHON_RABBITMQ_VERSION = 2.0.0
|
||||
PYTHON_REDIS_VERSION = 3.2.1
|
||||
|
||||
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: ## Remove build artifacts.
|
||||
rm -fr build/
|
||||
rm -fr dist/
|
||||
rm -fr *.egg-info
|
||||
|
||||
clean-pyc: ## Remove Python artifacts.
|
||||
find . -name '*.pyc' -exec rm -f {} +
|
||||
find . -name '*.pyo' -exec rm -f {} +
|
||||
find . -name '*~' -exec rm -f {} +
|
||||
find . -name '__pycache__' -exec rm -R -f {} +
|
||||
|
||||
# Testing
|
||||
|
||||
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: ## 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 $(DOCKER_POSTGRES_IMAGE)
|
||||
sudo apt-get install -q libpq-dev
|
||||
pip install psycopg2==$(PYTHON_PSYCOPG2_VERSION)
|
||||
while ! nc -z 127.0.0.1 5432; 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
|
||||
@docker volume rm test-postgres || true
|
||||
|
||||
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 $(DOCKER_MYSQL_IMAGE)
|
||||
sudo apt-get install -q libmysqlclient-dev mysql-client
|
||||
pip install mysqlclient==$(PYTHON_MYSQL_VERSION)
|
||||
while ! nc -z 127.0.0.1 3306; 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
|
||||
@docker volume rm test-mysql || true
|
||||
|
||||
test-launch-oracle:
|
||||
@docker rm -f test-oracle || true
|
||||
@docker volume rm test-oracle || true
|
||||
docker run -d --name test-oracle -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true -v test-oracle:/u01/app/oracle $(DOCKER_ORACLE_IMAGE)
|
||||
# https://gist.github.com/kimus/10012910
|
||||
pip install cx_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
|
||||
@docker volume rm test-oracle || true
|
||||
|
||||
# Documentation
|
||||
|
||||
docs-serve: ## Run the livehtml documentation generator.
|
||||
cd docs;make livehtml
|
||||
|
||||
docs-spellcheck: ## Spellcheck the documentation.
|
||||
sphinx-build -b spelling -d docs/_build/ docs docs/_build/spelling
|
||||
|
||||
# Translations
|
||||
|
||||
translations-make: ## Refresh all translation files.
|
||||
contrib/scripts/process_messages.py -m
|
||||
|
||||
translations-compile: ## Compile all translation files.
|
||||
contrib/scripts/process_messages.py -c
|
||||
|
||||
translations-push: ## Upload all translation files to Transifex.
|
||||
tx push -s
|
||||
|
||||
translations-pull: ## Download all translation files from Transifex.
|
||||
tx pull -f
|
||||
|
||||
# Releases
|
||||
|
||||
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/rootfs/version
|
||||
make generate-setup
|
||||
|
||||
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"
|
||||
|
||||
python-release: ## Package (sdist and wheel) and upload a release.
|
||||
python-release: clean python-wheel
|
||||
twine upload dist/* -r pypi
|
||||
|
||||
python-sdist: ## Build the source distribution package.
|
||||
python-sdist: clean
|
||||
python setup.py sdist
|
||||
ls -l dist
|
||||
|
||||
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
|
||||
|
||||
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 && \
|
||||
update-locale LANG=en_US.UTF-8 && \
|
||||
export LC_ALL=en_US.UTF-8 && \
|
||||
cp -r /host_source/* . && \
|
||||
apt-get update && \
|
||||
apt-get install make python-pip -y && \
|
||||
pip install -r requirements/build.txt && \
|
||||
cp -r /host_home/.pypirc ~/.pypirc && \
|
||||
make test-release"
|
||||
|
||||
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 && \
|
||||
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 && \
|
||||
cp -r /host_source/* . && \
|
||||
apt-get install make python-pip -y && \
|
||||
pip install -r requirements/build.txt && \
|
||||
cp -r /host_home/.pypirc ~/.pypirc && \
|
||||
make release"
|
||||
|
||||
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 && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
update-locale LANG=en_US.UTF-8 && \
|
||||
export LC_ALL=en_US.UTF-8 && \
|
||||
apt-get update && \
|
||||
apt-get install make python-pip libreoffice tesseract-ocr tesseract-ocr-deu poppler-utils -y && \
|
||||
pip install -r requirements/development.txt && \
|
||||
make sdist-test-suit \
|
||||
"
|
||||
|
||||
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 && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
update-locale LANG=en_US.UTF-8 && \
|
||||
export LC_ALL=en_US.UTF-8 && \
|
||||
apt-get update && \
|
||||
apt-get install make python-pip libreoffice tesseract-ocr tesseract-ocr-deu poppler-utils -y && \
|
||||
pip install -r requirements/development.txt && \
|
||||
make wheel-test-suit \
|
||||
"
|
||||
|
||||
python-sdist-test-suit: sdist
|
||||
rm -f -R _virtualenv
|
||||
virtualenv _virtualenv
|
||||
sh -c '\
|
||||
. _virtualenv/bin/activate; \
|
||||
pip install `ls dist/*.gz`; \
|
||||
_virtualenv/bin/mayan-edms.py initialsetup; \
|
||||
pip install mock==2.0.0; \
|
||||
_virtualenv/bin/mayan-edms.py test --mayan-apps \
|
||||
'
|
||||
|
||||
python-wheel-test-suit: wheel
|
||||
rm -f -R _virtualenv
|
||||
virtualenv _virtualenv
|
||||
sh -c '\
|
||||
. _virtualenv/bin/activate; \
|
||||
pip install `ls dist/*.whl`; \
|
||||
_virtualenv/bin/mayan-edms.py initialsetup; \
|
||||
pip install mock==2.0.0; \
|
||||
_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: ## Run the development server.
|
||||
./manage.py runserver --nothreading --settings=mayan.settings.development $(ADDRPORT)
|
||||
|
||||
runserver_plus: ## Run the Django extension's development server.
|
||||
./manage.py runserver_plus --nothreading --settings=mayan.settings.development $(ADDRPORT)
|
||||
|
||||
shell_plus: ## Run the shell_plus command.
|
||||
./manage.py shell_plus --settings=mayan.settings.development
|
||||
|
||||
test-with-docker-services-on: ## Launch and initialize production-like services using Docker (Postgres and Redis).
|
||||
docker run -d --name redis -p 6379:6379 $(DOCKER_REDIS_IMAGE)
|
||||
docker run -d --name postgres -p 5432:5432 $(DOCKER_POSTGRES_IMAGE)
|
||||
while ! nc -z 127.0.0.1 6379; do sleep 1; done
|
||||
while ! nc -z 127.0.0.1 5432; do sleep 1; done
|
||||
sleep 4
|
||||
pip install psycopg2==$(PYTHON_PSYCOPG2_VERSION) redis==$(PYTHON_REDIS_VERSION)
|
||||
./manage.py initialsetup --settings=mayan.settings.staging.docker
|
||||
|
||||
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: ## Launch a front end instance that uses the production-like services.
|
||||
./manage.py runserver --settings=mayan.settings.staging.docker
|
||||
|
||||
test-with-docker-worker: ## Launch a worker instance that uses the production-like services.
|
||||
DJANGO_SETTINGS_MODULE=mayan.settings.staging.docker ./manage.py celery worker -A mayan -B -l INFO -O fair
|
||||
|
||||
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 $(DOCKER_MYSQL_IMAGE)
|
||||
while ! nc -z 127.0.0.1 3306; do sleep 1; done
|
||||
|
||||
docker-mysql-off: ## Stop and delete the MySQL Docker container.
|
||||
docker stop mysql
|
||||
docker rm mysql
|
||||
|
||||
docker-postgres-on: ## Launch and initialize a PostgreSQL Docker container.
|
||||
docker run -d --name postgres -p 5432:5432 $(DOCKER_POSTGRES_IMAGE)
|
||||
while ! nc -z 127.0.0.1 5432; do sleep 1; done
|
||||
|
||||
docker-postgres-off: ## Stop and delete the PostgreSQL Docker container.
|
||||
docker stop postgres
|
||||
docker rm postgres
|
||||
|
||||
|
||||
# Security
|
||||
|
||||
safety-check: ## Run a package safety check.
|
||||
safety check
|
||||
|
||||
|
||||
# Other
|
||||
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
|
||||
|
||||
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 && \
|
||||
mkdir /host_source/dist || true && \
|
||||
export LC_ALL=C.UTF-8 && \
|
||||
cp -r /host_source/* . && \
|
||||
apt-get update && \
|
||||
apt-get install -y make && \
|
||||
pip install -r requirements/build.txt && \
|
||||
make wheel && \
|
||||
cp dist/* /host_source/dist/"
|
||||
|
||||
check-readme: ## Checks validity of the README.rst file for PyPI publication.
|
||||
python setup.py check -r -s
|
||||
|
||||
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
|
||||
115
README.md
115
README.md
@@ -1,86 +1,51 @@
|
||||
[](https://paypal.me/MayanEDMS)
|
||||
[![pypi][pypi]][pypi-url]
|
||||
[![builds][builds]][builds-url]
|
||||
![python][python]
|
||||
![license][license]
|
||||
[](https://hub.docker.com/r/mayanedms/mayanedms/)
|
||||
[](https://hub.docker.com/r/mayanedms/mayanedms/)
|
||||

|
||||
|
||||
Mayan EDMS
|
||||
==========
|
||||
|
||||
Open source, Django based document management system with custom metadata
|
||||
indexing, file serving integration, tagging, digital signature verification,
|
||||
text parsing and OCR capabilities.
|
||||
|
||||
[Website](http://www.mayan-edms.com)
|
||||
|
||||
[Video demostration](http://bit.ly/pADNXv)
|
||||
|
||||
[Documentation](http://readthedocs.org/docs/mayan/en/latest/)
|
||||
|
||||
[Translations](https://www.transifex.net/projects/p/mayan-edms/)
|
||||
|
||||
[Mailing list (via Google Groups)](http://groups.google.com/group/mayan-edms)
|
||||
|
||||
|
||||
[pypi]: http://img.shields.io/pypi/v/mayan-edms.svg
|
||||
[pypi-url]: http://badge.fury.io/py/mayan-edms
|
||||
Quick install
|
||||
-------------
|
||||
To bootstrap **Mayan EDMS** via the fabfile without having to clone the
|
||||
entire repository, run the following command, replacing the part that
|
||||
reads: <Your MySQL root password> with your current MySQL root password
|
||||
or the MySQL root password you plan to assign to it, during the MySQL
|
||||
installation when executing the fabfile.
|
||||
|
||||
[builds]: https://gitlab.com/mayan-edms/mayan-edms/badges/master/build.svg
|
||||
[builds-url]: https://gitlab.com/mayan-edms/mayan-edms/pipelines
|
||||
- Debian or Ubuntu:
|
||||
|
||||
[cover]: https://codecov.io/gitlab/mayan-edms/mayan-edms/coverage.svg?branch=master
|
||||
[cover-url]: https://codecov.io/gitlab/mayan-edms/mayan-edms?branch=master
|
||||
cd /tmp && sudo apt-get install -y fabric wget tar gzip && wget https://github.com/rosarior/mayan/raw/master/contrib/fabfile.tar.gz -O - | tar -xvzf - && echo "database_manager_admin_password=<Your MySQL root password>" > ~/.fabricrc && fab -H localhost install
|
||||
|
||||
[python]: https://img.shields.io/pypi/pyversions/mayan-edms.svg
|
||||
[python-url]: https://img.shields.io/pypi/l/mayan-edms.svg?style=flat
|
||||
- Fedora:
|
||||
|
||||
[license]: https://img.shields.io/pypi/l/mayan-edms.svg?style=flat
|
||||
[license-url]: https://img.shields.io/pypi/l/mayan-edms.svg?style=flat
|
||||
cd /tmp && sudo yum install -y fabric wget tar gzip && wget https://github.com/rosarior/mayan/raw/master/contrib/fabfile.tar.gz -O - | tar -xvzf - && echo "database_manager_admin_password=<Your MySQL root password>" > ~/.fabricrc && fab -H localhost install
|
||||
|
||||
|
||||
<div align="center">
|
||||
<a href="http://www.mayan-edms.com">
|
||||
<img width="200" heigth="200" src="https://gitlab.com/mayan-edms/mayan-edms/raw/master/docs/_static/mayan_logo.png">
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
<p>
|
||||
Mayan EDMS is a document management system. Its main purpose is to store,
|
||||
introspect, and categorize files, with a strong emphasis on preserving the
|
||||
contextual and business information of documents. It can also OCR, preview,
|
||||
label, sign, send, and receive thoses files. Other features of interest
|
||||
are its workflow system, role based access control, and REST API.
|
||||
<p>
|
||||
|
||||
<p align="center">
|
||||
<img width="400" src="https://gitlab.com/mayan-edms/mayan-edms/raw/master/docs/_static/overview.gif">
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<h2 align="center">Book</h2>
|
||||
|
||||
The pre-release version of the book "Exploring Mayan EDMS" available now at a discounted price!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://sellfy.com/p/um2fkx/">
|
||||
<img width="400" src="https://d12swbtw719y4s.cloudfront.net/images/v6RpxW40/aP0qKLjkPiAuXZhYuB45/wDAULAzFyx.jpeg?w=548">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Limited quantities. Buyers of the pre-release will get the full version for free when it is ready.
|
||||
|
||||
The link is https://sellfy.com/p/um2fkx/
|
||||
|
||||
<h2 align="center">Installation</h2>
|
||||
|
||||
The easiest way to use Mayan EDMS is by using the official
|
||||
[Docker](https://www.docker.com/) image. Make sure Docker is properly installed
|
||||
and working before attempting to install Mayan EDMS.
|
||||
|
||||
For the complete set of installation instructions visit the Mayan EDMS documentation
|
||||
at: https://docs.mayan-edms.com/topics/installation.html
|
||||
|
||||
<h2 align="center">Hardware requirements</h2>
|
||||
|
||||
- 2 Gigabytes of RAM (1 Gigabyte if OCR is turned off).
|
||||
- Multiple core CPU (64 bit, faster than 1 GHz recommended).
|
||||
|
||||
<h2 align="center">Important links</h2>
|
||||
License
|
||||
-------
|
||||
This project is open sourced under [GNU GPL Version 3](http://www.gnu.org/licenses/gpl-3.0.html).
|
||||
|
||||
|
||||
- [Homepage](http://www.mayan-edms.com)
|
||||
- [Documentation](https://docs.mayan-edms.com)
|
||||
- [Wiki](https://wiki.mayan-edms.com/)
|
||||
- [Contributing](https://gitlab.com/mayan-edms/mayan-edms/blob/master/CONTRIBUTING.md)
|
||||
- [Forum](https://forum.mayan-edms.com/)
|
||||
- [Source code, issues, bugs](https://gitlab.com/mayan-edms/mayan-edms)
|
||||
- [Plug-ins, other related projects](https://gitlab.com/mayan-edms/)
|
||||
- [Translations](https://www.transifex.com/rosarior/mayan-edms/)
|
||||
- [Videos](https://www.youtube.com/channel/UCJOOXHP1MJ9lVA7d8ZTlHPw)
|
||||
Author
|
||||
------
|
||||
Roberto Rosario - [Twitter](http://twitter.com/#siloraptor) [E-mail](mailto://roberto.rosario@mayan-edms.com)
|
||||
|
||||
|
||||
Donations
|
||||
---------
|
||||
Please [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W6LMMZHTNUJ6L) if you are willing to support the further development of this project.
|
||||
|
||||
|
||||
72
README.rst
72
README.rst
@@ -1,72 +0,0 @@
|
||||
|donation| |pypi| |builds| |coverage| |python| |license| |docker_pulls| |docker_stars| |docker_layers|
|
||||
|
||||
|
||||
.. image:: https://gitlab.com/mayan-edms/mayan-edms/raw/master/docs/_static/mayan_logo.png
|
||||
:align: center
|
||||
:width: 200
|
||||
:height: 200
|
||||
|
||||
Mayan EDMS is a document management system. Its main purpose is to store,
|
||||
introspect, and categorize files, with a strong emphasis on preserving the
|
||||
contextual and business information of documents. It can also OCR, preview,
|
||||
label, sign, send, and receive thoses files. Other features of interest
|
||||
are its workflow system, role based access control, and REST API.
|
||||
|
||||
.. image:: https://gitlab.com/mayan-edms/mayan-edms/raw/master/docs/_static/overview.gif
|
||||
:align: center
|
||||
:width: 300
|
||||
|
||||
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.
|
||||
|
||||
For the complete set of installation instructions visit the Mayan EDMS documentation
|
||||
at: https://docs.mayan-edms.com/topics/installation.html
|
||||
|
||||
.. _Docker: https://www.docker.com/
|
||||
|
||||
The pre-release version of the book "Exploring Mayan EDMS" available now at a discounted price!
|
||||
|
||||
.. image:: https://camo.githubusercontent.com/89d2fe787507c9247aa7bb406e2682b53eb7a5f9/68747470733a2f2f64313273776274773731397934732e636c6f756466726f6e742e6e65742f696d616765732f76365270785734302f615030714b4c6a6b50694175585a6859754234352f774441554c417a4679782e6a7065673f773d353438
|
||||
:align: center
|
||||
:width: 300
|
||||
:target: https://sellfy.com/p/um2fkx/
|
||||
|
||||
Limited quantities. Buyers of the pre-release will get the full version for free when it is ready.
|
||||
Click the image or visit: https://sellfy.com/p/um2fkx/
|
||||
|
||||
Hardware requirements
|
||||
|
||||
- 2 Gigabytes of RAM (1 Gigabyte if OCR is turned off).
|
||||
- Multiple core CPU (64 bit, faster than 1 GHz recommended).
|
||||
|
||||
|
||||
Important links
|
||||
|
||||
- `Homepage <http://www.mayan-edms.com>`__
|
||||
- `Documentation <https://docs.mayan-edms.com>`__
|
||||
- `Wiki <https://wiki.mayan-edms.com>`__
|
||||
- `Contributing <https://gitlab.com/mayan-edms/mayan-edms/blob/master/CONTRIBUTING.md>`__
|
||||
- `Forum <https://forum.mayan-edms.com>`__
|
||||
- `Source code, issues, bugs <https://gitlab.com/mayan-edms/mayan-edms>`__
|
||||
- `Plug-ins, other related projects <https://gitlab.com/mayan-edms/>`__
|
||||
- `Translations <https://www.transifex.com/rosarior/mayan-edms/>`__
|
||||
- `Videos <https://www.youtube.com/channel/UCJOOXHP1MJ9lVA7d8ZTlHPw>`__
|
||||
|
||||
|
||||
.. |donation| image:: https://img.shields.io/badge/donation-PayPal-brightgreen
|
||||
:target: https://paypal.me/MayanEDMS
|
||||
.. |pypi| image:: http://img.shields.io/pypi/v/mayan-edms.svg
|
||||
:target: http://badge.fury.io/py/mayan-edms
|
||||
.. |builds| image:: https://gitlab.com/mayan-edms/mayan-edms/badges/master/build.svg
|
||||
:target: https://gitlab.com/mayan-edms/mayan-edms/pipelines
|
||||
.. |coverage| image:: https://codecov.io/gitlab/mayan-edms/mayan-edms/coverage.svg?branch=master
|
||||
:target: https://codecov.io/gitlab/mayan-edms/mayan-edms?branch=master
|
||||
.. |python| image:: https://img.shields.io/pypi/pyversions/mayan-edms.svg
|
||||
.. |license| image:: https://img.shields.io/pypi/l/mayan-edms.svg?style=flat
|
||||
.. |docker_pulls| image:: https://img.shields.io/docker/pulls/mayanedms/mayanedms.svg?maxAge=3600
|
||||
:target: https://hub.docker.com/r/mayanedms/mayanedms/
|
||||
.. |docker_stars| image:: https://img.shields.io/docker/stars/mayanedms/mayanedms.svg?maxAge=3600
|
||||
:target: https://hub.docker.com/r/mayanedms/mayanedms/
|
||||
.. |docker_layers| image:: https://images.microbadger.com/badges/image/mayanedms/mayanedms.svg
|
||||
:target: https://microbadger.com/images/mayanedms/mayanedms
|
||||
@@ -1,14 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__title__ = 'Mayan EDMS'
|
||||
__version__ = '{{ version }}'
|
||||
__build__ = {{ build }}
|
||||
__build_string__ = '{{ build_string }}'
|
||||
__django_version__ = '1.11'
|
||||
__author__ = 'Roberto Rosario'
|
||||
__author_email__ = 'roberto.rosario@mayan-edms.com'
|
||||
__description__ = 'Free Open Source Electronic Document Management System'
|
||||
__license__ = 'Apache 2.0'
|
||||
__copyright_short__ = '2011 Roberto Rosario'
|
||||
__copyright__ = '{} {}'.format('Copyright', __copyright_short__)
|
||||
__website__ = 'https://www.mayan-edms.com'
|
||||
18
apps/acls/__init__.py
Normal file
18
apps/acls/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from navigation.api import bind_links, register_multi_item_links
|
||||
|
||||
from .classes import (AccessHolder, AccessObjectClass, ClassAccessHolder,
|
||||
AccessObject)
|
||||
from .links import (acl_detail, acl_grant, acl_revoke,
|
||||
acl_holder_new, acl_setup_valid_classes, acl_class_list,
|
||||
acl_class_acl_list, acl_class_acl_detail, acl_class_new_holder_for,
|
||||
acl_class_grant, acl_class_revoke)
|
||||
|
||||
bind_links([AccessHolder], [acl_detail])
|
||||
register_multi_item_links(['acl_detail'], [acl_grant, acl_revoke])
|
||||
bind_links([AccessObject], [acl_holder_new], menu_name='sidebar')
|
||||
bind_links(['acl_setup_valid_classes', 'acl_class_acl_list', 'acl_class_new_holder_for', 'acl_class_acl_detail', 'acl_class_multiple_grant', 'acl_class_multiple_revoke'], [acl_class_list], menu_name='secondary_menu')
|
||||
bind_links([ClassAccessHolder], [acl_class_acl_detail])
|
||||
bind_links([AccessObjectClass], [acl_class_acl_list, acl_class_new_holder_for])
|
||||
register_multi_item_links(['acl_class_acl_detail'], [acl_class_grant, acl_class_revoke])
|
||||
23
apps/acls/admin.py
Normal file
23
apps/acls/admin.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import AccessEntry
|
||||
|
||||
|
||||
#class PermissionHolderInline(admin.StackedInline):
|
||||
# model = PermissionHolder
|
||||
# extra = 1
|
||||
# classes = ('collapse-open',)
|
||||
# allow_add = True#
|
||||
#
|
||||
class AccessEntryAdmin(admin.ModelAdmin):
|
||||
related_lookup_fields = {
|
||||
'generic': [['holder_type', 'holder_id'], ['content_type', 'object_id']],
|
||||
}
|
||||
#inlines = [PermissionHolderInline]
|
||||
list_display = ('pk', 'holder_object', 'permission', 'content_object')
|
||||
list_display_links = ('pk',)
|
||||
model = AccessEntry
|
||||
|
||||
admin.site.register(AccessEntry, AccessEntryAdmin)
|
||||
28
apps/acls/api.py
Normal file
28
apps/acls/api.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
_class_permissions = {}
|
||||
|
||||
|
||||
def class_permissions(cls, permission_list):
|
||||
"""
|
||||
Associate a permissions list to a class
|
||||
"""
|
||||
stored_permissions = _class_permissions.setdefault(cls, [])
|
||||
stored_permissions.extend(permission_list)
|
||||
|
||||
|
||||
def get_class_permissions_for(obj):
|
||||
"""
|
||||
Return a list of permissions associated with a content type
|
||||
"""
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
return _class_permissions.get(content_type.model_class(), [])
|
||||
|
||||
|
||||
def get_classes():
|
||||
"""
|
||||
Return a list of encapsulated classes that have been registered
|
||||
"""
|
||||
return _class_permissions.keys()
|
||||
17
apps/acls/classes.py
Normal file
17
apps/acls/classes.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from common.classes import EncapsulatedObject
|
||||
|
||||
|
||||
class AccessHolder(EncapsulatedObject):
|
||||
source_object_name = u'holder_object'
|
||||
|
||||
|
||||
class AccessObject(EncapsulatedObject):
|
||||
source_object_name = u'obj'
|
||||
|
||||
|
||||
class AccessObjectClass(EncapsulatedObject):
|
||||
source_object_name = u'cls'
|
||||
|
||||
|
||||
class ClassAccessHolder(EncapsulatedObject):
|
||||
source_object_name = u'class_holder'
|
||||
8
apps/acls/cleanup.py
Normal file
8
apps/acls/cleanup.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from .models import AccessEntry, DefaultAccessEntry
|
||||
|
||||
|
||||
def cleanup():
|
||||
AccessEntry.objects.all().delete()
|
||||
DefaultAccessEntry.objects.all().delete()
|
||||
58
apps/acls/forms.py
Normal file
58
apps/acls/forms.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import User, Group
|
||||
|
||||
from permissions.models import Role
|
||||
from common.utils import get_object_name
|
||||
from common.models import AnonymousUserSingleton
|
||||
|
||||
from .classes import AccessHolder
|
||||
from .models import CreatorSingleton
|
||||
|
||||
|
||||
def _as_choice_list(holders):
|
||||
return sorted([(AccessHolder.encapsulate(holder).gid, get_object_name(holder, display_object_type=False)) for holder in holders], key=lambda x: x[1])
|
||||
|
||||
|
||||
class BaseHolderSelectionForm(forms.Form):
|
||||
holder_gid = forms.ChoiceField(
|
||||
label=_(u'New holder')
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
current_holders = kwargs.pop('current_holders', [])
|
||||
if current_holders:
|
||||
current_holders = [holder.source_object for holder in current_holders]
|
||||
|
||||
staff_users = User.objects.filter(is_staff=True)
|
||||
super_users = User.objects.filter(is_superuser=True)
|
||||
users = set(User.objects.filter(is_active=True)) - set(staff_users) - set(super_users) - set(current_holders)
|
||||
roles = set(Role.objects.all()) - set(current_holders)
|
||||
groups = set(Group.objects.all()) - set(current_holders)
|
||||
special = set(self.special_holders) - set(current_holders)
|
||||
|
||||
non_holder_list = []
|
||||
if users:
|
||||
non_holder_list.append((_(u'Users'), _as_choice_list(list(users))))
|
||||
|
||||
if groups:
|
||||
non_holder_list.append((_(u'Groups'), _as_choice_list(list(groups))))
|
||||
|
||||
if roles:
|
||||
non_holder_list.append((_(u'Roles'), _as_choice_list(list(roles))))
|
||||
|
||||
if special:
|
||||
non_holder_list.append((_(u'Special'), _as_choice_list(list(special))))
|
||||
|
||||
super(BaseHolderSelectionForm, self).__init__(*args, **kwargs)
|
||||
self.fields['holder_gid'].choices = non_holder_list
|
||||
|
||||
|
||||
class HolderSelectionForm(BaseHolderSelectionForm):
|
||||
special_holders = [AnonymousUserSingleton.objects.get()]
|
||||
|
||||
|
||||
class ClassHolderSelectionForm(BaseHolderSelectionForm):
|
||||
special_holders = [AnonymousUserSingleton.objects.get(), CreatorSingleton.objects.get()]
|
||||
20
apps/acls/icons.py
Normal file
20
apps/acls/icons.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from icons.literals import (KEY, KEY_GO, KEY_ADD, KEY_DELETE, LOCK, USER_ADD,
|
||||
PACKAGE, LOCK_GO)
|
||||
from icons import Icon
|
||||
|
||||
icon_acl_app = Icon(LOCK)
|
||||
|
||||
icon_acls = Icon(KEY)
|
||||
icon_acl_detail = Icon(KEY_GO)
|
||||
icon_acl_grant = Icon(KEY_ADD)
|
||||
icon_acl_revoke = Icon(KEY_DELETE)
|
||||
icon_acl_holder_new = Icon(USER_ADD)
|
||||
|
||||
icon_acl_class_list = Icon(PACKAGE)
|
||||
icon_acl_class_acl_list = Icon(LOCK_GO)
|
||||
icon_acl_class_acl_detail = Icon(KEY_GO)
|
||||
icon_acl_class_new_holder_for = Icon(USER_ADD)
|
||||
icon_acl_class_grant = Icon(KEY_ADD)
|
||||
icon_acl_class_revoke = Icon(KEY_DELETE)
|
||||
26
apps/acls/links.py
Normal file
26
apps/acls/links.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from navigation import Link
|
||||
|
||||
from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL,
|
||||
ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL)
|
||||
from .icons import (icon_acls, icon_acl_detail, icon_acl_grant, icon_acl_revoke,
|
||||
icon_acl_holder_new, icon_acl_class_list, icon_acl_class_acl_list,
|
||||
icon_acl_class_acl_list, icon_acl_class_acl_detail, icon_acl_class_new_holder_for,
|
||||
icon_acl_class_grant, icon_acl_class_revoke)
|
||||
|
||||
acl_list = Link(text=_(u'ACLs'), view='acl_list', icon=icon_acls, permissions=[ACLS_VIEW_ACL])
|
||||
acl_detail = Link(text=_(u'details'), view='acl_detail', args=['access_object.gid', 'object.gid'], icon=icon_acl_detail, permissions=[ACLS_VIEW_ACL])
|
||||
acl_grant = Link(text=_(u'grant'), view='acl_multiple_grant', icon=icon_acl_grant, permissions=[ACLS_EDIT_ACL])
|
||||
acl_revoke = Link(text=_(u'revoke'), view='acl_multiple_revoke', icon=icon_acl_revoke, permissions=[ACLS_EDIT_ACL])
|
||||
acl_holder_new = Link(text=_(u'New holder'), view='acl_holder_new', args='access_object.gid', icon=icon_acl_holder_new, permissions=[ACLS_EDIT_ACL])
|
||||
|
||||
acl_setup_valid_classes = Link(text=_(u'Default ACLs'), view='acl_setup_valid_classes', icon=icon_acl_class_list, permissions=[ACLS_CLASS_VIEW_ACL]) # 'children_view_regex=[r'^acl_class', r'^acl_setup']}
|
||||
acl_class_list = Link(text=_(u'List of classes'), view='acl_setup_valid_classes', icon=icon_acl_class_list, permissions=[ACLS_CLASS_VIEW_ACL])
|
||||
acl_class_acl_list = Link(text=_(u'ACLs for class'), view='acl_class_acl_list', args='object.gid', icon=icon_acl_class_acl_list, permissions=[ACLS_CLASS_VIEW_ACL])
|
||||
acl_class_acl_detail = Link(text=_(u'details'), view='acl_class_acl_detail', args=['access_object_class.gid', 'object.gid'], icon=icon_acl_class_acl_detail, permissions=[ACLS_CLASS_VIEW_ACL])
|
||||
acl_class_new_holder_for = Link(text=_(u'New holder'), view='acl_class_new_holder_for', args='object.gid', icon=icon_acl_class_new_holder_for, permissions=[ACLS_CLASS_EDIT_ACL])
|
||||
acl_class_grant = Link(text=_(u'grant'), view='acl_class_multiple_grant', icon=icon_acl_class_grant, permissions=[ACLS_CLASS_EDIT_ACL])
|
||||
acl_class_revoke = Link(text=_(u'revoke'), view='acl_class_multiple_revoke', icon=icon_acl_class_revoke, permissions=[ACLS_CLASS_EDIT_ACL])
|
||||
13
apps/acls/literals.py
Normal file
13
apps/acls/literals.py
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
# Content type <-> fam fam icon mapping
|
||||
CONTENT_TYPE_ICON_MAP = {
|
||||
'auth.user': 'user',
|
||||
'auth.group': 'group',
|
||||
'documents.document': 'page',
|
||||
'permissions.role': 'medal_gold_1',
|
||||
'folders.folder': 'folder',
|
||||
'taggit.tag': 'tag_blue',
|
||||
'linking.smartlink': 'page_link',
|
||||
'common.anonymoususersingleton': 'user',
|
||||
'acls.creatorsingleton': 'user',
|
||||
}
|
||||
BIN
apps/acls/locale/bg/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/bg/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
255
apps/acls/locale/bg/LC_MESSAGES/django.po
Normal file
255
apps/acls/locale/bg/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,255 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Iliya Georgiev <ikgeorgiev@gmail.com>, 2012.
|
||||
# <pkoldamov@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-10-15 10:27+0000\n"
|
||||
"Last-Translator: Pavlin Koldamov <pkoldamov@gmail.com>\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/bg/)\n"
|
||||
"Language: bg\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Нов притежател"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Потребители"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Групи"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Роли"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "детайли"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "предоставяне"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "отменя"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "Контролни списъци за достъп по подразбиране"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Списък на класовете"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "Контролни списъци за клас"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Недостатъчен достъп."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "разрешение"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "достъп за влизане"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "достъп вписвания"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "Контролни списъци за достъп"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "разрешения"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr " за %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr " към %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Сигурни ли сте, че искате да дадете разрешение за %(title_suffix)s?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Сигурни ли сте, че искате да дадете разрешения за %(title_suffix)s?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr " от %s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Сигурни ли сте, че искате да отнемете разрешението за %(title_suffix)s?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Сигурни ли сте, че искате да отнемете разрешенията за %(title_suffix)s?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "класове"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "клас"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr "правила за достъп по подразбиране за клас: %s"
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
BIN
apps/acls/locale/de_DE/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/de_DE/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
261
apps/acls/locale/de_DE/LC_MESSAGES/django.po
Normal file
261
apps/acls/locale/de_DE/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,261 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# <sl@suchreflex.de>, 2012.
|
||||
# <tilmann.sittig@web.de>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-09-20 07:40+0000\n"
|
||||
"Last-Translator: Manticor <sl@suchreflex.de>\n"
|
||||
"Language-Team: German (Germany) (http://www.transifex.com/projects/p/mayan-"
|
||||
"edms/language/de_DE/)\n"
|
||||
"Language: de_DE\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Neuer Berechtigter"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Gruppen"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Rollen"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "Details"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "Erlauben"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "Entziehen"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "Standard-ACLs"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Liste der Klassen"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACLs für Klasse"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Unzureichender Zugriff."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "Berechtigung"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "Zugriffsberechtigungseintrag"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "Zugriffsberechtigungseinträge"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr "Standard-Zugriffsberechtigungseintrag"
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr "Standard-Zugriffsberechtigungseinträge"
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Zugriffsberechtigungslisten (ACLs)"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "ACLs bearbeiten"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "ACLs anzeigen"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Standard-ACLs für Klasse bearbeiten"
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Standard-ACLs für Klasse anzeigen"
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr "Zugriffberechtigungsliste für: %s"
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr "Berechtigter"
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "Berechtigungen"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr "verfügbare Berechtigungen: %(actor)s für %(obj)s "
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr "Namensraum"
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr "Bezeichner"
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr "hat die Berechtigung"
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr "für %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr "zu %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Sind Sie sicher, dass Sie die Berechtigung %(title_suffix)s erteilen "
|
||||
"möchten?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Sind Sie sicher, dass Sie die Berechtigungen %(title_suffix)s erteilen "
|
||||
"möchten?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr "von %s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Sind Sie sicher, dass Sie die Berechtigung %(title_suffix)s enziehen "
|
||||
"möchten?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Sind Sie sicher, dass Sie die Berechtigungen %(title_suffix)s enziehen "
|
||||
"möchten?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr "neuen Berechtigten für %s hinzufügen"
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "Klassen"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "Klasse"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
BIN
apps/acls/locale/en/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/en/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
249
apps/acls/locale/en/LC_MESSAGES/django.po
Normal file
249
apps/acls/locale/en/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,249 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:10
|
||||
msgid "ACL"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
BIN
apps/acls/locale/es/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/es/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
253
apps/acls/locale/es/LC_MESSAGES/django.po
Normal file
253
apps/acls/locale/es/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,253 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-02-12 00:16+0000\n"
|
||||
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/es/)\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Nuevo titular"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Usuarios"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Grupos"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Funciones"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr "Especial"
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "LCA"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "detalles"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "otorgar"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "revocar"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "LCA por defecto"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Lista de clases"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "LCA para la clase"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Acceso insuficiente."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "permiso"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "entrada de acceso"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "entradas de acceso"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr "entrada de acceso por defecto"
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr "entradas de acceso por defecto"
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr "Creador"
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr "creador"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Listas de control de acceso"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Editar LCA"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "Ver LCA"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Editar LCA por defecto de la clase"
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Ver LCA por defecto de la clase"
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "LCA"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr "listas de control de acceso para: %s"
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr "titular"
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "permisos"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr "permisos disponibles a: %(actor)s para %(obj)s "
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr "espacio de nombres"
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr "etiqueta"
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr "tiene permiso"
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ", "
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr " para %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr " a %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "¿Está seguro que desea conceder el permiso %(title_suffix)s?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "¿Está seguro que desea conceder los permisos de %(title_suffix)s?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Permiso \"%(permission)s\" otorgado a %(actor)s para %(object)s."
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
"%(actor)s, ya tenía el permiso \"%(permission)s\", otorgado para %(object)s."
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr " de %s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "¿Está seguro que desea revocar el permiso %(title_suffix)s?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "¿Está seguro de querer revocar los permisos %(title_suffix)s?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr "Permiso \"%(permission)s\" revocado del %(actor)s para %(object)s."
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s, no tenía el permiso \"%(permission)s\" para %(object)s."
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr "añadir nuevo titular para: %s"
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr "Seleccionar"
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "clases"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "clase"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr "listas de control de acceso por defecto para la clase: %s"
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr "permisos disponibles para: %(actor)s para la clase %(class)s "
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr "añadir nuevo titular para la clase: %s"
|
||||
BIN
apps/acls/locale/fr/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/fr/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
258
apps/acls/locale/fr/LC_MESSAGES/django.po
Normal file
258
apps/acls/locale/fr/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,258 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Pierre Lhoste <peter.cathbad.host@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-07-28 15:20+0000\n"
|
||||
"Last-Translator: Pierre Lhoste <peter.cathbad.host@gmail.com>\n"
|
||||
"Language-Team: French (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/fr/)\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Nouveau détenteur"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Utilisateurs"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Groupes"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Rôles"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr "Spécial"
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "détails"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "autoriser"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "révoquer"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "ACLs par défaut"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Liste des classes"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACLs pour la classe"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Autorisations insuffisantes."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "autorisation"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "autorisation d'accès"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "autorisations d'accès"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr "autorisation d'accès par défaut"
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr "autorisations d'accès par défaut"
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr "Créateur"
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr "créateur"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Listes de contrôle d'accès (ACL)"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Modifier ACLs"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "Afficher ACLs"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Modifier ACLs par défaut"
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Afficher ACLs par défaut pour la classe"
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "ACLs"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr "Liste de contrôle d'accès (ACL) pour: %s"
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr "détenteur"
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "autorisations"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr "autorisations pour: %(actor)s for %(obj)s"
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr "espace de nommage"
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr "label"
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr "autorisation accordée "
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ","
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr "à %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr "sur %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Êtes vous certain de vouloir attribuer l'autorisation %(title_suffix)s?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Êtes vous certain de vouloir attribuer les autorisations %(title_suffix)s?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Autorisation \"%(permission)s\" accordée à %(actor)s sur %(object)s."
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
"%(actor)s, dispose déjà de l'autorisation \"%(permission)s\" accordée sur "
|
||||
"%(object)s."
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr "de %s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Êtes vous certain de vouloir révoquer l'autorisation %(title_suffix)s?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
"Êtes vous certain de vouloir révoquer les autorisations %(title_suffix)s?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
"Autorisation \"%(permission)s\" révoquée pour %(actor)s sur %(object)s."
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s, n'a pas l'autorisation \"%(permission)s\" sur %(object)s."
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr "ajouter un nouveau détenteur pour: %s"
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr "Sélectionner"
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "classes"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "classe"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr "liste de contrôle d'accès (ACL) par défaut pour: %s"
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr "autorisations attribuées à: %(actor)s sur la classe %(class)s"
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr "ajouter un nouveau détenteur sur la classe: %s"
|
||||
BIN
apps/acls/locale/it/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/it/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
254
apps/acls/locale/it/LC_MESSAGES/django.po
Normal file
254
apps/acls/locale/it/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,254 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Carlo Zanatto <>, 2012.
|
||||
# Pierpaolo Baldan <pierpaolo.baldan@gmail.com>, 2012.
|
||||
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-06-08 07:20+0000\n"
|
||||
"Last-Translator: Carlo Zanatto <>\n"
|
||||
"Language-Team: Italian (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/it/)\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Nuovo titolare"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Utenti"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Gruppi"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Ruoli"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr "Speciale"
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "ACL"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "dettagli"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "permetti"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "revocare"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "Default ACL"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Elenco delle classi"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACL per la classe"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Accesso insufficiente."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "autorizzazione"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "voce di accesso"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "voci di accesso"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr "accesso voce predefinita"
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr "voci di accesso predefinite "
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr "Creatore"
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr "creatore"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Liste di controllo accessi"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Modifica ACL"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "Visualizza ACL"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Modifica ACL predefiniti di classe"
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Visualizza classi ACL predefinite"
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "ACL"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr "lista controllo accessi per: %s"
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr "titolare"
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "le autorizzazioni"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr "autorizzazioni disponibili per: %(actor)s per %(obj)s "
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr "namespace"
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr "etichetta"
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr "ha l'autorizzazione"
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ", "
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr "per %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr "a %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Sei sicuro di voler concedere l'autorizzazione %(title_suffix)s?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Sei sicuro di voler concedere permessi %(title_suffix)s?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Permesso \"%(permission)s\" concesso%(actor)s per %(object)s."
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr "%(actor)s, ha già i permessi\"%(permission)s\" concessi per%(object)s."
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr "da %s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Sei sicuro di voler revocare l'autorizzazione %(title_suffix)s?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "Sei sicuro di voler revocare permessi %(title_suffix)s?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr "Permessi \"%(permission)s\" revocati al %(actor)s per %(object)s."
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s, non ha i permessi\"%(permission)s\" per %(object)s."
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr "aggiungi nuovo titolare per: %s"
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr "Selezionare"
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "classi"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "classe"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr "lista di default per il controllo accessi per la classe: %s"
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr "permessi disponibili per: %(actor)s per la classe %(class)s"
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr "aggiungi un nuovo titolare per la calsse: %s"
|
||||
BIN
apps/acls/locale/nl_NL/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/nl_NL/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
250
apps/acls/locale/nl_NL/LC_MESSAGES/django.po
Normal file
250
apps/acls/locale/nl_NL/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,250 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-01-02 09:45+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
|
||||
"mayan-edms/language/nl_NL/)\n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:10
|
||||
msgid "ACL"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
BIN
apps/acls/locale/pl/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/pl/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
251
apps/acls/locale/pl/LC_MESSAGES/django.po
Normal file
251
apps/acls/locale/pl/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,251 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-01-02 09:45+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Polish (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/pl/)\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:10
|
||||
msgid "ACL"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
BIN
apps/acls/locale/pt/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/pt/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
252
apps/acls/locale/pt/LC_MESSAGES/django.po
Normal file
252
apps/acls/locale/pt/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,252 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Vítor Figueiró <vfigueiro@gmail.com>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-07-03 19:01+0000\n"
|
||||
"Last-Translator: Vítor Figueiró <vfigueiro@gmail.com>\n"
|
||||
"Language-Team: Portuguese (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/pt/)\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Novo detentor"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Utilizadores"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Grupos"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Funções"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr "Especial"
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "ACL's"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "detalhes"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "conceder"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "revogar"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "ACL's padrão"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Lista de classes"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACL's para a classe"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Acesso insuficiente."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "permissão"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "entrada de acesso"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "entradas de acesso"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr "entrada de acesso padrão"
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr "entradas de acesso padrão"
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr "Criador"
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr "criador"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Listas de controlo de acesso"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Editar ACL's"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "Ver ACL's"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Editar os ACL's padrão da classe"
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Ver os ACL's padrão da classe"
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "ACL's"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr "listas de controlo de acesso para: %s"
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr "detentor"
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "permissões"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr "permissões disponíveis para: %(actor)s para %(obj)s"
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr "escopo"
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr "rótulo"
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr "tem a permissão"
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ", "
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr " para %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr " a %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Tem a certeza de que pretende conceder a permissão %(title_suffix)s?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Tem a certeza de que pretende conceder as permissões %(title_suffix)s?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Permissão \"%(permission)s\" concedida a %(actor)s para %(object)s."
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr "%(actor)s, já possuia a permissão \"%(permission)s\" para %(object)s."
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr " de %s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Tem a certeza de que pretende revogar a permissão %(title_suffix)s?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "Tem a certeza de que pretende revogar as permissões %(title_suffix)s?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr "Permissão \"%(permission)s\" revogada para %(actor)s para %(object)s."
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s, não tinha a permissão \"%(permission)s\" para %(object)s."
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr "adicionar novo detentor para: %s"
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr "Selecionar"
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "classes"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "classe"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr "Listas de controlo de acesso padrão para a classe: %s"
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr "permissões disponíveis para: %(actor)s para a classe %(class)s"
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr "adicionar novo detentor para a classe: %s"
|
||||
BIN
apps/acls/locale/pt_BR/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/pt_BR/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
250
apps/acls/locale/pt_BR/LC_MESSAGES/django.po
Normal file
250
apps/acls/locale/pt_BR/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,250 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-01-02 09:45+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
|
||||
"mayan-edms/language/pt_BR/)\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr ""
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:10
|
||||
msgid "ACL"
|
||||
msgstr ""
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
BIN
apps/acls/locale/ru/LC_MESSAGES/django.mo
Normal file
BIN
apps/acls/locale/ru/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
253
apps/acls/locale/ru/LC_MESSAGES/django.po
Normal file
253
apps/acls/locale/ru/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,253 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Sergey Glita <gsv70@mail.ru>, 2012.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-14 04:18-0400\n"
|
||||
"PO-Revision-Date: 2012-02-27 04:26+0000\n"
|
||||
"Last-Translator: Sergey Glita <gsv70@mail.ru>\n"
|
||||
"Language-Team: Russian (http://www.transifex.com/projects/p/mayan-edms/"
|
||||
"language/ru/)\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: forms.py:21 links.py:18 links.py:24
|
||||
msgid "New holder"
|
||||
msgstr "Новый владелец"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr "Пользователи"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr "Группы"
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr "Роли"
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr "Специальный"
|
||||
|
||||
#: links.py:14
|
||||
msgid "ACLs"
|
||||
msgstr "Списки ACL"
|
||||
|
||||
#: links.py:15 links.py:23
|
||||
msgid "details"
|
||||
msgstr "детали"
|
||||
|
||||
#: links.py:16 links.py:25
|
||||
msgid "grant"
|
||||
msgstr "предоставить"
|
||||
|
||||
#: links.py:17 links.py:26
|
||||
msgid "revoke"
|
||||
msgstr "отозвать"
|
||||
|
||||
#: links.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr "ACL по умолчанию"
|
||||
|
||||
#: links.py:21
|
||||
msgid "List of classes"
|
||||
msgstr "Список классов"
|
||||
|
||||
#: links.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr "ACL для класса"
|
||||
|
||||
#: managers.py:119 managers.py:131
|
||||
msgid "Insufficient access."
|
||||
msgstr "Недостаточный доступ."
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr "разрешение"
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr "запись доступа"
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr "записи доступа"
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr "запись доступа по умолчанию"
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr "записи доступа по умолчанию"
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr "Создатель"
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr "создатель"
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr "Списки контроля доступа"
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr "Редактировать списки ACL"
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr "Просмотр списков ACL"
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr "Редактировать списки ACL класса по умолчанию"
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr "Просмотр списков ACL класса по умолчанию"
|
||||
|
||||
#: registry.py:10
|
||||
#, fuzzy
|
||||
msgid "ACL"
|
||||
msgstr "Списки ACL"
|
||||
|
||||
#: registry.py:11
|
||||
msgid "Handles object level access control."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr "списки контроля доступа для %s"
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr "владелец"
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr "разрешения"
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr "разрешения, доступные %(actor)s для %(obj)s"
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr "пространство имен"
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr "этикетка"
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr "имеет разрешение"
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ","
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr "для %s"
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr "до %s"
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr "Вы действительно хотите предоставить разрешение %(title_suffix)s?"
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr "Вы уверены, что хотите предоставить разрешения %(title_suffix)s?"
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr "Право \"%(permission)s\" проедоставлено %(actor)s для %(object)s."
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr "%(actor)s, уже имеет право \"%(permission)s\" для %(object)s."
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr "от%s"
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr "Вы уверены, что хотите отменить разрешение %(title_suffix)s?"
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr "Вы уверены, что хотите отменить разрешение %(title_suffix)s?"
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr "Право \"%(permission)s\" для %(object)s отозвано у %(actor)s."
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr "%(actor)s не имеет права \"%(permission)s\" для %(object)s."
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr "добавить нового владельца для %s"
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr "Выбор"
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr "классы"
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr "класс"
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr "списки контроля доступа умолчанию для класса %s"
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr "разрешения доступные %(actor)s для класса %(class)s"
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr "добавить нового владельца для класса %s"
|
||||
241
apps/acls/locale/sl_SI/LC_MESSAGES/django.po
Normal file
241
apps/acls/locale/sl_SI/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,241 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Mayan EDMS\n"
|
||||
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
|
||||
"POT-Creation-Date: 2012-12-12 01:48-0400\n"
|
||||
"PO-Revision-Date: 2012-01-02 09:45+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Slovenian (Slovenia) (http://www.transifex.com/projects/p/mayan-edms/language/sl_SI/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: sl_SI\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||
|
||||
#: __init__.py:14
|
||||
msgid "ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:15 __init__.py:23
|
||||
msgid "details"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:16 __init__.py:25
|
||||
msgid "grant"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:17 __init__.py:26
|
||||
msgid "revoke"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:18 __init__.py:24 forms.py:21
|
||||
msgid "New holder"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:20
|
||||
msgid "Default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:21
|
||||
msgid "List of classes"
|
||||
msgstr ""
|
||||
|
||||
#: __init__.py:22
|
||||
msgid "ACLs for class"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:44
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:47
|
||||
msgid "Special"
|
||||
msgstr ""
|
||||
|
||||
#: managers.py:118 managers.py:130
|
||||
msgid "Insufficient access."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25 models.py:67
|
||||
msgid "permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:51
|
||||
msgid "access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
msgid "access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "default access entry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "default access entries"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:108
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:111 models.py:112
|
||||
msgid "creator"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:7 permissions.py:8
|
||||
msgid "Access control lists"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:10
|
||||
msgid "Edit ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:11
|
||||
msgid "View ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:13
|
||||
msgid "Edit class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: permissions.py:14
|
||||
msgid "View class default ACLs"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:47
|
||||
#, python-format
|
||||
msgid "access control lists for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:49 views.py:409
|
||||
msgid "holder"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:50 views.py:410
|
||||
msgid "permissions"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:97
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for %(obj)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:104 views.py:442
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:105 views.py:443
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:107 views.py:445
|
||||
msgid "has permission"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:184 views.py:277 views.py:525 views.py:604
|
||||
msgid ", "
|
||||
msgstr ""
|
||||
|
||||
#: views.py:185 views.py:278 views.py:526 views.py:605
|
||||
#, python-format
|
||||
msgid " for %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:186 views.py:527
|
||||
#, python-format
|
||||
msgid " to %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:189 views.py:530
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:191 views.py:532
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:198 views.py:539
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:204 views.py:545
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%(actor)s, already had the permission \"%(permission)s\" granted for "
|
||||
"%(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:279 views.py:606
|
||||
#, python-format
|
||||
msgid " from %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:282 views.py:609
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:284 views.py:611
|
||||
#, python-format
|
||||
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:291 views.py:618
|
||||
#, python-format
|
||||
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:297 views.py:624
|
||||
#, python-format
|
||||
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
|
||||
msgstr ""
|
||||
|
||||
#: views.py:353
|
||||
#, python-format
|
||||
msgid "add new holder for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:354 views.py:486
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:386
|
||||
msgid "classes"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:388
|
||||
msgid "class"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:407
|
||||
#, python-format
|
||||
msgid "default access control lists for class: %s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:435
|
||||
#, python-format
|
||||
msgid "permissions available to: %(actor)s for class %(class)s"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:484
|
||||
#, python-format
|
||||
msgid "add new holder for class: %s"
|
||||
msgstr ""
|
||||
331
apps/acls/managers.py
Normal file
331
apps/acls/managers.py
Normal file
@@ -0,0 +1,331 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db.models import Q
|
||||
|
||||
from common.models import AnonymousUserSingleton
|
||||
from common.classes import get_source_object
|
||||
from permissions.models import Permission, RoleMember
|
||||
|
||||
from .classes import AccessHolder, ClassAccessHolder
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccessEntryManager(models.Manager):
|
||||
"""
|
||||
Implement a 3 tier permission system, involving a permissions, an actor
|
||||
and an object
|
||||
"""
|
||||
def grant(self, permission, actor, obj):
|
||||
"""
|
||||
Grant a permission (what), (to) an actor, (on) a specific object
|
||||
"""
|
||||
obj = get_source_object(obj)
|
||||
actor = get_source_object(actor)
|
||||
|
||||
access_entry, created = self.model.objects.get_or_create(
|
||||
permission=permission,
|
||||
holder_type=ContentType.objects.get_for_model(actor),
|
||||
holder_id=actor.pk,
|
||||
content_type=ContentType.objects.get_for_model(obj),
|
||||
object_id=obj.pk
|
||||
)
|
||||
return created
|
||||
|
||||
def revoke(self, permission, actor, obj):
|
||||
"""
|
||||
Revoke a permission (what), (from) an actor, (on) a specific object
|
||||
"""
|
||||
obj = get_source_object(obj)
|
||||
actor = get_source_object(actor)
|
||||
|
||||
try:
|
||||
access_entry = self.model.objects.get(
|
||||
permission=permission,
|
||||
holder_type=ContentType.objects.get_for_model(actor),
|
||||
holder_id=actor.pk,
|
||||
content_type=ContentType.objects.get_for_model(obj),
|
||||
object_id=obj.pk
|
||||
)
|
||||
except self.model.DoesNotExist:
|
||||
return False
|
||||
else:
|
||||
access_entry.delete()
|
||||
return True
|
||||
|
||||
def has_access(self, permission, actor, obj, db_only=False):
|
||||
"""
|
||||
Returns whether an actor has a specific permission for an object
|
||||
"""
|
||||
obj = get_source_object(obj)
|
||||
actor = get_source_object(actor)
|
||||
|
||||
if isinstance(actor, User) and db_only == False:
|
||||
# db_only causes the return of only the stored permissions
|
||||
# and not the perceived permissions for an actor
|
||||
if actor.is_superuser or actor.is_staff:
|
||||
return True
|
||||
|
||||
actor = AnonymousUserSingleton.objects.passthru_check(actor)
|
||||
try:
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
except AttributeError:
|
||||
# Object doesn't have a content type, therefore allow access
|
||||
return True
|
||||
|
||||
try:
|
||||
self.model.objects.get(
|
||||
permission=permission.get_stored_permission(),
|
||||
holder_type=ContentType.objects.get_for_model(actor),
|
||||
holder_id=actor.pk,
|
||||
content_type=content_type,
|
||||
object_id=obj.pk
|
||||
)
|
||||
except self.model.DoesNotExist:
|
||||
# If not check if the actor's memberships is one of
|
||||
# the access's holder?
|
||||
roles = RoleMember.objects.get_roles_for_member(actor)
|
||||
|
||||
if isinstance(actor, User):
|
||||
groups = actor.groups.all()
|
||||
else:
|
||||
groups = []
|
||||
|
||||
for membership in list(set(roles) | set(groups)):
|
||||
if self.has_access(permission, membership, obj, db_only):
|
||||
return True
|
||||
|
||||
logger.debug('Fallthru')
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def check_access(self, permission, actor, obj):
|
||||
# TODO: Merge with has_access
|
||||
obj = get_source_object(obj)
|
||||
actor = get_source_object(actor)
|
||||
|
||||
if self.has_access(permission, actor, obj):
|
||||
return True
|
||||
else:
|
||||
raise PermissionDenied(ugettext(u'Insufficient access.'))
|
||||
|
||||
def check_accesses(self, permission_list, actor, obj):
|
||||
"""
|
||||
Returns whether an actor has at least one of a list of permissions for an object
|
||||
"""
|
||||
obj = get_source_object(obj)
|
||||
actor = get_source_object(actor)
|
||||
for permission in permission_list:
|
||||
if self.has_access(permission, actor, obj):
|
||||
return True
|
||||
|
||||
raise PermissionDenied(ugettext(u'Insufficient access.'))
|
||||
|
||||
def get_allowed_class_objects(self, permission, actor, cls, related=None):
|
||||
logger.debug('related: %s' % related)
|
||||
|
||||
actor = AnonymousUserSingleton.objects.passthru_check(actor)
|
||||
actor_type = ContentType.objects.get_for_model(actor)
|
||||
content_type = ContentType.objects.get_for_model(cls)
|
||||
|
||||
# Calculate actor role membership ACL query
|
||||
total_queries = Q()
|
||||
for role in RoleMember.objects.get_roles_for_member(actor):
|
||||
role_type = ContentType.objects.get_for_model(role)
|
||||
if related:
|
||||
query = Q(holder_type=role_type, holder_id=role.pk, permission=permission.get_stored_permission)
|
||||
else:
|
||||
query = Q(holder_type=role_type, holder_id=role.pk, content_type=content_type, permission=permission.get_stored_permission)
|
||||
if not total_queries:
|
||||
total_queries = query
|
||||
else:
|
||||
total_queries = total_queries | query
|
||||
|
||||
# Calculate actor group membership ACL query
|
||||
if isinstance(actor, User):
|
||||
groups = actor.groups.all()
|
||||
else:
|
||||
groups = []
|
||||
|
||||
for group in groups:
|
||||
group_type = ContentType.objects.get_for_model(group)
|
||||
if related:
|
||||
query = Q(holder_type=group_type, holder_id=group.pk, permission=permission.get_stored_permission)
|
||||
else:
|
||||
query = Q(holder_type=group_type, holder_id=group.pk, content_type=content_type, permission=permission.get_stored_permission)
|
||||
if not total_queries:
|
||||
total_queries = query
|
||||
else:
|
||||
total_queries = total_queries | query
|
||||
|
||||
if related:
|
||||
actor_query = Q(holder_type=actor_type, holder_id=actor.pk, permission=permission.get_stored_permission)
|
||||
master_list = [obj.content_object for obj in self.model.objects.select_related().filter(actor_query | total_queries)]
|
||||
logger.debug('master_list: %s' % master_list)
|
||||
# TODO: update to use Q objects and check performance diff
|
||||
# kwargs = {'%s__in' % related: master_list}
|
||||
# Q(**kwargs)
|
||||
return (obj for obj in cls.objects.all() if getattr(obj, related) in master_list)
|
||||
else:
|
||||
actor_query = Q(holder_type=actor_type, holder_id=actor.pk, content_type=content_type, permission=permission.get_stored_permission)
|
||||
return (obj.content_object for obj in self.model.objects.filter(actor_query | total_queries))
|
||||
|
||||
def get_acl_url(self, obj):
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
return reverse('acl_list', args=[content_type.app_label, content_type.model, obj.pk])
|
||||
|
||||
def get_new_holder_url(self, obj):
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
return reverse('acl_new_holder_for', args=[content_type.app_label, content_type.model, obj.pk])
|
||||
|
||||
def get_holders_for(self, obj):
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
holder_list = []
|
||||
for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk):
|
||||
if access_entry.holder_object:
|
||||
# Don't add references to non existant content type objects
|
||||
entry = AccessHolder.encapsulate(access_entry.holder_object)
|
||||
|
||||
if entry not in holder_list:
|
||||
holder_list.append(entry)
|
||||
|
||||
return holder_list
|
||||
|
||||
def get_holder_permissions_for(self, obj, actor, db_only=False):
|
||||
"""
|
||||
Returns a list of actors that hold at least one permission for
|
||||
a specific object
|
||||
"""
|
||||
logger.debug('obj: %s' % obj)
|
||||
logger.debug('actor: %s' % actor)
|
||||
|
||||
if isinstance(actor, User) and db_only == False:
|
||||
if actor.is_superuser or actor.is_staff:
|
||||
return Permission.objects.all()
|
||||
|
||||
actor_type = ContentType.objects.get_for_model(actor)
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
return (access.permission for access in self.model.objects.filter(content_type=content_type, object_id=obj.pk, holder_type=actor_type, holder_id=actor.pk))
|
||||
|
||||
def filter_objects_by_access(self, permission, actor, object_list, exception_on_empty=False, related=None):
|
||||
"""
|
||||
Filter a list of objects or a QuerySet elements depending on
|
||||
whether the actor holds the specified permission
|
||||
"""
|
||||
logger.debug('exception_on_empty: %s' % exception_on_empty)
|
||||
logger.debug('object_list: %s' % object_list)
|
||||
|
||||
if isinstance(actor, User):
|
||||
if actor.is_superuser or actor.is_staff:
|
||||
return object_list
|
||||
|
||||
try:
|
||||
if object_list.count() == 0:
|
||||
return object_list
|
||||
except TypeError:
|
||||
# object_list is not a queryset
|
||||
if len(object_list) == 0:
|
||||
return object_list
|
||||
|
||||
try:
|
||||
# Try to process as a QuerySet
|
||||
qs = object_list.filter(pk__in=[obj.pk for obj in self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)])
|
||||
logger.debug('qs: %s' % qs)
|
||||
|
||||
if qs.count() == 0 and exception_on_empty == True:
|
||||
raise PermissionDenied
|
||||
|
||||
return qs
|
||||
except AttributeError:
|
||||
# Fallback to a filtered list
|
||||
object_list = list(set(object_list) & set(self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)))
|
||||
logger.debug('object_list: %s' % object_list)
|
||||
if len(object_list) == 0 and exception_on_empty == True:
|
||||
raise PermissionDenied
|
||||
|
||||
return object_list
|
||||
|
||||
|
||||
class DefaultAccessEntryManager(models.Manager):
|
||||
"""
|
||||
Implement a 3 tier permission system, involving a permission, an actor
|
||||
and a class or content type. This model keeps track of the access
|
||||
control lists that will be added when an instance of the recorded
|
||||
content type is created.
|
||||
"""
|
||||
def get_holders_for(self, cls):
|
||||
cls = get_source_object(cls)
|
||||
content_type = ContentType.objects.get_for_model(cls)
|
||||
holder_list = []
|
||||
for access_entry in self.model.objects.filter(content_type=content_type):
|
||||
if access_entry.holder_object:
|
||||
# Don't add references to non existant content type objects
|
||||
entry = ClassAccessHolder.encapsulate(access_entry.holder_object)
|
||||
|
||||
if entry not in holder_list:
|
||||
holder_list.append(entry)
|
||||
|
||||
return holder_list
|
||||
|
||||
def has_access(self, permission, actor, cls):
|
||||
if isinstance(actor, User):
|
||||
if actor.is_superuser or actor.is_staff:
|
||||
return True
|
||||
|
||||
try:
|
||||
self.model.objects.get(
|
||||
permission=permission.get_stored_permission(),
|
||||
holder_type=ContentType.objects.get_for_model(actor),
|
||||
holder_id=actor.pk,
|
||||
content_type=ContentType.objects.get_for_model(cls),
|
||||
)
|
||||
except self.model.DoesNotExist:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def grant(self, permission, actor, cls):
|
||||
"""
|
||||
Grant a permission (what), (to) an actor, (on) a specific class
|
||||
"""
|
||||
access_entry, created = self.model.objects.get_or_create(
|
||||
permission=permission,
|
||||
holder_type=ContentType.objects.get_for_model(actor),
|
||||
holder_id=actor.pk,
|
||||
content_type=ContentType.objects.get_for_model(cls),
|
||||
)
|
||||
return created
|
||||
|
||||
def revoke(self, permission, actor, cls):
|
||||
"""
|
||||
Revoke a permission (what), (from) an actor, (on) a specific class
|
||||
"""
|
||||
try:
|
||||
access_entry = self.model.objects.get(
|
||||
permission=permission,
|
||||
holder_type=ContentType.objects.get_for_model(actor),
|
||||
holder_id=actor.pk,
|
||||
content_type=ContentType.objects.get_for_model(cls),
|
||||
)
|
||||
access_entry.delete()
|
||||
return True
|
||||
except self.model.DoesNotExist:
|
||||
return False
|
||||
|
||||
def get_holder_permissions_for(self, cls, actor):
|
||||
if isinstance(actor, User):
|
||||
if actor.is_superuser or actor.is_staff:
|
||||
return Permission.objects.all()
|
||||
|
||||
actor_type = ContentType.objects.get_for_model(actor)
|
||||
content_type = ContentType.objects.get_for_model(cls)
|
||||
return [access.permission for access in self.model.objects.filter(content_type=content_type, holder_type=actor_type, holder_id=actor.pk)]
|
||||
89
apps/acls/migrations/0001_initial.py
Normal file
89
apps/acls/migrations/0001_initial.py
Normal file
@@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'AccessEntry'
|
||||
db.create_table('acls_accessentry', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('permission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['permissions.StoredPermission'])),
|
||||
('holder_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='access_holder', to=orm['contenttypes.ContentType'])),
|
||||
('holder_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
|
||||
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='object_content_type', to=orm['contenttypes.ContentType'])),
|
||||
('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
|
||||
))
|
||||
db.send_create_signal('acls', ['AccessEntry'])
|
||||
|
||||
# Adding model 'DefaultAccessEntry'
|
||||
db.create_table('acls_defaultaccessentry', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('permission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['permissions.StoredPermission'])),
|
||||
('holder_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='default_access_entry_holder', to=orm['contenttypes.ContentType'])),
|
||||
('holder_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
|
||||
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='default_access_entry_class', to=orm['contenttypes.ContentType'])),
|
||||
))
|
||||
db.send_create_signal('acls', ['DefaultAccessEntry'])
|
||||
|
||||
# Adding model 'CreatorSingleton'
|
||||
db.create_table('acls_creatorsingleton', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('lock_id', self.gf('django.db.models.fields.CharField')(default=1, unique=True, max_length=1)),
|
||||
))
|
||||
db.send_create_signal('acls', ['CreatorSingleton'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'AccessEntry'
|
||||
db.delete_table('acls_accessentry')
|
||||
|
||||
# Deleting model 'DefaultAccessEntry'
|
||||
db.delete_table('acls_defaultaccessentry')
|
||||
|
||||
# Deleting model 'CreatorSingleton'
|
||||
db.delete_table('acls_creatorsingleton')
|
||||
|
||||
|
||||
models = {
|
||||
'acls.accessentry': {
|
||||
'Meta': {'object_name': 'AccessEntry'},
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'object_content_type'", 'to': "orm['contenttypes.ContentType']"}),
|
||||
'holder_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
|
||||
'holder_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'access_holder'", 'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
|
||||
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.StoredPermission']"})
|
||||
},
|
||||
'acls.creatorsingleton': {
|
||||
'Meta': {'object_name': 'CreatorSingleton'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'lock_id': ('django.db.models.fields.CharField', [], {'default': '1', 'unique': 'True', 'max_length': '1'})
|
||||
},
|
||||
'acls.defaultaccessentry': {
|
||||
'Meta': {'object_name': 'DefaultAccessEntry'},
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'default_access_entry_class'", 'to': "orm['contenttypes.ContentType']"}),
|
||||
'holder_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
|
||||
'holder_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'default_access_entry_holder'", 'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.StoredPermission']"})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'permissions.storedpermission': {
|
||||
'Meta': {'ordering': "('namespace',)", 'unique_together': "(('namespace', 'name'),)", 'object_name': 'StoredPermission'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'namespace': ('django.db.models.fields.CharField', [], {'max_length': '64'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['acls']
|
||||
112
apps/acls/models.py
Normal file
112
apps/acls/models.py
Normal file
@@ -0,0 +1,112 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.contenttypes import generic
|
||||
|
||||
from permissions.models import StoredPermission
|
||||
from common.models import Singleton, SingletonManager
|
||||
|
||||
from .managers import AccessEntryManager, DefaultAccessEntryManager
|
||||
from .classes import AccessObjectClass
|
||||
from .api import get_classes
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccessEntry(models.Model):
|
||||
"""
|
||||
Model that hold the permission, object, actor relationship
|
||||
"""
|
||||
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
|
||||
|
||||
holder_type = models.ForeignKey(
|
||||
ContentType,
|
||||
related_name='access_holder',
|
||||
limit_choices_to={'model__in': ('user', 'group', 'role')}
|
||||
)
|
||||
holder_id = models.PositiveIntegerField()
|
||||
holder_object = generic.GenericForeignKey(
|
||||
ct_field='holder_type',
|
||||
fk_field='holder_id'
|
||||
)
|
||||
|
||||
content_type = models.ForeignKey(
|
||||
ContentType,
|
||||
related_name='object_content_type'
|
||||
)
|
||||
object_id = models.PositiveIntegerField()
|
||||
content_object = generic.GenericForeignKey(
|
||||
ct_field='content_type',
|
||||
fk_field='object_id'
|
||||
)
|
||||
|
||||
objects = AccessEntryManager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'access entry')
|
||||
verbose_name_plural = _(u'access entries')
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s: %s' % (self.content_type, self.content_object)
|
||||
|
||||
|
||||
class DefaultAccessEntry(models.Model):
|
||||
"""
|
||||
Model that holds the permission, class, actor relationship, that will
|
||||
be added upon the creation of an instance of said class
|
||||
"""
|
||||
@classmethod
|
||||
def get_classes(cls):
|
||||
return [AccessObjectClass.encapsulate(cls) for cls in get_classes()]
|
||||
|
||||
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
|
||||
|
||||
holder_type = models.ForeignKey(
|
||||
ContentType,
|
||||
limit_choices_to={'model__in': ('user', 'group', 'role')},
|
||||
related_name='default_access_entry_holder'
|
||||
)
|
||||
holder_id = models.PositiveIntegerField()
|
||||
holder_object = generic.GenericForeignKey(
|
||||
ct_field='holder_type',
|
||||
fk_field='holder_id'
|
||||
)
|
||||
|
||||
content_type = models.ForeignKey(
|
||||
ContentType,
|
||||
related_name='default_access_entry_class'
|
||||
)
|
||||
|
||||
objects = DefaultAccessEntryManager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'default access entry')
|
||||
verbose_name_plural = _(u'default access entries')
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s: %s' % (self.content_type, self.content_object)
|
||||
|
||||
|
||||
class CreatorSingletonManager(SingletonManager):
|
||||
def passthru_check(self, holder, creator=None):
|
||||
if isinstance(holder, self.model):
|
||||
# TODO: raise explicit error if is instance and creator=None
|
||||
return creator
|
||||
else:
|
||||
return holder
|
||||
|
||||
|
||||
class CreatorSingleton(Singleton):
|
||||
objects = CreatorSingletonManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return ugettext('Creator')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'creator')
|
||||
verbose_name_plural = _(u'creator')
|
||||
14
apps/acls/permissions.py
Normal file
14
apps/acls/permissions.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from permissions.models import PermissionNamespace, Permission
|
||||
|
||||
acls_namespace = PermissionNamespace('acls', _(u'Access control lists'))
|
||||
acls_setup_namespace = PermissionNamespace('acls_setup', _(u'Access control lists'))
|
||||
|
||||
ACLS_EDIT_ACL = Permission.objects.register(acls_namespace, 'acl_edit', _(u'Edit ACLs'))
|
||||
ACLS_VIEW_ACL = Permission.objects.register(acls_namespace, 'acl_view', _(u'View ACLs'))
|
||||
|
||||
ACLS_CLASS_EDIT_ACL = Permission.objects.register(acls_setup_namespace, 'acl_class_edit', _(u'Edit class default ACLs'))
|
||||
ACLS_CLASS_VIEW_ACL = Permission.objects.register(acls_setup_namespace, 'acl_class_view', _(u'View class default ACLs'))
|
||||
20
apps/acls/registry.py
Normal file
20
apps/acls/registry.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .cleanup import cleanup
|
||||
from .icons import icon_acl_app
|
||||
from .links import acl_setup_valid_classes
|
||||
|
||||
name = 'acls'
|
||||
label = _(u'ACL')
|
||||
description = _(u'Handles object level access control.')
|
||||
icon = icon_acl_app
|
||||
setup_links = [acl_setup_valid_classes]
|
||||
dependencies = ['app_registry', 'permissions', 'navigation']
|
||||
bootstrap_models = [
|
||||
{
|
||||
'name': 'defaultaccessentry',
|
||||
},
|
||||
]
|
||||
cleanup_functions = [cleanup]
|
||||
BIN
apps/acls/static/images/icons/lock.png
Normal file
BIN
apps/acls/static/images/icons/lock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
71
apps/acls/templatetags/acl_tags.py
Normal file
71
apps/acls/templatetags/acl_tags.py
Normal file
@@ -0,0 +1,71 @@
|
||||
import logging
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.template import (TemplateSyntaxError, Library,
|
||||
Node, Variable, VariableDoesNotExist)
|
||||
|
||||
|
||||
from acls.models import AccessEntry
|
||||
|
||||
register = Library()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CheckAccessNode(Node):
|
||||
def __init__(self, permission_list=None, requester=None, obj=None, *args, **kwargs):
|
||||
self.requester = requester
|
||||
self.permission_list = permission_list
|
||||
self.obj = obj
|
||||
|
||||
def render(self, context):
|
||||
permission_list = Variable(self.permission_list).resolve(context)
|
||||
logger.debug('permission_list: %s' % u','.join([unicode(p) for p in permission_list]))
|
||||
|
||||
try:
|
||||
# Check access_object, useful for document_page views
|
||||
obj = Variable('access_object').resolve(context)
|
||||
logger.debug('access_object: %s' % obj)
|
||||
except VariableDoesNotExist:
|
||||
try:
|
||||
obj = Variable(self.obj).resolve(context)
|
||||
logger.debug('obj: %s' % obj)
|
||||
except VariableDoesNotExist:
|
||||
context[u'access'] = False
|
||||
logger.debug('no obj, access False')
|
||||
return u''
|
||||
|
||||
if not permission_list:
|
||||
# There is no permissions list to check against which means
|
||||
# this link is available for all
|
||||
context[u'access'] = True
|
||||
return u''
|
||||
|
||||
requester = Variable(self.requester).resolve(context)
|
||||
logger.debug('requester: %s' % requester)
|
||||
|
||||
if obj:
|
||||
try:
|
||||
AccessEntry.objects.check_accesses(permission_list, requester, obj)
|
||||
except PermissionDenied:
|
||||
context[u'access'] = False
|
||||
logger.debug('access: False')
|
||||
return u''
|
||||
else:
|
||||
context[u'access'] = True
|
||||
logger.debug('access: True')
|
||||
return u''
|
||||
else:
|
||||
context[u'access'] = False
|
||||
logger.debug('No object, access: False')
|
||||
return u''
|
||||
|
||||
|
||||
@register.tag
|
||||
def check_access(parser, token):
|
||||
try:
|
||||
# Splitting by None == splitting by spaces.
|
||||
tag_name, args = token.contents.split(None, 1)
|
||||
except ValueError:
|
||||
raise TemplateSyntaxError(u'%r tag requires arguments' % token.contents.split()[0])
|
||||
|
||||
return CheckAccessNode(*args.split())
|
||||
20
apps/acls/urls.py
Normal file
20
apps/acls/urls.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
urlpatterns = patterns('acls.views',
|
||||
url(r'^new_holder_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_new_holder_for', (), 'acl_new_holder_for'),
|
||||
url(r'^list_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_list', (), 'acl_list'),
|
||||
url(r'^details/(?P<access_object_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_detail', (), 'acl_detail'),
|
||||
url(r'^holder/new/(?P<access_object_gid>[.\w]+)/$', 'acl_holder_new', (), 'acl_holder_new'),
|
||||
|
||||
url(r'^multiple/grant/$', 'acl_grant', (), 'acl_multiple_grant'),
|
||||
url(r'^multiple/revoke/$', 'acl_revoke', (), 'acl_multiple_revoke'),
|
||||
|
||||
url(r'^class/$', 'acl_setup_valid_classes', (), 'acl_setup_valid_classes'),
|
||||
url(r'^class/details/(?P<access_object_class_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_class_acl_detail', (), 'acl_class_acl_detail'),
|
||||
url(r'^class/list_for/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_acl_list', (), 'acl_class_acl_list'),
|
||||
url(r'^class/holder/new/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_new_holder_for', (), 'acl_class_new_holder_for'),
|
||||
|
||||
url(r'^class/multiple/grant/$', 'acl_class_multiple_grant', (), 'acl_class_multiple_grant'),
|
||||
url(r'^class/multiple/revoke/$', 'acl_class_multiple_revoke', (), 'acl_class_multiple_revoke'),
|
||||
|
||||
)
|
||||
34
apps/acls/utils.py
Normal file
34
apps/acls/utils.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from common.classes import get_source_object
|
||||
from common.models import AnonymousUserSingleton
|
||||
|
||||
from .models import AccessEntry, DefaultAccessEntry, CreatorSingleton
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def apply_default_acls(obj, actor=None):
|
||||
logger.debug('actor, init: %s' % actor)
|
||||
obj = get_source_object(obj)
|
||||
|
||||
if actor:
|
||||
actor = AnonymousUserSingleton.objects.passthru_check(actor)
|
||||
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
|
||||
for default_acl in DefaultAccessEntry.objects.filter(content_type=content_type):
|
||||
holder = CreatorSingleton.objects.passthru_check(default_acl.holder_object, actor)
|
||||
|
||||
if holder:
|
||||
# When the creator is admin
|
||||
access_entry = AccessEntry(
|
||||
permission=default_acl.permission,
|
||||
holder_object=holder,
|
||||
content_object=obj,
|
||||
)
|
||||
access_entry.save()
|
||||
649
apps/acls/views.py
Normal file
649
apps/acls/views.py
Normal file
File diff suppressed because it is too large
Load Diff
27
apps/acls/widgets.py
Normal file
27
apps/acls/widgets.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models.base import ModelBase
|
||||
from django.template.defaultfilters import capfirst
|
||||
|
||||
from .literals import CONTENT_TYPE_ICON_MAP
|
||||
|
||||
|
||||
def content_type_icon(content_type):
|
||||
return mark_safe(u'<span class="famfam active famfam-%s"></span>' % CONTENT_TYPE_ICON_MAP.get('%s.%s' % (content_type.app_label, content_type.model), 'help'))
|
||||
|
||||
|
||||
def object_w_content_type_icon(obj):
|
||||
content_type = ContentType.objects.get_for_model(obj)
|
||||
|
||||
ct_fullname = '%s.%s' % (content_type.app_label, content_type.name)
|
||||
if isinstance(obj, ModelBase):
|
||||
label = getattr(obj._meta, 'verbose_name_plural', unicode(content_type))
|
||||
else:
|
||||
if ct_fullname == 'auth.user':
|
||||
label = obj.get_full_name()
|
||||
else:
|
||||
label = unicode(obj)
|
||||
|
||||
return mark_safe('%s<span>%s</span>' % (content_type_icon(content_type), capfirst(label)))
|
||||
23
apps/app_registry/__init__.py
Normal file
23
apps/app_registry/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.importlib import import_module
|
||||
|
||||
from .models import App
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def register_apps():
|
||||
for app_name in settings.INSTALLED_APPS:
|
||||
logger.debug('registering: %s' % app_name)
|
||||
App.register(app_name)
|
||||
try:
|
||||
post_init = import_module('%s.post_init' % app_name)
|
||||
except ImportError:
|
||||
logger.debug('Unable to import post_init module from: %s' % app_name)
|
||||
|
||||
|
||||
register_apps()
|
||||
6
apps/app_registry/icons.py
Normal file
6
apps/app_registry/icons.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from icons.literals import PLUGIN
|
||||
from icons import Icon
|
||||
|
||||
icon_app = Icon(PLUGIN)
|
||||
10
apps/app_registry/links.py
Normal file
10
apps/app_registry/links.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from navigation import Link
|
||||
|
||||
from .icons import icon_app
|
||||
|
||||
app_registry_tool_link = Link(text=_(u'Apps'), view='app_list', icon=icon_app)#, permissions=[PERMISSION_BACKUP_JOB_VIEW])
|
||||
app_list = Link(text=_(u'app list'), view='app_list', icon=icon_app)#, permissions=[PERMISSION_BACKUP_JOB_VIEW])
|
||||
32
apps/app_registry/migrations/0001_initial.py
Normal file
32
apps/app_registry/migrations/0001_initial.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'App'
|
||||
db.create_table('app_registry_app', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
|
||||
))
|
||||
db.send_create_signal('app_registry', ['App'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'App'
|
||||
db.delete_table('app_registry_app')
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'App.icon'
|
||||
db.add_column('app_registry_app', 'icon',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=64, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding unique constraint on 'App', fields ['name']
|
||||
db.create_unique('app_registry_app', ['name'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Removing unique constraint on 'App', fields ['name']
|
||||
db.delete_unique('app_registry_app', ['name'])
|
||||
|
||||
# Deleting field 'App.icon'
|
||||
db.delete_column('app_registry_app', 'icon')
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'icon': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
58
apps/app_registry/migrations/0003_auto__add_backupjob.py
Normal file
58
apps/app_registry/migrations/0003_auto__add_backupjob.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'BackupJob'
|
||||
db.create_table('app_registry_backupjob', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
|
||||
('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
|
||||
('begin_datetime', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2012, 8, 18, 0, 0))),
|
||||
('storage_module_name', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||
('storage_arguments_json', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
))
|
||||
db.send_create_signal('app_registry', ['BackupJob'])
|
||||
|
||||
# Adding M2M table for field apps on 'BackupJob'
|
||||
db.create_table('app_registry_backupjob_apps', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('backupjob', models.ForeignKey(orm['app_registry.backupjob'], null=False)),
|
||||
('app', models.ForeignKey(orm['app_registry.app'], null=False))
|
||||
))
|
||||
db.create_unique('app_registry_backupjob_apps', ['backupjob_id', 'app_id'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'BackupJob'
|
||||
db.delete_table('app_registry_backupjob')
|
||||
|
||||
# Removing M2M table for field apps on 'BackupJob'
|
||||
db.delete_table('app_registry_backupjob_apps')
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'icon': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'app_registry.backupjob': {
|
||||
'Meta': {'object_name': 'BackupJob'},
|
||||
'apps': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['app_registry.App']", 'symmetrical': 'False'}),
|
||||
'begin_datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 8, 18, 0, 0)'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'storage_arguments_json': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'storage_module_name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
45
apps/app_registry/migrations/0004_auto.py
Normal file
45
apps/app_registry/migrations/0004_auto.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding M2M table for field dependencies on 'App'
|
||||
db.create_table('app_registry_app_dependencies', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('from_app', models.ForeignKey(orm['app_registry.app'], null=False)),
|
||||
('to_app', models.ForeignKey(orm['app_registry.app'], null=False))
|
||||
))
|
||||
db.create_unique('app_registry_app_dependencies', ['from_app_id', 'to_app_id'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Removing M2M table for field dependencies on 'App'
|
||||
db.delete_table('app_registry_app_dependencies')
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'dependencies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'dependencies_rel_+'", 'null': 'True', 'to': "orm['app_registry.App']"}),
|
||||
'icon': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'app_registry.backupjob': {
|
||||
'Meta': {'object_name': 'BackupJob'},
|
||||
'apps': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['app_registry.App']", 'symmetrical': 'False'}),
|
||||
'begin_datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 8, 18, 0, 0)'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'storage_arguments_json': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'storage_module_name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
44
apps/app_registry/migrations/0005_auto.py
Normal file
44
apps/app_registry/migrations/0005_auto.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Removing M2M table for field dependencies on 'App'
|
||||
db.delete_table('app_registry_app_dependencies')
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding M2M table for field dependencies on 'App'
|
||||
db.create_table('app_registry_app_dependencies', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('from_app', models.ForeignKey(orm['app_registry.app'], null=False)),
|
||||
('to_app', models.ForeignKey(orm['app_registry.app'], null=False))
|
||||
))
|
||||
db.create_unique('app_registry_app_dependencies', ['from_app_id', 'to_app_id'])
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'icon': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'app_registry.backupjob': {
|
||||
'Meta': {'object_name': 'BackupJob'},
|
||||
'apps': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['app_registry.App']", 'symmetrical': 'False'}),
|
||||
'begin_datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 8, 18, 0, 0)'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'storage_arguments_json': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'storage_module_name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
45
apps/app_registry/migrations/0006_auto.py
Normal file
45
apps/app_registry/migrations/0006_auto.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding M2M table for field dependencies on 'App'
|
||||
db.create_table('app_registry_app_dependencies', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('from_app', models.ForeignKey(orm['app_registry.app'], null=False)),
|
||||
('to_app', models.ForeignKey(orm['app_registry.app'], null=False))
|
||||
))
|
||||
db.create_unique('app_registry_app_dependencies', ['from_app_id', 'to_app_id'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Removing M2M table for field dependencies on 'App'
|
||||
db.delete_table('app_registry_app_dependencies')
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'dependencies': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['app_registry.App']", 'null': 'True', 'blank': 'True'}),
|
||||
'icon': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'app_registry.backupjob': {
|
||||
'Meta': {'object_name': 'BackupJob'},
|
||||
'apps': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['app_registry.App']", 'symmetrical': 'False'}),
|
||||
'begin_datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 8, 18, 0, 0)'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'storage_arguments_json': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'storage_module_name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
@@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting model 'BackupJob'
|
||||
db.delete_table('app_registry_backupjob')
|
||||
|
||||
# Removing M2M table for field apps on 'BackupJob'
|
||||
db.delete_table('app_registry_backupjob_apps')
|
||||
|
||||
# Deleting field 'App.icon'
|
||||
db.delete_column('app_registry_app', 'icon')
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding model 'BackupJob'
|
||||
db.create_table('app_registry_backupjob', (
|
||||
('storage_arguments_json', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
|
||||
('storage_module_name', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||
('begin_datetime', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2012, 8, 18, 0, 0))),
|
||||
('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
))
|
||||
db.send_create_signal('app_registry', ['BackupJob'])
|
||||
|
||||
# Adding M2M table for field apps on 'BackupJob'
|
||||
db.create_table('app_registry_backupjob_apps', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('backupjob', models.ForeignKey(orm['app_registry.backupjob'], null=False)),
|
||||
('app', models.ForeignKey(orm['app_registry.app'], null=False))
|
||||
))
|
||||
db.create_unique('app_registry_backupjob_apps', ['backupjob_id', 'app_id'])
|
||||
|
||||
# Adding field 'App.icon'
|
||||
db.add_column('app_registry_app', 'icon',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=64, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
models = {
|
||||
'app_registry.app': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'App'},
|
||||
'dependencies': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['app_registry.App']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['app_registry']
|
||||
115
apps/app_registry/models.py
Normal file
115
apps/app_registry/models.py
Normal file
@@ -0,0 +1,115 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import imp
|
||||
import sys
|
||||
|
||||
from django.db import models
|
||||
from django.db import DatabaseError, transaction
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.importlib import import_module
|
||||
|
||||
from common.models import TranslatableLabelMixin, LiveObjectMixin
|
||||
from smart_settings import SettingsNamespace
|
||||
from project_setup.api import register_setup
|
||||
from project_tools.api import register_tool
|
||||
from statistics.api import register_statistics
|
||||
from navigation.api import register_top_menu
|
||||
from bootstrap.classes import Cleanup, BootstrapModel
|
||||
|
||||
#from .classes import AppBackup, StorageModuleBase, Setting
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class App(TranslatableLabelMixin, LiveObjectMixin, models.Model):
|
||||
translatables = ['label', 'description', 'icon']
|
||||
|
||||
#class UnableToRegister(Exception):
|
||||
# pass
|
||||
|
||||
name = models.CharField(max_length=64, verbose_name=_(u'name'), unique=True)
|
||||
dependencies = models.ManyToManyField('self', verbose_name=_(u'dependencies'), symmetrical=False, blank=True, null=True)
|
||||
#version
|
||||
#top_urls
|
||||
#namespace
|
||||
|
||||
@classmethod
|
||||
@transaction.commit_on_success
|
||||
def register(cls, app_name):
|
||||
logger.debug('Trying to import: %s' % app_name)
|
||||
try:
|
||||
app_module = import_module(app_name)
|
||||
except ImportError:
|
||||
transaction.rollback
|
||||
logger.debug('Unable to import app: %s' % app_name)
|
||||
else:
|
||||
logger.debug('Trying to import registry from: %s' % app_name)
|
||||
try:
|
||||
registration = import_module('%s.registry' % app_name)
|
||||
except ImportError:
|
||||
transaction.rollback
|
||||
logger.debug('Unable to import registry for app: %s' % app_name)
|
||||
else:
|
||||
if not getattr(registration, 'disabled', False):
|
||||
try:
|
||||
app, created = App.objects.get_or_create(name=app_name)
|
||||
except DatabaseError:
|
||||
transaction.rollback()
|
||||
# If database is not ready create a memory only app instance
|
||||
app = App()
|
||||
app.label = getattr(registration, 'label', app_name)
|
||||
app.description = getattr(registration, 'description', u'')
|
||||
else:
|
||||
# If there are not error go ahead with the stored app instance
|
||||
app.label = getattr(registration, 'label', app_name)
|
||||
app.description = getattr(registration, 'description', u'')
|
||||
app.dependencies.clear()
|
||||
app.save()
|
||||
for dependency_name in getattr(registration, 'dependencies', []):
|
||||
dependency, created = App.objects.get_or_create(name=dependency_name)
|
||||
app.dependencies.add(dependency)
|
||||
|
||||
app.icon = getattr(registration, 'icon', None)
|
||||
settings = getattr(registration, 'settings', None)
|
||||
|
||||
if settings:
|
||||
logger.debug('settings: %s' % settings)
|
||||
settings_module = imp.new_module('settings')
|
||||
setattr(app_module, 'settings', settings_module)
|
||||
sys.modules['%s.settings' % app_name] = settings_module
|
||||
settings_namespace = SettingsNamespace(app_name, app.label, '%s.settings' % app_name)
|
||||
for setting in settings:
|
||||
settings_namespace.add_setting(**setting)
|
||||
|
||||
for link in getattr(registration, 'setup_links', []):
|
||||
logger.debug('setup link: %s' % link)
|
||||
register_setup(link)
|
||||
|
||||
for link in getattr(registration, 'tool_links', []):
|
||||
logger.debug('tool link: %s' % link)
|
||||
register_tool(link)
|
||||
|
||||
for statistic in getattr(registration, 'statistics', []):
|
||||
logger.debug('statistic: %s' % statistic)
|
||||
register_statistics(statistic)
|
||||
|
||||
for index, link in enumerate(getattr(registration, 'menu_links', [])):
|
||||
logger.debug('menu_link: %s' % link)
|
||||
register_top_menu(name='%s.%s' % (app_name, index), link=link)
|
||||
|
||||
for cleanup_function in getattr(registration, 'cleanup_functions', []):
|
||||
logger.debug('cleanup_function: %s' % cleanup_function)
|
||||
Cleanup(cleanup_function)
|
||||
|
||||
for bootstrap_model in getattr(registration, 'bootstrap_models', []):
|
||||
logger.debug('bootstrap_model: %s' % bootstrap_model)
|
||||
BootstrapModel(model_name=bootstrap_model.get('name'), app_name=app_name, sanitize=bootstrap_model.get('sanitize', True), dependencies=bootstrap_model.get('dependencies'))
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.label)
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', )
|
||||
verbose_name = _(u'app')
|
||||
verbose_name_plural = _(u'apps')
|
||||
13
apps/app_registry/registry.py
Normal file
13
apps/app_registry/registry.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .icons import icon_app
|
||||
from .links import app_registry_tool_link
|
||||
|
||||
name = 'app_registry'
|
||||
label = _(u'App registry')
|
||||
description = _(u'Handles the registration of apps in a project.')
|
||||
icon = icon_app
|
||||
tool_links = [app_registry_tool_link]
|
||||
dependencies = ['navigation']
|
||||
BIN
apps/app_registry/static/images/icons/plugin.png
Normal file
BIN
apps/app_registry/static/images/icons/plugin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
5
apps/app_registry/urls.py
Normal file
5
apps/app_registry/urls.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
urlpatterns = patterns('app_registry.views',
|
||||
url(r'^list/$', 'app_list', (), 'app_list'),
|
||||
)
|
||||
27
apps/app_registry/views.py
Normal file
27
apps/app_registry/views.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from common.utils import encapsulate
|
||||
from permissions.models import Permission
|
||||
|
||||
from .models import App
|
||||
from .icons import icon_app
|
||||
|
||||
|
||||
def app_list(request):
|
||||
#order = [i for i,f in sorted(smart_modules.items(), key=lambda k: 'dependencies' in k[1] and k[1]['dependencies'])]
|
||||
|
||||
return render_to_response('generic_list.html', {
|
||||
'object_list': App.live.all(),
|
||||
'hide_object': True,
|
||||
'title': _(u'registered apps'),
|
||||
'extra_columns': [
|
||||
{'name': _(u'label'), 'attribute': 'label'},
|
||||
{'name': _(u'icon'), 'attribute': encapsulate(lambda x: (getattr(x, 'icon') or icon_app).display_big())},
|
||||
{'name': _(u'description'), 'attribute': 'description'},
|
||||
{'name': _(u'dependencies'), 'attribute': encapsulate(lambda x: u', '.join([unicode(dependency) for dependency in x.dependencies.all()]))},
|
||||
],
|
||||
}, context_instance=RequestContext(request))
|
||||
63
apps/backups/__init__.py
Normal file
63
apps/backups/__init__.py
Normal file
@@ -0,0 +1,63 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import inspect
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import transaction, DatabaseError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.importlib import import_module
|
||||
|
||||
#from common.utils import encapsulate
|
||||
#from job_processor.exceptions import JobQueuePushError
|
||||
#from job_processor.models import JobQueue, JobType
|
||||
#from project_tools.api import register_tool
|
||||
#from project_setup.api import register_setup
|
||||
#from navigation.api import bind_links, register_model_list_columns
|
||||
|
||||
#from .classes import AppBackup, ModelBackup
|
||||
|
||||
#from .links import (app_registry_tool_link, app_list, backup_tool_link,
|
||||
# restore_tool_link, backup_job_list, backup_job_create, backup_job_edit,
|
||||
# backup_job_test)
|
||||
#from .literals import BACKUP_JOB_QUEUE_NAME
|
||||
#from .models import App
|
||||
#from . import models
|
||||
|
||||
#class UnableToRegister(Exception):
|
||||
# pass
|
||||
|
||||
#apipkg.initpkg(__name__, {
|
||||
# #'App': _App,
|
||||
## 'App': 'app_registry.models:App',
|
||||
# #'App': models.App
|
||||
#})
|
||||
#pp = 1
|
||||
#from .models import App#as _App#, BackupJob as _BackupJob
|
||||
|
||||
#@transaction.commit_on_success
|
||||
#def create_backups_job_queue():
|
||||
# global backups_job_queue
|
||||
# try:
|
||||
# backups_job_queue, created = JobQueue.objects.get_or_create(name=BACKUP_JOB_QUEUE_NAME, defaults={'label': _('Backups'), 'unique_jobs': True})
|
||||
# except DatabaseError:
|
||||
# transaction.rollback()
|
||||
|
||||
|
||||
#bind_links(['app_list'], [app_list], menu_name='secondary_menu')
|
||||
|
||||
#create_backups_job_queue()
|
||||
###backup_job_type = JobType('remote_backup', _(u'Remove backup'), do_backup)
|
||||
|
||||
#register_setup(backup_tool_link)
|
||||
#register_tool(restore_tool_link)
|
||||
#bind_links([BackupJob, 'backup_job_list', 'backup_job_create'], [backup_job_list], menu_name='secondary_menu')
|
||||
#bind_links([BackupJob, 'backup_job_list', 'backup_job_create'], [backup_job_create], menu_name='sidebar')
|
||||
#bind_links([BackupJob], [backup_job_edit, backup_job_test])
|
||||
|
||||
#register_model_list_columns(BackupJob, [
|
||||
# {'name':_(u'begin date time'), 'attribute': 'begin_datetime'},
|
||||
# {'name':_(u'storage module'), 'attribute': 'storage_module.label'},
|
||||
# {'name':_(u'apps'), 'attribute': encapsulate(lambda x: u', '.join([unicode(app) for app in x.apps.all()]))},
|
||||
#])
|
||||
|
||||
###app.set_backup([ModelBackup()])
|
||||
161
apps/backups/classes.py
Normal file
161
apps/backups/classes.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
from django.core.management.commands.dumpdata import Command
|
||||
from django.conf import settings
|
||||
from django.db import router, DEFAULT_DB_ALIAS
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
from django.utils.importlib import import_module
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Data types
|
||||
class ElementDataBase(object):
|
||||
"""
|
||||
The basic unit of a backup, a data type
|
||||
it is produced or consumed by the ElementBackup classes
|
||||
"""
|
||||
def make_filename(self, id):
|
||||
return '%s-%s' % (self.model_backup.app_backup.app.name, id)
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Must return a file like object
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
def load(self, file_object):
|
||||
"""
|
||||
Must read a file like object and store content
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
|
||||
class Fixture(ElementDataBase):
|
||||
name = 'fixture'
|
||||
|
||||
def __init__(self, model_backup, content):
|
||||
self.model_backup = model_backup
|
||||
self.content = content
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return self.make_filename(self.__class__.name)
|
||||
|
||||
def save(self):
|
||||
return ContentFile(name=self.filename, content=self.content)
|
||||
|
||||
#def load(self):
|
||||
|
||||
|
||||
# Element backup
|
||||
class ElementBackupBase(object):
|
||||
"""
|
||||
Sub classes must provide at least:
|
||||
info()
|
||||
backup()
|
||||
restore()
|
||||
"""
|
||||
|
||||
label = _(u'Base backup manager')
|
||||
|
||||
def info(self):
|
||||
"""
|
||||
Must return at least None
|
||||
"""
|
||||
return None
|
||||
|
||||
def link(self, app_backup):
|
||||
self.app_backup = app_backup
|
||||
return self
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.__class__.label)
|
||||
|
||||
|
||||
class ModelBackup(ElementBackupBase):
|
||||
label = _(u'Model fixtures')
|
||||
|
||||
def __init__(self, models=None):
|
||||
self.model_list = models or []
|
||||
|
||||
def info(self):
|
||||
return _(u'models: %s') % (u', '.join(self.model_list) if self.model_list else _(u'All'))
|
||||
|
||||
def backup(self):
|
||||
"""
|
||||
"""
|
||||
#TODO: turn into a generator
|
||||
|
||||
command = Command()
|
||||
if not self.model_list:
|
||||
result = [self.app_backup.app.name]
|
||||
else:
|
||||
result = [u'%s.%s' (self.app_backup.app.name, model) for model in self.model_list]
|
||||
|
||||
#TODO: a single Fixture or a list of Fixtures for each model?
|
||||
#Can't return multiple Fixture until a way to find all of an app's models is found
|
||||
return [Fixture(
|
||||
model_backup=self,
|
||||
content=command.handle(u' '.join(result), format='json', indent=4, using=DEFAULT_DB_ALIAS, exclude=[], user_base_manager=False, use_natural_keys=False)
|
||||
)]
|
||||
|
||||
|
||||
class FileBackup(ElementBackupBase):
|
||||
label = _(u'File copy')
|
||||
|
||||
def __init__(self, storage_class, filepath=None):
|
||||
self.storage_class = storage_class
|
||||
self.filepath = filepath
|
||||
|
||||
def info(self):
|
||||
return _(u'%s from %s') % (self.filepath or _(u'all files'), self.storage_class)
|
||||
|
||||
def backup(self):
|
||||
"""
|
||||
Fetch a file specified by filepath from the Django storage class
|
||||
and return a file like object
|
||||
"""
|
||||
return None
|
||||
|
||||
|
||||
# App config
|
||||
class AppBackup(object):
|
||||
_registry = {}
|
||||
|
||||
STATE_BACKING_UP = 'backing_up'
|
||||
STATE_RESTORING = 'restoring'
|
||||
STATE_IDLE = 'idle'
|
||||
|
||||
STATE_CHOICES = (
|
||||
(STATE_BACKING_UP, _(u'backing up')),
|
||||
(STATE_RESTORING, _(u'restoring')),
|
||||
(STATE_IDLE, _(u'idle')),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get(cls, name):
|
||||
return cls._registry[name]
|
||||
|
||||
@classmethod
|
||||
def get_all(cls):
|
||||
return cls._registry.values()
|
||||
|
||||
def __init__(self, app, backup_managers):
|
||||
# app = App instance from app_registry app
|
||||
self.app = app
|
||||
self.backup_managers = [manager.link(self) for manager in backup_managers]
|
||||
self.state = self.__class__.STATE_IDLE
|
||||
self.__class__._registry[app] = self
|
||||
|
||||
def info(self):
|
||||
results = []
|
||||
for manager in self.backup_managers:
|
||||
results.append(u'%s - %s' % (manager, manager.info() or _(u'Nothing')))
|
||||
return u', '.join(results)
|
||||
|
||||
|
||||
20
apps/backups/forms.py
Normal file
20
apps/backups/forms.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django import forms
|
||||
|
||||
from common.widgets import ScrollableCheckboxSelectMultiple
|
||||
|
||||
#from .classes import AppBackup
|
||||
#from .models import App, BackupJob
|
||||
|
||||
|
||||
#def valid_app_choices():
|
||||
# # Return app that exist in the app registry and that have been registered for backup
|
||||
# return App.live.filter(pk__in=[appbackup.app.pk for appbackup in AppBackup.get_all()])
|
||||
|
||||
|
||||
#class BackupJobForm(forms.ModelForm):
|
||||
# apps = forms.ModelMultipleChoiceField(queryset=valid_app_choices(), widget=ScrollableCheckboxSelectMultiple())
|
||||
#
|
||||
# class Meta:
|
||||
# model = BackupJob
|
||||
17
apps/backups/links.py
Normal file
17
apps/backups/links.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from navigation import Link
|
||||
|
||||
from .icons import icon_app
|
||||
from .permissions import PERMISSION_BACKUP_JOB_VIEW, PERMISSION_BACKUP_JOB_CREATE, PERMISSION_BACKUP_JOB_EDIT, PERMISSION_BACKUP_JOB_DELETE
|
||||
|
||||
backup_tool_link = Link(text=_(u'backups'), view='backup_job_list', icon='cd_burn.png', permissions=[PERMISSION_BACKUP_JOB_VIEW])
|
||||
backup_job_list = Link(text=_(u'backup job list'), view='backup_job_list', sprite='cd_burn', permissions=[PERMISSION_BACKUP_JOB_VIEW])
|
||||
backup_job_create = Link(text=_(u'create'), view='backup_job_create', sprite='cd_add', permissions=[PERMISSION_BACKUP_JOB_CREATE])
|
||||
backup_job_edit = Link(text=_(u'edit'), view='backup_job_edit', args='object.pk', sprite='cd_edit', permissions=[PERMISSION_BACKUP_JOB_EDIT])
|
||||
backup_job_test = Link(text=_(u'test'), view='backup_job_test', args='object.pk', sprite='cd_go')#, permissions=[PERMISSION_BACKUP_JOB_TEST])
|
||||
backup_job_delete = Link(text=_(u'delete'), view='backup_job_delete', args='object.pk', sprite='cd_delete', permissions=[PERMISSION_BACKUP_JOB_DELETE])
|
||||
|
||||
restore_tool_link = Link(text=_(u'restore'), view='restore_view', icon='cd_eject.png')#, permissions=[])
|
||||
1
apps/backups/literals.py
Normal file
1
apps/backups/literals.py
Normal file
@@ -0,0 +1 @@
|
||||
BACKUP_JOB_QUEUE_NAME = 'backups_queue'
|
||||
58
apps/backups/models.py
Normal file
58
apps/backups/models.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from django.db import models
|
||||
|
||||
from app_registry.models import App
|
||||
|
||||
"""
|
||||
class BackupJob(models.Model):
|
||||
name = models.CharField(max_length=64, verbose_name=_(u'name'))
|
||||
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
|
||||
apps = models.ManyToManyField(App)
|
||||
begin_datetime = models.DateTimeField(verbose_name=_(u'begin date and time'), default=lambda: datetime.datetime.now())
|
||||
|
||||
# * repetition =
|
||||
# day - 1 days
|
||||
# weekly - days of week checkbox
|
||||
# month - day of month, day of week
|
||||
# * repetition option field
|
||||
# * ends
|
||||
# - never
|
||||
# - After # ocurrences
|
||||
# - On date
|
||||
# * end option field
|
||||
# * type
|
||||
# - Full
|
||||
# - Incremental
|
||||
storage_module_name = models.CharField(max_length=32, choices=StorageModuleBase.get_as_choices(), verbose_name=_(u'storage module'))
|
||||
storage_arguments_json = models.TextField(verbose_name=_(u'storage module arguments (in JSON)'), blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def storage_module(self):
|
||||
return StorageModuleBase.get(self.storage_module_name)
|
||||
|
||||
def backup(self, dry_run=False):
|
||||
logger.debug('starting: %s', self)
|
||||
logger.debug('dry_run: %s' % dry_run)
|
||||
storage_module = self.storage_module
|
||||
#TODO: loads
|
||||
for app in self.apps.all():
|
||||
app_backup = AppBackup.get(app)
|
||||
app_backup.backup(storage_module(backup_path='/tmp'), dry_run=dry_run)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
#dump
|
||||
super(BackupJob, self).save(*args, **kwargs)
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self):
|
||||
return ('checkout_info', [self.document.pk])
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'document checkout')
|
||||
verbose_name_plural = _(u'document checkouts')
|
||||
|
||||
|
||||
#class BackupJobLog
|
||||
"""
|
||||
12
apps/backups/permissions.py
Normal file
12
apps/backups/permissions.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from permissions.models import PermissionNamespace, Permission
|
||||
|
||||
namespace = PermissionNamespace('backups', _(u'Backups'))
|
||||
|
||||
PERMISSION_BACKUP_JOB_VIEW = Permission.objects.register(namespace, 'backup_job_view', _(u'View a backup job'))
|
||||
PERMISSION_BACKUP_JOB_CREATE = Permission.objects.register(namespace, 'backup_job_view', _(u'Create backup jobs'))
|
||||
PERMISSION_BACKUP_JOB_EDIT = Permission.objects.register(namespace, 'backup_job_edit', _(u'Edit an existing backup jobs'))
|
||||
PERMISSION_BACKUP_JOB_DELETE = Permission.objects.register(namespace, 'backup_job_delete', _(u'Delete an existing backup jobs'))
|
||||
9
apps/backups/urls.py
Normal file
9
apps/backups/urls.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
urlpatterns = patterns('backups.views',
|
||||
#url(r'^jobs/list/$', 'backup_job_list', (), 'backup_job_list'),
|
||||
#url(r'^jobs/create/$', 'backup_job_create', (), 'backup_job_create'),
|
||||
#url(r'^jobs/(?P<backup_job_pk>\d+)/edit/$', 'backup_job_edit', (), 'backup_job_edit'),
|
||||
#url(r'^jobs/(?P<backup_job_pk>\d+)/test/$', 'backup_job_test', (), 'backup_job_test'),
|
||||
#url(r'^jobs/(?P<backup_job_pk>\d+)/delete/$', 'backup_job_delete', (), 'backup_job_delete'),
|
||||
)
|
||||
126
apps/backups/views.py
Normal file
126
apps/backups/views.py
Normal file
@@ -0,0 +1,126 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response, get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from common.utils import encapsulate
|
||||
from permissions.models import Permission
|
||||
|
||||
#from .classes import AppBackup
|
||||
#from .forms import BackupJobForm
|
||||
#from .models import App#, BackupJob
|
||||
from .permissions import PERMISSION_BACKUP_JOB_VIEW, PERMISSION_BACKUP_JOB_CREATE, PERMISSION_BACKUP_JOB_EDIT
|
||||
|
||||
|
||||
def backup_job_list(request):
|
||||
pre_object_list = BackupJob.objects.all()
|
||||
|
||||
try:
|
||||
Permission.objects.check_permissions(request.user, [PERMISSION_BACKUP_JOB_VIEW])
|
||||
except PermissionDenied:
|
||||
# If user doesn't have global permission, get a list of backup jobs
|
||||
# for which he/she does have access use it to filter the
|
||||
# provided object_list
|
||||
final_object_list = AccessEntry.objects.filter_objects_by_access(PERMISSION_BACKUP_JOB_VIEW, request.user, pre_object_list)
|
||||
else:
|
||||
final_object_list = pre_object_list
|
||||
|
||||
context = {
|
||||
'object_list': final_object_list,
|
||||
'title': _(u'backup jobs'),
|
||||
'hide_link': True,
|
||||
#'extra_columns': [
|
||||
# {'name': _(u'info'), 'attribute': 'info'},
|
||||
#],
|
||||
}
|
||||
return render_to_response('generic_list.html', context,
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
def backup_job_create(request):
|
||||
Permission.objects.check_permissions(request.user, [PERMISSION_BACKUP_JOB_CREATE])
|
||||
|
||||
if request.method == 'POST':
|
||||
form = BackupJobForm(data=request.POST)
|
||||
if form.is_valid():
|
||||
try:
|
||||
backup_job = form.save()
|
||||
except Exception, exc:
|
||||
messages.error(request, _(u'Error creating backup job; %s') % exc)
|
||||
else:
|
||||
messages.success(request, _(u'Backup job "%s" created successfully.') % backup_job)
|
||||
return HttpResponseRedirect(reverse('backup_job_list'))
|
||||
else:
|
||||
form = BackupJobForm()
|
||||
|
||||
return render_to_response('generic_form.html', {
|
||||
'form': form,
|
||||
'title': _(u'Create backup job')
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
|
||||
def backup_job_edit(request, backup_job_pk):
|
||||
backup_job = get_object_or_404(BackupJob, pk=backup_job_pk)
|
||||
try:
|
||||
Permission.objects.check_permissions(request.user, [PERMISSION_BACKUP_JOB_EDIT])
|
||||
except PermissionDenied:
|
||||
AccessEntry.objects.check_access(PERMISSION_BACKUP_JOB_EDIT, request.user, backup_job)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = BackupJobForm(data=request.POST, instance=backup_job)
|
||||
if form.is_valid():
|
||||
try:
|
||||
backup_job = form.save()
|
||||
except Exception, exc:
|
||||
messages.error(request, _(u'Error editing backup job; %s') % exc)
|
||||
else:
|
||||
messages.success(request, _(u'Backup job "%s" edited successfully.') % backup_job)
|
||||
return HttpResponseRedirect(reverse('backup_job_list'))
|
||||
else:
|
||||
form = BackupJobForm(instance=backup_job)
|
||||
|
||||
return render_to_response('generic_form.html', {
|
||||
'form': form,
|
||||
'object': backup_job,
|
||||
'title': _(u'Edit backup job: %s') % backup_job
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
|
||||
def backup_job_test(request, backup_job_pk):
|
||||
backup_job = get_object_or_404(BackupJob, pk=backup_job_pk)
|
||||
#try:
|
||||
# Permission.objects.check_permissions(request.user, [PERMISSION_BACKUP_JOB_EDIT])
|
||||
#except PermissionDenied:
|
||||
# AccessEntry.objects.check_access(PERMISSION_BACKUP_JOB_EDIT, request.user, backup_job)
|
||||
|
||||
try:
|
||||
backup_job.backup(dry_run=True)
|
||||
except Exception, exc:
|
||||
if settings.DEBUG:
|
||||
raise
|
||||
else:
|
||||
messages.error(request, _(u'Error testing backup job; %s') % exc)
|
||||
return HttpResponseRedirect(reverse('backup_job_list'))
|
||||
else:
|
||||
messages.success(request, _(u'Test for backup job "%s" finished successfully.') % backup_job)
|
||||
return HttpResponseRedirect(reverse('backup_job_list'))
|
||||
|
||||
|
||||
def backup_view(request):
|
||||
#Permission.objects.check_permissions(request.user, [])
|
||||
|
||||
context = {
|
||||
'object_list': AppBackup.get_all(),
|
||||
'title': _(u'registered apps for backup'),
|
||||
'hide_link': True,
|
||||
'extra_columns': [
|
||||
{'name': _(u'info'), 'attribute': 'info'},
|
||||
],
|
||||
}
|
||||
return render_to_response('generic_list.html', context,
|
||||
context_instance=RequestContext(request))
|
||||
1
apps/bootstrap/__init__.py
Normal file
1
apps/bootstrap/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user