mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-06 14:37:02 +00:00
Compare commits
3088 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb0a302f62 | ||
|
|
43127379cd | ||
|
|
c5bc7136c7 | ||
|
|
18ba671417 | ||
|
|
6141bfd1fb | ||
|
|
4e4b51c4f1 | ||
|
|
83ac300aa3 | ||
|
|
f641a3c9c6 | ||
|
|
18a4782bf1 | ||
|
|
f1fddb7325 | ||
|
|
9c864af409 | ||
|
|
7cd332228a | ||
|
|
54c534736f | ||
|
|
6f07862572 | ||
|
|
54863ca6a4 | ||
|
|
70499e504c | ||
|
|
697565f95c | ||
|
|
94f1501c96 | ||
|
|
145b0e2c7b | ||
|
|
7057b3ba82 | ||
|
|
f6eecce135 | ||
|
|
1f0d105685 | ||
|
|
7caf841edd | ||
|
|
7cd82b1e03 | ||
|
|
2c8a21fc04 | ||
|
|
102ec389b9 | ||
|
|
f07895eeb0 | ||
|
|
a1570c7666 | ||
|
|
ef260784ac | ||
|
|
bc7be925e2 | ||
|
|
9091e49650 | ||
|
|
5a8dd95565 | ||
|
|
23df87a8c3 | ||
|
|
3781d10cb6 | ||
|
|
f1d505330c | ||
|
|
fc9fbd25fe | ||
|
|
b3e5003e0c | ||
|
|
be9fd29023 | ||
|
|
22bb9cfe09 | ||
|
|
02238b4000 | ||
|
|
2f9bf085fa | ||
|
|
11010f274f | ||
|
|
9f2c57c3f1 | ||
|
|
41d815103c | ||
|
|
967c48f6d7 | ||
|
|
c4d0d0fba7 | ||
|
|
9a720e9c82 | ||
|
|
c41522ab67 | ||
|
|
501a4b3415 | ||
|
|
7af59ac7ec | ||
|
|
c16a4707b5 | ||
|
|
0a86ea65ed | ||
|
|
273ab1fe54 | ||
|
|
1b9622e6dd | ||
|
|
7209184636 | ||
|
|
b4c0b264b9 | ||
|
|
2e13e758b8 | ||
|
|
5359eb85e1 | ||
|
|
e42e758150 | ||
|
|
340fd9a324 | ||
|
|
1e277e5681 | ||
|
|
2534176b8d | ||
|
|
4f1c547f77 | ||
|
|
4698b2a0e7 | ||
|
|
cb76c9762c | ||
|
|
496890357a | ||
|
|
fc7dba6c91 | ||
|
|
67efbdc6e9 | ||
|
|
d660137e7e | ||
|
|
15ae14d4a1 | ||
|
|
111524b6c6 | ||
|
|
ce806c5aa8 | ||
|
|
b244f613ee | ||
|
|
ad5cb35260 | ||
|
|
c0ca2174b6 | ||
|
|
c3c1398a2d | ||
|
|
1fbdd2edf4 | ||
|
|
a64a66912f | ||
|
|
61bbb23e7a | ||
|
|
e8d62ecc22 | ||
|
|
7db64e9375 | ||
|
|
0a320cb3b3 | ||
|
|
50d38d127c | ||
|
|
1ad42423bf | ||
|
|
273c9b2f18 | ||
|
|
90260bbed5 | ||
|
|
833804c7b4 | ||
|
|
206f4bc2bb | ||
|
|
5280bdab86 | ||
|
|
ce0113cd6c | ||
|
|
24885853fd | ||
|
|
1f4ce20c8b | ||
|
|
5629682a9a | ||
|
|
826e335611 | ||
|
|
06c0a425cd | ||
|
|
dc9b4bbb20 | ||
|
|
4e951bcb98 | ||
|
|
428cafeb7d | ||
|
|
e145e461fa | ||
|
|
7bfd268793 | ||
|
|
2bc2d4ed26 | ||
|
|
185d006a61 | ||
|
|
42068c8a95 | ||
|
|
cb4e86886a | ||
|
|
02f6b1850c | ||
|
|
a667380d7a | ||
|
|
21be67f025 | ||
|
|
7d3fbcc7d0 | ||
|
|
cbbfc2227c | ||
|
|
9add3fa538 | ||
|
|
ef13bffcb9 | ||
|
|
a40c9d2b11 | ||
|
|
ddaa4c056d | ||
|
|
8f0b34c2de | ||
|
|
5ff145ff12 | ||
|
|
6e8a3fa05d | ||
|
|
2d3816e3ae | ||
|
|
4c9441a690 | ||
|
|
035523b426 | ||
|
|
93179a21b2 | ||
|
|
53534cf3d5 | ||
|
|
8bb6c4012a | ||
|
|
57960111f7 | ||
|
|
165e6322fc | ||
|
|
2afc157c24 | ||
|
|
9822bb94a1 | ||
|
|
bf72c8a4cc | ||
|
|
f6c8281c9e | ||
|
|
dcc2b2cb31 | ||
|
|
e9d3127932 | ||
|
|
c5d6b7d053 | ||
|
|
9bb0950c12 | ||
|
|
b2d6bd58e6 | ||
|
|
4fdcdec802 | ||
|
|
0873b17894 | ||
|
|
48957d33b6 | ||
|
|
48675f1875 | ||
|
|
ef4377c77b | ||
|
|
4394e0fca1 | ||
|
|
fc7b15042c | ||
|
|
bbaa119617 | ||
|
|
88f4797f0b | ||
|
|
fa35e32578 | ||
|
|
c40cbc6cc2 | ||
|
|
8fcd6c2ff9 | ||
|
|
30c6a713d6 | ||
|
|
029a18ff1a | ||
|
|
45049ae176 | ||
|
|
01f59521af | ||
|
|
0f3cd9dd24 | ||
|
|
ba4619df21 | ||
|
|
f7aa5aaf0b | ||
|
|
d3f0553c65 | ||
|
|
601d7729bc | ||
|
|
ac464b4036 | ||
|
|
5f220bc364 | ||
|
|
962ea50c44 | ||
|
|
742fda24c6 | ||
|
|
e0c10f3564 | ||
|
|
5a94143fd7 | ||
|
|
c5ba226fa0 | ||
|
|
be8dff3de7 | ||
|
|
0582fd680d | ||
|
|
c93a5e5299 | ||
|
|
c5229f1100 | ||
|
|
d78023f388 | ||
|
|
f15b63fd66 | ||
|
|
0ff236edbc | ||
|
|
9d23f3bdd0 | ||
|
|
dd74aac117 | ||
|
|
d49b713ccd | ||
|
|
d6431cbcc4 | ||
|
|
392748db57 | ||
|
|
70cc8fb9e3 | ||
|
|
bbabe672d8 | ||
|
|
447732bf9c | ||
|
|
29f60b5199 | ||
|
|
94fa7b17ff | ||
|
|
b5ec93e571 | ||
|
|
132e762c7e | ||
|
|
8ef94890a9 | ||
|
|
b6c9ef990f | ||
|
|
b19ce60e74 | ||
|
|
632e1ecb5c | ||
|
|
fa3ec522ca | ||
|
|
4615cea8a6 | ||
|
|
3c5dc1672a | ||
|
|
768c68df49 | ||
|
|
c44731bd97 | ||
|
|
9450cf9447 | ||
|
|
1cfb60d65b | ||
|
|
64519d6310 | ||
|
|
3d9b5852f8 | ||
|
|
dc6109c530 | ||
|
|
7fe1e27667 | ||
|
|
e24209438c | ||
|
|
ee2a3c9bea | ||
|
|
5861aa11c1 | ||
|
|
0041c11aae | ||
|
|
ed8def4ece | ||
|
|
7f08cc9cf0 | ||
|
|
981e477bd0 | ||
|
|
01bf39764a | ||
|
|
b4a2ad646b | ||
|
|
79d557542b | ||
|
|
26d411c94d | ||
|
|
8d3ae2ef00 | ||
|
|
f28854b7f2 | ||
|
|
5a24771d3c | ||
|
|
84830d6aef | ||
|
|
134cd53f45 | ||
|
|
717b9db4af | ||
|
|
87c313c933 | ||
|
|
928320c1bd | ||
|
|
bba4ad55da | ||
|
|
23604fba25 | ||
|
|
112c51d6e3 | ||
|
|
9339a15d18 | ||
|
|
a4b65ba0c7 | ||
|
|
00dfe2599e | ||
|
|
dcf6ec5612 | ||
|
|
0acd47fba0 | ||
|
|
4e718ff879 | ||
|
|
1205462620 | ||
|
|
75344a4ed2 | ||
|
|
6dae15155a | ||
|
|
338922099d | ||
|
|
0c840de187 | ||
|
|
16755831bc | ||
|
|
4c64b7e456 | ||
|
|
28a56c0bd7 | ||
|
|
894f99aa66 | ||
|
|
450d785a58 | ||
|
|
a26be8e7f0 | ||
|
|
d2f982fccb | ||
|
|
4b38f81384 | ||
|
|
20bc336036 | ||
|
|
cec4585538 | ||
|
|
8b4635ffaa | ||
|
|
3dc53c5436 | ||
|
|
7265b3c4b6 | ||
|
|
49033dec1a | ||
|
|
9b632f582f | ||
|
|
a989c8a6d1 | ||
|
|
e5c0427e68 | ||
|
|
c5811749cb | ||
|
|
5e925865a7 | ||
|
|
175f837f3d | ||
|
|
b28d3816c0 | ||
|
|
3ad66acb20 | ||
|
|
958b44af15 | ||
|
|
99b20f6724 | ||
|
|
4eec64e811 | ||
|
|
052548fda7 | ||
|
|
98e7218cf5 | ||
|
|
374c3786df | ||
|
|
a9a3f4381a | ||
|
|
b845ad6d3c | ||
|
|
7c8d3caba6 | ||
|
|
fcddc472e1 | ||
|
|
1c18348475 | ||
|
|
c6c74bd7b9 | ||
|
|
0775edd29e | ||
|
|
52017e5281 | ||
|
|
af3aecc3f8 | ||
|
|
eaf6b511d0 | ||
|
|
e13d0248ae | ||
|
|
e3d563a556 | ||
|
|
e2078bba84 | ||
|
|
017af8a383 | ||
|
|
0739e9f655 | ||
|
|
6f2904eb9a | ||
|
|
4003977ce3 | ||
|
|
d058bb7c3b | ||
|
|
139dfc5b81 | ||
|
|
152a5b5a7b | ||
|
|
ad54fa2ace | ||
|
|
d2e15f52c3 | ||
|
|
f670f382cd | ||
|
|
1ebedaf791 | ||
|
|
2879f426e0 | ||
|
|
d7c2cd8d2a | ||
|
|
78814dedd3 | ||
|
|
4865cf2202 | ||
|
|
239c533137 | ||
|
|
55bf893228 | ||
|
|
349cb32c5f | ||
|
|
1545305d43 | ||
|
|
0f84c6eaaa | ||
|
|
df94b38019 | ||
|
|
e8451f9648 | ||
|
|
b42ed51c5e | ||
|
|
9ed9ccbe4a | ||
|
|
b4d0343992 | ||
|
|
4b0604a183 | ||
|
|
8d50ae1f46 | ||
|
|
6ed4b60ebb | ||
|
|
86e0c502ae | ||
|
|
c1936cf46b | ||
|
|
973910b837 | ||
|
|
590918ac6d | ||
|
|
b9e1efbe00 | ||
|
|
2ca6870c6a | ||
|
|
ca3bedeeb4 | ||
|
|
f85d56ac4d | ||
|
|
9a522f7922 | ||
|
|
f453077796 | ||
|
|
387029c5a6 | ||
|
|
f3b74696c0 | ||
|
|
f946adb6d1 | ||
|
|
dc3174747b | ||
|
|
837ad89502 | ||
|
|
58ffd93961 | ||
|
|
579c392a09 | ||
|
|
81fd1f522f | ||
|
|
e30dcac465 | ||
|
|
ee54cf2ebb | ||
|
|
f47ead51ca | ||
|
|
ab425e0492 | ||
|
|
95134b9ab8 | ||
|
|
7ccac9aa79 | ||
|
|
69f221a424 | ||
|
|
3c6eabaef8 | ||
|
|
76361d1ca9 | ||
|
|
de69cf7ceb | ||
|
|
3fd894df50 | ||
|
|
ddbed22a6f | ||
|
|
f51140f361 | ||
|
|
1876667db1 | ||
|
|
2587c2e372 | ||
|
|
4f6dfe3132 | ||
|
|
58dbd7868a | ||
|
|
3d1245bee6 | ||
|
|
2df012fb97 | ||
|
|
83d5f74e19 | ||
|
|
4dfac05fcb | ||
|
|
3548e3e8cd | ||
|
|
862ebe7d48 | ||
|
|
a56acf553c | ||
|
|
0658f5b7fa | ||
|
|
972e154a75 | ||
|
|
70b0bedf9b | ||
|
|
d843f719c8 | ||
|
|
edf8d8a463 | ||
|
|
8c3e61c6a0 | ||
|
|
6de1d45246 | ||
|
|
5488870267 | ||
|
|
a3845187b3 | ||
|
|
2955a61a5c | ||
|
|
0f11730181 | ||
|
|
75255d80cd | ||
|
|
2d88f5966c | ||
|
|
2984b755d5 | ||
|
|
7362db833b | ||
|
|
7b9bbd5be4 | ||
|
|
11d4687794 | ||
|
|
ef7c94f4e0 | ||
|
|
676e516f73 | ||
|
|
d83d3982cd | ||
|
|
a24bf2d1d7 | ||
|
|
db46faef29 | ||
|
|
64e7c1081b | ||
|
|
56bfd6a069 | ||
|
|
18ac071c5d | ||
|
|
b44790c15f | ||
|
|
e04f0eb98b | ||
|
|
2278a1217b | ||
|
|
183205b8d4 | ||
|
|
435bb7b65b | ||
|
|
52159093dd | ||
|
|
c7056efe69 | ||
|
|
1b69ffe9e0 | ||
|
|
04203312bf | ||
|
|
57bb2a3978 | ||
|
|
c32cea8f8a | ||
|
|
6ba62abd88 | ||
|
|
a31bf4e48e | ||
|
|
fab113db25 | ||
|
|
2858fd4fa8 | ||
|
|
49f12ac82f | ||
|
|
bf943cc706 | ||
|
|
09d8c550b5 | ||
|
|
dadcee8fe2 | ||
|
|
9dacaf7ddf | ||
|
|
622cf46858 | ||
|
|
0c6f8bb52d | ||
|
|
cccf05db39 | ||
|
|
f4ca5290ce | ||
|
|
2380b6aa76 | ||
|
|
215ccb70bc | ||
|
|
3d5376889f | ||
|
|
6053e3be64 | ||
|
|
51f6d27edf | ||
|
|
e46a2089dd | ||
|
|
d5dd918fde | ||
|
|
bf855c8b4c | ||
|
|
4d273b34f7 | ||
|
|
eb82a8afda | ||
|
|
73c4204ee9 | ||
|
|
8fbbd0e714 | ||
|
|
438daf82b4 | ||
|
|
7066098957 | ||
|
|
4e2b1cf4ce | ||
|
|
8e36b55e40 | ||
|
|
e8df572503 | ||
|
|
3e9556e1ef | ||
|
|
ceef3e690d | ||
|
|
3e6bc02256 | ||
|
|
6cc1d7f721 | ||
|
|
53dba06764 | ||
|
|
e514a34e60 | ||
|
|
3efe76dc71 | ||
|
|
571e7e3333 | ||
|
|
6b4d955d7c | ||
|
|
da0b4ca25d | ||
|
|
3b093f5da3 | ||
|
|
570c02ae55 | ||
|
|
81ff4f2c8a | ||
|
|
34b0402bc1 | ||
|
|
469b75624d | ||
|
|
59e239118c | ||
|
|
10957b5fdf | ||
|
|
bc9f66008d | ||
|
|
76b798d6e2 | ||
|
|
7717a15fc2 | ||
|
|
e0ef0a38a5 | ||
|
|
b21eea1568 | ||
|
|
ac73f8d6b6 | ||
|
|
7d95969f03 | ||
|
|
f67b06be88 | ||
|
|
fa5effe1a9 | ||
|
|
1f4dcb5a38 | ||
|
|
949149ea4d | ||
|
|
8ff262456b | ||
|
|
03cf443b14 | ||
|
|
2681fdabec | ||
|
|
678c9779ce | ||
|
|
1728f5d9f0 | ||
|
|
b71312b8eb | ||
|
|
ebe27c499e | ||
|
|
fbc164df8c | ||
|
|
d419da1cac | ||
|
|
67e6e29994 | ||
|
|
3059e60096 | ||
|
|
8a4a0f6bdc | ||
|
|
a1ea97950e | ||
|
|
2d58361620 | ||
|
|
a98262338a | ||
|
|
47cd8b71f7 | ||
|
|
36d6a72317 | ||
|
|
1da5f7e223 | ||
|
|
29398de678 | ||
|
|
d95d562843 | ||
|
|
cb51839eb9 | ||
|
|
ec31075fae | ||
|
|
b30a845a65 | ||
|
|
9667c2fc5a | ||
|
|
7df4084d45 | ||
|
|
d91c9f45c3 | ||
|
|
840b3940cd | ||
|
|
8a1e875020 | ||
|
|
8c43d3f378 | ||
|
|
d67ebbe683 | ||
|
|
16d9845027 | ||
|
|
5591b49c8d | ||
|
|
e67d140af0 | ||
|
|
d8252fc769 | ||
|
|
dfb50ab7ee | ||
|
|
fcc2271e83 | ||
|
|
ae25a48d4e | ||
|
|
b703c6a0ae | ||
|
|
c8ae67aba8 | ||
|
|
9e68c32f96 | ||
|
|
5887480b29 | ||
|
|
edabd603b3 | ||
|
|
1131af8283 | ||
|
|
59e69ac1cc | ||
|
|
25281d0c6f | ||
|
|
0ab3da1512 | ||
|
|
80d4799073 | ||
|
|
71353042c3 | ||
|
|
b5c3fb16cb | ||
|
|
3e3159f03b | ||
|
|
97a2044f5e | ||
|
|
fd1093180f | ||
|
|
68f3d6c056 | ||
|
|
6002e73a59 | ||
|
|
1e0fd60d4e | ||
|
|
f0d5cda1c5 | ||
|
|
04f8630d96 | ||
|
|
440db9ba7e | ||
|
|
44fca49e3f | ||
|
|
061220263c | ||
|
|
428f8a68bf | ||
|
|
03f3e4595e | ||
|
|
21fe26d042 | ||
|
|
38f79e9244 | ||
|
|
2ff4ec81ac | ||
|
|
3d24f63fd7 | ||
|
|
e8c66db876 | ||
|
|
f38811ae9d | ||
|
|
74693c5f6e | ||
|
|
3f2560655e | ||
|
|
bac596ff5b | ||
|
|
b7561b6cfc | ||
|
|
afb41ebc05 | ||
|
|
4961f4859e | ||
|
|
0b18e1ae88 | ||
|
|
217fcaaddc | ||
|
|
f77c23f781 | ||
|
|
639c7bb876 | ||
|
|
b9a5498279 | ||
|
|
3a8e98bb82 | ||
|
|
f2e5e66383 | ||
|
|
2a52d3c52e | ||
|
|
7332d0aa37 | ||
|
|
1e7f248d28 | ||
|
|
a381eb3d5a | ||
|
|
70f2d82963 | ||
|
|
2dc0a6bc95 | ||
|
|
b37a458a1d | ||
|
|
e2257c5046 | ||
|
|
e3ee433b49 | ||
|
|
16e4b2ae40 | ||
|
|
0a513fe088 | ||
|
|
f0cd18e711 | ||
|
|
9559e9fff3 | ||
|
|
e6c869a438 | ||
|
|
f701a142c8 | ||
|
|
f02cfc5a1a | ||
|
|
14e5446696 | ||
|
|
61dc029867 | ||
|
|
9f00055454 | ||
|
|
bf4a01971d | ||
|
|
5b1d060e5a | ||
|
|
8582f74e3e | ||
|
|
fcfeacdd82 | ||
|
|
78902caf30 | ||
|
|
03d5a8357a | ||
|
|
c8f6f1b4f2 | ||
|
|
519df8c33b | ||
|
|
14205b4145 | ||
|
|
cf6eadcc8c | ||
|
|
ab5e9c8344 | ||
|
|
c1f9a86dd3 | ||
|
|
5204a34031 | ||
|
|
4c980e64ac | ||
|
|
ad772b7706 | ||
|
|
471299bd21 | ||
|
|
fc945fbab9 | ||
|
|
defc97dc35 | ||
|
|
e239cb551d | ||
|
|
bceecbf377 | ||
|
|
6bdbfe4aa0 | ||
|
|
243fab3a05 | ||
|
|
24470ffe11 | ||
|
|
cb04731319 | ||
|
|
16db12231a | ||
|
|
9e6385c00a | ||
|
|
5d79dfa6be | ||
|
|
6ccc65a85a | ||
|
|
58d2a2460b | ||
|
|
df887cba61 | ||
|
|
e68ad67070 | ||
|
|
8c9a4f9d3b | ||
|
|
d853f0e7f9 | ||
|
|
5e60f65711 | ||
|
|
ad72465a04 | ||
|
|
df75bc04f8 | ||
|
|
442c5870c4 | ||
|
|
08495a3cb2 | ||
|
|
06de76ed58 | ||
|
|
23f3ca2c5c | ||
|
|
4939c281aa | ||
|
|
02d15211fa | ||
|
|
be6f7671c8 | ||
|
|
76cd1b9cad | ||
|
|
57cfa6f5a0 | ||
|
|
aa5bcf97d2 | ||
|
|
fbf05d5263 | ||
|
|
f54a8002a7 | ||
|
|
c25b10bb78 | ||
|
|
703279a2f8 | ||
|
|
beae99c71b | ||
|
|
7478a323ab | ||
|
|
31a273446b | ||
|
|
e1e51eb124 | ||
|
|
95327fd3a3 | ||
|
|
533eed11f0 | ||
|
|
eb68a43544 | ||
|
|
7bd1156cda | ||
|
|
0c7e33b2f1 | ||
|
|
a9623ff698 | ||
|
|
44d97b64b9 | ||
|
|
e4778dea36 | ||
|
|
c3421b42c7 | ||
|
|
10bbe516d7 | ||
|
|
771e33109d | ||
|
|
ec81d5a964 | ||
|
|
ee1628dbdf | ||
|
|
a1c2c9efbd | ||
|
|
f2070332e9 | ||
|
|
5079ece2dc | ||
|
|
6a791713ea | ||
|
|
41c9568d80 | ||
|
|
698f3d2821 | ||
|
|
a86ea5d12f | ||
|
|
fea9837f30 | ||
|
|
72a11e51a2 | ||
|
|
b9e1406f5b | ||
|
|
564b425b8f | ||
|
|
532dd78aa8 | ||
|
|
5f969c703f | ||
|
|
675b0a39fc | ||
|
|
0a62472840 | ||
|
|
faa8545fcf | ||
|
|
7d98a01e9a | ||
|
|
d74d3b282d | ||
|
|
747e9438c9 | ||
|
|
b6ae809b56 | ||
|
|
c999ae9da4 | ||
|
|
61eff01008 | ||
|
|
f2ee9afa88 | ||
|
|
dc5ac7b3a3 | ||
|
|
612fbf8f38 | ||
|
|
f97a8728fd | ||
|
|
1c1ddaf3d0 | ||
|
|
30316222f3 | ||
|
|
d53e6b767c | ||
|
|
661a1b5839 | ||
|
|
cb2485ae3d | ||
|
|
fa70bf3ff8 | ||
|
|
a32419d07d | ||
|
|
c2e806e318 | ||
|
|
ba8bbc462d | ||
|
|
c4a04d3dca | ||
|
|
1135458d60 | ||
|
|
3d2aa17cf2 | ||
|
|
3baf1f17bf | ||
|
|
f8ecbb7806 | ||
|
|
8f3f2a20c1 | ||
|
|
7935644115 | ||
|
|
dde3eca10e | ||
|
|
ae60a08baa | ||
|
|
676e4a2cd4 | ||
|
|
7f66d4690e | ||
|
|
40fccc57ed | ||
|
|
df44cc0779 | ||
|
|
d29e2f3994 | ||
|
|
3c6b485321 | ||
|
|
4e08c0f3cf | ||
|
|
c9c45ec8d1 | ||
|
|
af4d1e650c | ||
|
|
3412cb6e45 | ||
|
|
9cbf9f3942 | ||
|
|
837e5764b8 | ||
|
|
491c27cd74 | ||
|
|
bddb517583 | ||
|
|
843cc89547 | ||
|
|
4324b8dfc5 | ||
|
|
078a65a8bf | ||
|
|
17aa37f17b | ||
|
|
d30d951494 | ||
|
|
7bc76bdee4 | ||
|
|
4fc1a87ead | ||
|
|
4b8e157098 | ||
|
|
8fef756172 | ||
|
|
7aab27a60f | ||
|
|
2ebcc52358 | ||
|
|
7e83bad920 | ||
|
|
052ea72e87 | ||
|
|
37dd04746b | ||
|
|
c0a815f36e | ||
|
|
8fa1e3dd79 | ||
|
|
61c9bdea92 | ||
|
|
d804ca40f4 | ||
|
|
aa3d09a55c | ||
|
|
5a65ee5254 | ||
|
|
a50c7d34ff | ||
|
|
b98ab87ae7 | ||
|
|
f90f1ec7c0 | ||
|
|
b8edecc092 | ||
|
|
3b73e3d49d | ||
|
|
580afb5a21 | ||
|
|
a673756664 | ||
|
|
0499639473 | ||
|
|
69dd14682c | ||
|
|
d9fa110156 | ||
|
|
3f9fc67ab4 | ||
|
|
43c82fb028 | ||
|
|
01c0fa9563 | ||
|
|
ffce78808e | ||
|
|
e4d5ffb281 | ||
|
|
b8422e7299 | ||
|
|
d7641455d4 | ||
|
|
b6e56ae42c | ||
|
|
52cfa061c4 | ||
|
|
9208debb1a | ||
|
|
5da4e9f4a8 | ||
|
|
f30bfb20ef | ||
|
|
798eee940c | ||
|
|
9c44356d5a | ||
|
|
e241ad349a | ||
|
|
25f5b82cff | ||
|
|
5776f56f7b | ||
|
|
20da15c931 | ||
|
|
0b68dd0e85 | ||
|
|
4e49e69c16 | ||
|
|
8c775896b2 | ||
|
|
9af1168004 | ||
|
|
c1986623ed | ||
|
|
700a39f4c5 | ||
|
|
738cae727e | ||
|
|
08536f0850 | ||
|
|
ddca72e8bd | ||
|
|
3ddbf3aca7 | ||
|
|
52ed21cae5 | ||
|
|
f7dd5d92ac | ||
|
|
4d3e1c713a | ||
|
|
b54f6310f3 | ||
|
|
008bdfdad5 | ||
|
|
ffa6c115e1 | ||
|
|
ae3d59fc47 | ||
|
|
3207aeb741 | ||
|
|
b3949aa3cc | ||
|
|
6e9d29937d | ||
|
|
96dca60a2b | ||
|
|
8d3a7f2526 | ||
|
|
ac9f51a0f3 | ||
|
|
8ffd06025e | ||
|
|
576f424bc0 | ||
|
|
ec5c92e369 | ||
|
|
6a97b3dee5 | ||
|
|
70070daf1c | ||
|
|
482e4097d8 | ||
|
|
f774b4bbcf | ||
|
|
47938a1072 | ||
|
|
93449c9320 | ||
|
|
e93310b9bf | ||
|
|
9a26889fc7 | ||
|
|
106fdc72c4 | ||
|
|
6224d8fbbe | ||
|
|
b1a195c67e | ||
|
|
607fbb609c | ||
|
|
13e186576b | ||
|
|
d30041dfe7 | ||
|
|
dc14024dd7 | ||
|
|
bd95bc12ba | ||
|
|
0b67883de8 | ||
|
|
64e1d6b27e | ||
|
|
7a840f1a6e | ||
|
|
35ac4e91f6 | ||
|
|
9a03074283 | ||
|
|
0ed68957db | ||
|
|
44d4e4f78f | ||
|
|
4506f06b01 | ||
|
|
813e3227ad | ||
|
|
3bbccf2c3c | ||
|
|
810677014c | ||
|
|
f81ef16012 | ||
|
|
c33a9ea975 | ||
|
|
f672231eec | ||
|
|
9876189c64 | ||
|
|
2f84ac6fee | ||
|
|
692904dc5e | ||
|
|
c02aceeead | ||
|
|
ee24b58a2c | ||
|
|
29d1cda756 | ||
|
|
343df3f97c | ||
|
|
089eeb2956 | ||
|
|
da2e2dbf20 | ||
|
|
8501a0b818 | ||
|
|
59a9f73872 | ||
|
|
b3438ccc86 | ||
|
|
72a57edaa3 | ||
|
|
b19a63f69a | ||
|
|
71a600e308 | ||
|
|
ebb9758d28 | ||
|
|
e9e25f8800 | ||
|
|
b42226c490 | ||
|
|
15965cd1b1 | ||
|
|
8fef564297 | ||
|
|
81f01996db | ||
|
|
00c378ad94 | ||
|
|
85eefe9a54 | ||
|
|
43cbc44941 | ||
|
|
f7540e7e36 | ||
|
|
c0a8c02c26 | ||
|
|
c054712828 | ||
|
|
f20616e6b7 | ||
|
|
e518c146f0 | ||
|
|
602115266a | ||
|
|
4e074af139 | ||
|
|
cceaf2bc02 | ||
|
|
acb49d2b69 | ||
|
|
4d84924da0 | ||
|
|
cc94913e16 | ||
|
|
13459bd136 | ||
|
|
b285b1c17f | ||
|
|
05c18658a0 | ||
|
|
f1a52f55d9 | ||
|
|
ea05052677 | ||
|
|
13311c374f | ||
|
|
daa288c1cc | ||
|
|
38b613ac5f | ||
|
|
7429f454eb | ||
|
|
3c119fe3e8 | ||
|
|
428525e1bd | ||
|
|
e07dbf374c | ||
|
|
f1306dfbee | ||
|
|
db4663cbf9 | ||
|
|
3760275937 | ||
|
|
b4afeac71f | ||
|
|
b19c543988 | ||
|
|
0a5ce00878 | ||
|
|
bfe256c578 | ||
|
|
af31c84982 | ||
|
|
67a2ad241a | ||
|
|
8a9449e240 | ||
|
|
95ef59be68 | ||
|
|
8463fb402e | ||
|
|
0f4391bdd1 | ||
|
|
2738019c3f | ||
|
|
ce3e76aa3d | ||
|
|
9d76b6c5cc | ||
|
|
6e023222de | ||
|
|
6b62fc7963 | ||
|
|
d38962868b | ||
|
|
3a0ee7de94 | ||
|
|
dff21145d0 | ||
|
|
81bf80d8b0 | ||
|
|
d2e1b556ba | ||
|
|
97b263cf57 | ||
|
|
fa140f09fc | ||
|
|
2cb824c1e1 | ||
|
|
9dc5c60100 | ||
|
|
8212810276 | ||
|
|
44d772a32f | ||
|
|
fbe3e1b44f | ||
|
|
d56fe9f9b0 | ||
|
|
9d3d347fb7 | ||
|
|
30fcab6626 | ||
|
|
44f25f7497 | ||
|
|
53c4a74074 | ||
|
|
a126c8f06d | ||
|
|
2ed81ef9be | ||
|
|
3a844767f0 | ||
|
|
3667b72634 | ||
|
|
3f8d272eee | ||
|
|
a15daa87c5 | ||
|
|
d6092fc3eb | ||
|
|
4d2c7bd776 | ||
|
|
78947d51dc | ||
|
|
8d7e482219 | ||
|
|
14d313686c | ||
|
|
b79bd9a30e | ||
|
|
891885fcb3 | ||
|
|
e1986612d5 | ||
|
|
4c9435594d | ||
|
|
cc353f5956 | ||
|
|
a90971b762 | ||
|
|
f32edcde74 | ||
|
|
177a7d3054 | ||
|
|
c693146e15 | ||
|
|
296358e473 | ||
|
|
06d5628180 | ||
|
|
9085bbff96 | ||
|
|
0171ce64e4 | ||
|
|
222ff4a6de | ||
|
|
1c46f2436c | ||
|
|
65654fdef2 | ||
|
|
9035d68d96 | ||
|
|
41b2d2bce7 | ||
|
|
b67c2dc625 | ||
|
|
ec0d738e9f | ||
|
|
028da06b34 | ||
|
|
dd5037cb07 | ||
|
|
5406c0156a | ||
|
|
2f97583289 | ||
|
|
fcde65eaee | ||
|
|
8fccdae675 | ||
|
|
50cb0528c6 | ||
|
|
3cf0c2f804 | ||
|
|
fad9e8516e | ||
|
|
7b3d4739aa | ||
|
|
e9f7046a05 | ||
|
|
9ce7239308 | ||
|
|
acc5a88a27 | ||
|
|
1cc99231ae | ||
|
|
39e0784714 | ||
|
|
9f0569cd0b | ||
|
|
d455ef3e33 | ||
|
|
691918cfc8 | ||
|
|
df294eee15 | ||
|
|
3a94ea35f6 | ||
|
|
4f711d8a34 | ||
|
|
c5ec653215 | ||
|
|
937b83d776 | ||
|
|
8b585a06e7 | ||
|
|
a53f88cbaf | ||
|
|
604a9212ca | ||
|
|
09d7e8abde | ||
|
|
1ddfcff441 | ||
|
|
08eb168f06 | ||
|
|
f0f6fd6887 | ||
|
|
892df7bd0c | ||
|
|
1a672a8aa3 | ||
|
|
8ec9a8ae22 | ||
|
|
defa18724c | ||
|
|
f56f965d06 | ||
|
|
1ea488024b | ||
|
|
4f85734de5 | ||
|
|
a3b6e6f161 | ||
|
|
ff1e851143 | ||
|
|
95f19bde45 | ||
|
|
457110fa62 | ||
|
|
23195e03b8 | ||
|
|
c9feaa7074 | ||
|
|
6ec5df9309 | ||
|
|
892e5fab1f | ||
|
|
15424a2617 | ||
|
|
5188c0f473 | ||
|
|
c91552339c | ||
|
|
8565b74510 | ||
|
|
7524bc3bc3 | ||
|
|
038d0e038b | ||
|
|
077e1a697b | ||
|
|
f5053bbc22 | ||
|
|
baf61c0bdb | ||
|
|
e3dcfb9136 | ||
|
|
e4c71fb3e4 | ||
|
|
44e947ac8a | ||
|
|
fc7e2400cf | ||
|
|
e30e164ba3 | ||
|
|
007e013514 | ||
|
|
10b5d2c4f7 | ||
|
|
ef9b15d924 | ||
|
|
a44bc68e81 | ||
|
|
ec75d17bcf | ||
|
|
ad5f9a3762 | ||
|
|
a720065a45 | ||
|
|
6342e0b243 | ||
|
|
e9814504db | ||
|
|
145cf9820a | ||
|
|
d7fae910fb | ||
|
|
d15474c243 | ||
|
|
805f377459 | ||
|
|
bf320261f9 | ||
|
|
fb94597409 | ||
|
|
93e4bd8cd0 | ||
|
|
dfa839526c | ||
|
|
0d1f138459 | ||
|
|
ace47d6515 | ||
|
|
87c1808b7e | ||
|
|
95627f3617 | ||
|
|
9c20ac68f5 | ||
|
|
ed1665d625 | ||
|
|
c6de70f57f | ||
|
|
28dcfd714e | ||
|
|
1ed6099878 | ||
|
|
5e9c2fc255 | ||
|
|
f9a4e3c9fc | ||
|
|
9d7582caa6 | ||
|
|
f9d47de8f2 | ||
|
|
e057b64055 | ||
|
|
5968e3d065 | ||
|
|
b22bb295af | ||
|
|
fb3ecd4cf7 | ||
|
|
65b4454f2c | ||
|
|
3e5f178c4d | ||
|
|
35f87f6361 | ||
|
|
c2141dc034 | ||
|
|
6e460c5584 | ||
|
|
3a523a514c | ||
|
|
e1e654c6b7 | ||
|
|
161009c4ac | ||
|
|
6cb2649981 | ||
|
|
6089e2e267 | ||
|
|
ac6bf02b2d | ||
|
|
365bbaf2ad | ||
|
|
f320ef4721 | ||
|
|
87a34f2fbb | ||
|
|
defdd904c8 | ||
|
|
3f91c33eae | ||
|
|
2e3642671f | ||
|
|
02e2f42481 | ||
|
|
168f37dc8a | ||
|
|
38aeda6d83 | ||
|
|
eb29b626d0 | ||
|
|
e50839b7cc | ||
|
|
082086ffa3 | ||
|
|
7327b995e1 | ||
|
|
a6fb23302e | ||
|
|
055518da79 | ||
|
|
6d903a526b | ||
|
|
8d0c230c30 | ||
|
|
440e71d983 | ||
|
|
328cc89e39 | ||
|
|
e4fd5d7293 | ||
|
|
77d8fbbfc5 | ||
|
|
fd4f484bab | ||
|
|
e116c52ea9 | ||
|
|
46fbd93d9b | ||
|
|
bd1805750b | ||
|
|
114663836c | ||
|
|
82c5e88c4a | ||
|
|
a0ec26a755 | ||
|
|
a29386c7a1 | ||
|
|
0ea25b46f7 | ||
|
|
63b471780d | ||
|
|
25065a66aa | ||
|
|
60c64fcb6c | ||
|
|
e5f8a83c7f | ||
|
|
39811e7a2e | ||
|
|
04cb611183 | ||
|
|
f15a73200f | ||
|
|
a6f3c879a5 | ||
|
|
811e5479f4 | ||
|
|
13af95f600 | ||
|
|
b6743725e0 | ||
|
|
d3579218f2 | ||
|
|
ff003d9603 | ||
|
|
805b27074c | ||
|
|
22e34da132 | ||
|
|
71119b8d81 | ||
|
|
ef2886ffc7 | ||
|
|
770b85ebd2 | ||
|
|
f75f992a59 | ||
|
|
113f1fac6a | ||
|
|
de58da6dab | ||
|
|
256eeb863c | ||
|
|
7420f2ff98 | ||
|
|
b2b968f915 | ||
|
|
12d89d8c4a | ||
|
|
476e64c389 | ||
|
|
e183f39dfd | ||
|
|
f9e34ce9d5 | ||
|
|
6bdd976209 | ||
|
|
efd64ecded | ||
|
|
50db978fa2 | ||
|
|
de410bf75f | ||
|
|
2ff7825b34 | ||
|
|
9b1ae75a00 | ||
|
|
e7f0911f8b | ||
|
|
c004beab02 | ||
|
|
fa758c51ee | ||
|
|
1aa2282321 | ||
|
|
9094c44b07 | ||
|
|
c46036761c | ||
|
|
5d2f3cd2a7 | ||
|
|
76f1902cae | ||
|
|
5801c329b2 | ||
|
|
302833eb22 | ||
|
|
f30b25e23f | ||
|
|
211e8c438a | ||
|
|
4a33ed8fc2 | ||
|
|
556ea8754c | ||
|
|
d2fdd37084 | ||
|
|
12e2f146bf | ||
|
|
eae701012a | ||
|
|
c4ae2c5c1b | ||
|
|
fb52bf3984 | ||
|
|
6c0ae235f0 | ||
|
|
399f867016 | ||
|
|
bb947ac0a9 | ||
|
|
30813f5efc | ||
|
|
411e6720e1 | ||
|
|
1255dc03b2 | ||
|
|
61e060b8ef | ||
|
|
18b009f6af | ||
|
|
d4b246e37f | ||
|
|
4da052279e | ||
|
|
12a9afe2fe | ||
|
|
e2a0314742 | ||
|
|
bdd4df9dd7 | ||
|
|
491a28c03e | ||
|
|
dc389e0f41 | ||
|
|
121f9b547c | ||
|
|
6c03a00f57 | ||
|
|
58ec18f47d | ||
|
|
973a92886b | ||
|
|
4497c4be66 | ||
|
|
33ec8d0041 | ||
|
|
215867ae21 | ||
|
|
4711c0f785 | ||
|
|
ad1dece946 | ||
|
|
dc202f987a | ||
|
|
12fbee8597 | ||
|
|
856621a8a7 | ||
|
|
2c4bda882f | ||
|
|
7f524153a6 | ||
|
|
6652f8cb65 | ||
|
|
b00dfb6135 | ||
|
|
93960dd1b8 | ||
|
|
d105045b75 | ||
|
|
49d21bbba8 | ||
|
|
b1f05c38b3 | ||
|
|
9f7ed802ea | ||
|
|
9b7313ce95 | ||
|
|
d42896a19c | ||
|
|
2729b8ece8 | ||
|
|
85ed99a1dc | ||
|
|
aa7959b91c | ||
|
|
781d9dd440 | ||
|
|
483a346faa | ||
|
|
6e9f368a0a | ||
|
|
84a3688525 | ||
|
|
3c08986889 | ||
|
|
477828beb9 | ||
|
|
fadc6c46ba | ||
|
|
3111166f89 | ||
|
|
f7c8b62f6c | ||
|
|
e6edc6ae03 | ||
|
|
3bc0799091 | ||
|
|
1285955e32 | ||
|
|
5fdc8cb32c | ||
|
|
8538a77db7 | ||
|
|
329b84f7b5 | ||
|
|
4dcb7acd58 | ||
|
|
d91f9cf29f | ||
|
|
1a04dec97b | ||
|
|
c6f95a9030 | ||
|
|
62d2157fd8 | ||
|
|
d0c61ea5fa | ||
|
|
b9c7d108e5 | ||
|
|
20a8597b45 | ||
|
|
9a1ada97ec | ||
|
|
0ebe32228d | ||
|
|
ad5da12154 | ||
|
|
cdd2e0dd1d | ||
|
|
3fe10212d5 | ||
|
|
97e97a6cfc | ||
|
|
9cb8d9d65e | ||
|
|
eadf3b46e0 | ||
|
|
5d97a16d75 | ||
|
|
e13ca70143 | ||
|
|
732493d663 | ||
|
|
569284ef60 | ||
|
|
85a1891b8c | ||
|
|
6a67344643 | ||
|
|
0bff0a7878 | ||
|
|
925d26f02b | ||
|
|
45539289fd | ||
|
|
4cbcddf3c0 | ||
|
|
304d63c6a2 | ||
|
|
ec784b4a98 | ||
|
|
1b899f2228 | ||
|
|
a8d437720b | ||
|
|
fc7c9e1c0a | ||
|
|
514607a731 | ||
|
|
9344e08d7b | ||
|
|
13cec0dd31 | ||
|
|
b80e890fd6 | ||
|
|
e54c07325e | ||
|
|
3107705e25 | ||
|
|
62db7b8382 | ||
|
|
8e8fefef36 | ||
|
|
0c178ec71f | ||
|
|
3c9c3cb709 | ||
|
|
2ebfd108ea | ||
|
|
31df3927c5 | ||
|
|
c1b7e06308 | ||
|
|
8368eb4541 | ||
|
|
ce995a9380 | ||
|
|
110d773e3c | ||
|
|
6965591e7b | ||
|
|
4b47cfda57 | ||
|
|
e7db4d6b67 | ||
|
|
c8a63044af | ||
|
|
622b27448f | ||
|
|
e2814141d4 | ||
|
|
1a0f70c56b | ||
|
|
e86ec32dd7 | ||
|
|
4667a14080 | ||
|
|
c8bd2ec1a1 | ||
|
|
933625011c | ||
|
|
c032541f69 | ||
|
|
78b9bf9823 | ||
|
|
3cf94bb728 | ||
|
|
ae1ee69d25 | ||
|
|
bf6bb93829 | ||
|
|
61ef7dfc75 | ||
|
|
82948e56d2 | ||
|
|
2338c5a4fa | ||
|
|
63b60999f8 | ||
|
|
5857a3aed7 | ||
|
|
364d41737f | ||
|
|
31c69477f4 | ||
|
|
d1e9477fb4 | ||
|
|
f325b778a9 | ||
|
|
a7270f7510 | ||
|
|
5da493713f | ||
|
|
ca0a7689be | ||
|
|
6efe19d50c | ||
|
|
08ce7c9186 | ||
|
|
cd25f0c723 | ||
|
|
fd6554658b | ||
|
|
8abc8ab0e4 | ||
|
|
7a16e7743e | ||
|
|
aac3cf2b69 | ||
|
|
c30a5e437f | ||
|
|
473c63267f | ||
|
|
318d8f8ccc | ||
|
|
ee24ab8f6e | ||
|
|
e89ca133cd | ||
|
|
c1292e5a52 | ||
|
|
a236b1f9da | ||
|
|
c9c7794e73 | ||
|
|
29c5717e79 | ||
|
|
ccc8e704b4 | ||
|
|
5991afc1f0 | ||
|
|
58329fd61f | ||
|
|
b7ed8ec246 | ||
|
|
c975ab7b05 | ||
|
|
fdf11d144f | ||
|
|
99f1821215 | ||
|
|
3d14646548 | ||
|
|
b826b1928e | ||
|
|
b6038285f4 | ||
|
|
0f8621d923 | ||
|
|
2d9e9a5e93 | ||
|
|
abeb5fc0e3 | ||
|
|
47e61cecdd | ||
|
|
17aaf08717 | ||
|
|
89e849d851 | ||
|
|
42098f477a | ||
|
|
e44ee9ca03 | ||
|
|
e7831ac960 | ||
|
|
8a48b71a0f | ||
|
|
2e4d50c7b5 | ||
|
|
df501e42b9 | ||
|
|
1d14d37c1d | ||
|
|
0d728ed4ce | ||
|
|
4e2ff445e0 | ||
|
|
f3818803fd | ||
|
|
329668322f | ||
|
|
0ffd0c1530 | ||
|
|
7b7c6fbfae | ||
|
|
b946228ee2 | ||
|
|
61177901e8 | ||
|
|
bb4f8b0d78 | ||
|
|
1a4e701f98 | ||
|
|
968ee917fc | ||
|
|
bbc01c0be9 | ||
|
|
3387b41841 | ||
|
|
d36a578708 | ||
|
|
36d42ab8ba | ||
|
|
ba71f10dee | ||
|
|
7bb1857d0c | ||
|
|
999ce51178 | ||
|
|
a2ebf69551 | ||
|
|
9ef3ba9342 | ||
|
|
88e82a511b | ||
|
|
495c49f277 | ||
|
|
0459091a52 | ||
|
|
ba67529d62 | ||
|
|
9bd16c0b5c | ||
|
|
a0c76052cc | ||
|
|
c4861c5efa | ||
|
|
6b8f46bf81 | ||
|
|
1a71f43c54 | ||
|
|
b4d732656f | ||
|
|
6a335269f4 | ||
|
|
c51f2fa401 | ||
|
|
69072cf0ca | ||
|
|
b023964aec | ||
|
|
59321dbd56 | ||
|
|
f1c282451b | ||
|
|
ff0c34c0b8 | ||
|
|
4380175c8b | ||
|
|
439598d7ee | ||
|
|
08fa24b095 | ||
|
|
c836548fc7 | ||
|
|
f109146379 | ||
|
|
8ff46bba74 | ||
|
|
af7f4e3bc4 | ||
|
|
06f1305f23 | ||
|
|
ddc299fa08 | ||
|
|
43df9d25f0 | ||
|
|
250ac0e8ba | ||
|
|
29d960878c | ||
|
|
8e6634ff0f | ||
|
|
15b5cf9750 | ||
|
|
c001c4b5bd | ||
|
|
43723697f7 | ||
|
|
99d6a0ab32 | ||
|
|
c2809ca091 | ||
|
|
108432c268 | ||
|
|
aa0db4b665 | ||
|
|
cda62b8a3e | ||
|
|
970242e860 | ||
|
|
9c741da4e8 | ||
|
|
2dfd43c8ba | ||
|
|
5536687d90 | ||
|
|
34c421733e | ||
|
|
b0b29443a5 | ||
|
|
a637dcd28d | ||
|
|
b6b3ec04be | ||
|
|
6586f51791 | ||
|
|
dff2e344a4 | ||
|
|
92e4e81788 | ||
|
|
aa9ee7e1af | ||
|
|
2d3f2f4b36 | ||
|
|
73fe4d68f1 | ||
|
|
d244602818 | ||
|
|
67d9c6ed4e | ||
|
|
55f8932495 | ||
|
|
24617f4a41 | ||
|
|
5d47009e07 | ||
|
|
c46acc1ad4 | ||
|
|
20051a835b | ||
|
|
2ae0f36241 | ||
|
|
873e33a04f | ||
|
|
e33c5d7cbc | ||
|
|
b729ec1a85 | ||
|
|
9b18ecf072 | ||
|
|
88c4ae5721 | ||
|
|
d2b94955d1 | ||
|
|
dbcc00fe1a | ||
|
|
b56ae68854 | ||
|
|
312ea7d962 | ||
|
|
ceb3b562e6 | ||
|
|
b211009e91 | ||
|
|
eec372c6df | ||
|
|
011e83fac6 | ||
|
|
70fa577e10 | ||
|
|
dd8e55c2ac | ||
|
|
b8f3f53d56 | ||
|
|
d5623dabb6 | ||
|
|
db50687a1e | ||
|
|
00fcd5a9b6 | ||
|
|
272fd58481 | ||
|
|
ecbde48f63 | ||
|
|
3dda43c70a | ||
|
|
39827e449b | ||
|
|
44d0c78077 | ||
|
|
34029c6f6f | ||
|
|
929b8c2d50 | ||
|
|
b71a64c214 | ||
|
|
66c5d408c6 | ||
|
|
ab1dbd0d5c | ||
|
|
cc307e3217 | ||
|
|
e3c45a5039 | ||
|
|
6754efc486 | ||
|
|
1e5d9d314b | ||
|
|
cea6aaf7ff | ||
|
|
c1f019e71c | ||
|
|
c00b511c17 | ||
|
|
51c6067c17 | ||
|
|
c032e74e58 | ||
|
|
412d40d041 | ||
|
|
2cc69a0725 | ||
|
|
89b3b6da61 | ||
|
|
77a7fffcb2 | ||
|
|
30a9c8c90e | ||
|
|
abd52c7a42 | ||
|
|
9bb164246e | ||
|
|
87d0e18696 | ||
|
|
e8f5864dd9 | ||
|
|
51d7b3f413 | ||
|
|
fb3de84aa4 | ||
|
|
4a2aa91b6d | ||
|
|
a4edac59c6 | ||
|
|
19af59b301 | ||
|
|
d1b27dfd9d | ||
|
|
274fb0f380 | ||
|
|
8e70567688 | ||
|
|
7cbc24feb8 | ||
|
|
2bdcf3919e | ||
|
|
8214f4ba20 | ||
|
|
d0a5fc24b1 | ||
|
|
c8084c670a | ||
|
|
82a9779b09 | ||
|
|
fdb887e43a | ||
|
|
7761244eec | ||
|
|
6580334bdd | ||
|
|
e2f7a22457 | ||
|
|
494382f5cb | ||
|
|
2ff248a4c4 | ||
|
|
7ed15a2dbc | ||
|
|
3d1725054a | ||
|
|
d6e37f9f13 | ||
|
|
2c78bef505 | ||
|
|
d60b9706b3 | ||
|
|
d20996d788 | ||
|
|
0010976803 | ||
|
|
bd422323ee | ||
|
|
6a66d99017 | ||
|
|
f1d87da9b6 | ||
|
|
ac8674a8b3 | ||
|
|
c2af7914e3 | ||
|
|
102db4c937 | ||
|
|
1f7d92b209 | ||
|
|
555cc74312 | ||
|
|
761319c13d | ||
|
|
828e867ac9 | ||
|
|
6a7b4f107e | ||
|
|
c0df364b4f | ||
|
|
71c72136f6 | ||
|
|
ec5f8fc4f5 | ||
|
|
f5e6ed914d | ||
|
|
2e7bc894f1 | ||
|
|
7f57e64292 | ||
|
|
18537b9cdb | ||
|
|
ed5cb715da | ||
|
|
300a0ece75 | ||
|
|
3172ba213e | ||
|
|
32cf86ede5 | ||
|
|
97f320c9a7 | ||
|
|
7c6dd75a23 | ||
|
|
6a59355514 | ||
|
|
91c3413c57 | ||
|
|
717f5f6e2e | ||
|
|
f48efae82d | ||
|
|
5f372ebee3 | ||
|
|
5b27fad3aa | ||
|
|
5685ccbffd | ||
|
|
6149a951bd | ||
|
|
2529205359 | ||
|
|
81b71a7676 | ||
|
|
29c80f7845 | ||
|
|
05372fc4a4 | ||
|
|
50e433aba0 | ||
|
|
ac4797a943 | ||
|
|
3e372f753d | ||
|
|
3c7baa7237 | ||
|
|
3f9d6e48b5 | ||
|
|
79adfe70a4 | ||
|
|
ae8b616fed | ||
|
|
0b8b2db41e | ||
|
|
63183b33f1 | ||
|
|
de09d1dbd2 | ||
|
|
b59e318444 | ||
|
|
51ea8a5e1c | ||
|
|
0a65da2fc4 | ||
|
|
d3c634b89f | ||
|
|
e46be54688 | ||
|
|
e4f8a51df8 | ||
|
|
a51f48f060 | ||
|
|
32df0c1730 | ||
|
|
530c8818b7 | ||
|
|
6c99f73596 | ||
|
|
61acaaa054 | ||
|
|
eca341d7ec | ||
|
|
25b695bc32 | ||
|
|
0f41cb5ad4 | ||
|
|
454ca3b136 | ||
|
|
e3b8b450a4 | ||
|
|
c15c486603 | ||
|
|
40e57e3a54 | ||
|
|
c6554afaae | ||
|
|
0d6b5ce68c | ||
|
|
2830400da5 | ||
|
|
113b05ed05 | ||
|
|
824ce88914 | ||
|
|
aa8edf1ee9 | ||
|
|
f1bf439f7b | ||
|
|
220992fc37 | ||
|
|
a1e243714e | ||
|
|
1c0ed64f67 | ||
|
|
1f1cd1b6d7 | ||
|
|
e81725eb16 | ||
|
|
ee4220e1ce | ||
|
|
a733c6c68d | ||
|
|
d7c7619218 | ||
|
|
77066ba7e5 | ||
|
|
35c5919c44 | ||
|
|
fcdd286965 | ||
|
|
e84fa1d636 | ||
|
|
de52af79c5 | ||
|
|
c555102b5f | ||
|
|
4c05175dbe | ||
|
|
de543fa2db | ||
|
|
bfe9bad905 | ||
|
|
459b6bc6fe | ||
|
|
332211fb13 | ||
|
|
a0f85bd55a | ||
|
|
7273caac36 | ||
|
|
d8383dc38a | ||
|
|
7824ab8dc9 | ||
|
|
7320bf68e5 | ||
|
|
e5d42cf0eb | ||
|
|
d7b9492f15 | ||
|
|
6a7b782309 | ||
|
|
9d080d7dca | ||
|
|
424df8d4fe | ||
|
|
2f4422f719 | ||
|
|
831611af1e | ||
|
|
c302d362a4 | ||
|
|
69d4b1096f | ||
|
|
2514a89286 | ||
|
|
2034055148 | ||
|
|
3a3b1007b9 | ||
|
|
2582dfe3c4 | ||
|
|
295411a5d2 | ||
|
|
09a83b36ff | ||
|
|
32cc59228d | ||
|
|
31b2413953 | ||
|
|
c8eb643818 | ||
|
|
11b251003e | ||
|
|
28bb0e99cb | ||
|
|
5c9c686317 | ||
|
|
098425bdbf | ||
|
|
5189f6b392 | ||
|
|
f487479b1d | ||
|
|
03224cc4f6 | ||
|
|
482754eddb | ||
|
|
7fcf6874e3 | ||
|
|
a3e0eee8d4 | ||
|
|
453589de92 | ||
|
|
b7ffb06f9c | ||
|
|
35a209bcb6 | ||
|
|
c3a2a15608 | ||
|
|
9acdfe5dcf | ||
|
|
9ec8056d89 | ||
|
|
b9c2cc2c4f | ||
|
|
675a2811d4 | ||
|
|
b1df5f533b | ||
|
|
a61cf3f889 | ||
|
|
ace09646c6 | ||
|
|
f42c33d77a | ||
|
|
d2113c4379 | ||
|
|
0d202499bc | ||
|
|
9e60778075 | ||
|
|
be6896f34c | ||
|
|
4e78e4019f | ||
|
|
823d13af34 | ||
|
|
4007870bfb | ||
|
|
5d92f98548 | ||
|
|
e5a3a0637d | ||
|
|
cbbff69003 | ||
|
|
f40240d8cb | ||
|
|
9671599fc9 | ||
|
|
e1be421410 | ||
|
|
068653ad3e | ||
|
|
cd2a2c2639 | ||
|
|
2d37dde8b8 | ||
|
|
42613c79b6 | ||
|
|
f4a80ed856 | ||
|
|
39610bce24 | ||
|
|
124cce55bd | ||
|
|
589aa4ae40 | ||
|
|
41ccba7955 | ||
|
|
ac2613682c | ||
|
|
8a46cfb0da | ||
|
|
9c0643b61f | ||
|
|
4d755d3795 | ||
|
|
9fe61d2342 | ||
|
|
d0273febf9 | ||
|
|
5610ed6e15 | ||
|
|
89ff894917 | ||
|
|
e2b6f0c70f | ||
|
|
654741261b | ||
|
|
1f17d79e2d | ||
|
|
3b0c7f1d5b | ||
|
|
f2831f84df | ||
|
|
d30edee790 | ||
|
|
2635ed69ac | ||
|
|
18e0044373 | ||
|
|
a9759a20c2 | ||
|
|
f5b9673044 | ||
|
|
9756bfbc4d | ||
|
|
1ae125ceb1 | ||
|
|
443d010a59 | ||
|
|
fcdc704cc2 | ||
|
|
0815cc3b5e | ||
|
|
2416cf6ad5 | ||
|
|
9cf03fcbb0 | ||
|
|
43c524533c | ||
|
|
600ae5aed6 | ||
|
|
a9fb352fd9 | ||
|
|
dd2434d4b4 | ||
|
|
3f221878e8 | ||
|
|
876dbb3ab4 | ||
|
|
97e7b1982f | ||
|
|
ddff78756d | ||
|
|
d78df859b1 | ||
|
|
aa09f8789c | ||
|
|
106ffe5df7 | ||
|
|
f8c01808d4 | ||
|
|
9de775e0c9 | ||
|
|
e073c82992 | ||
|
|
90a6c85aff | ||
|
|
aa82f96993 | ||
|
|
867a0225f1 | ||
|
|
ead92aac31 | ||
|
|
97ff03f87e | ||
|
|
ec40acfac1 | ||
|
|
52904999fb | ||
|
|
14d296ea38 | ||
|
|
4ab636ded8 | ||
|
|
f764375e0e | ||
|
|
98b20a3e24 | ||
|
|
7f6843b895 | ||
|
|
74ad947ade | ||
|
|
3dc1a156d4 | ||
|
|
b6a6cf052b | ||
|
|
ae3975e3dd | ||
|
|
79b2beba8f | ||
|
|
e7345f678c | ||
|
|
771f8a8430 | ||
|
|
ddef5312fd | ||
|
|
43a7085f7c | ||
|
|
fd11c1d5bd | ||
|
|
5cf06bce7e | ||
|
|
f5232dc5af | ||
|
|
d0cf57cb66 | ||
|
|
ca17a5453a | ||
|
|
713ecb3be7 | ||
|
|
e43265fe57 | ||
|
|
9642f9ae41 | ||
|
|
5f95859bcd | ||
|
|
6fecf61648 | ||
|
|
85c199d563 | ||
|
|
facb5c747d | ||
|
|
1b517a6eb1 | ||
|
|
99dc6b1623 | ||
|
|
e569b8b9a7 | ||
|
|
f0b0c55d9b | ||
|
|
df179212b1 | ||
|
|
19ccf09c20 | ||
|
|
641382dc66 | ||
|
|
8f89fa4597 | ||
|
|
543eb21a8b | ||
|
|
9fbc62837f | ||
|
|
d194eac5bc | ||
|
|
5ffd03ca85 | ||
|
|
d6dec82610 | ||
|
|
521a166c92 | ||
|
|
2ca97d4e31 | ||
|
|
b30df2f6e2 | ||
|
|
4ab0d765e3 | ||
|
|
58d3929bee | ||
|
|
35eff68f64 | ||
|
|
bb10b0a266 | ||
|
|
9dc050332e | ||
|
|
c65b9d8cc2 | ||
|
|
2d26d1a9d1 | ||
|
|
a2be80501a | ||
|
|
e19462c045 | ||
|
|
8a23bba39a | ||
|
|
105b494710 | ||
|
|
e35ecf96ca | ||
|
|
df16f37912 | ||
|
|
d3dcaa92e5 | ||
|
|
b1e31c9999 | ||
|
|
3a89b16b91 | ||
|
|
06ff48515c | ||
|
|
b870025f88 | ||
|
|
7041a9ca9d | ||
|
|
2f40830630 | ||
|
|
55b7d81922 | ||
|
|
07d63013aa | ||
|
|
70d15cbac5 | ||
|
|
d3d710b2b9 | ||
|
|
4426d81e77 | ||
|
|
fad183e20a | ||
|
|
ad2e977b7c | ||
|
|
6b3e81e3fd | ||
|
|
dd708778d6 | ||
|
|
0bc06f3cae | ||
|
|
0ab8853455 | ||
|
|
bdf5664672 | ||
|
|
83a44c60c1 | ||
|
|
a612ffd2d2 | ||
|
|
43b529ea8b | ||
|
|
bc19a6bb5f | ||
|
|
8cc6a2ddf0 | ||
|
|
c1f0c47cf7 | ||
|
|
7e71eb0aeb | ||
|
|
196f787a1f | ||
|
|
b7bec1793c | ||
|
|
b97aa8e3a7 | ||
|
|
21dcf59f21 | ||
|
|
326b6c8c53 | ||
|
|
7ebf0e7bf8 | ||
|
|
014df8b9d3 | ||
|
|
6d85055147 | ||
|
|
077f7d8855 | ||
|
|
296484360f | ||
|
|
08fa801878 | ||
|
|
426260de00 | ||
|
|
86ff40e408 | ||
|
|
1071f8a045 | ||
|
|
962d3a049c | ||
|
|
4272376278 | ||
|
|
3d2857eec2 | ||
|
|
4c0298aed9 | ||
|
|
161859606a | ||
|
|
a71df0cff6 | ||
|
|
e9917f4fca | ||
|
|
fb9ff0b8c0 | ||
|
|
d1a62baa12 | ||
|
|
cdec7ccfe8 | ||
|
|
25bc3a40f7 | ||
|
|
826ba4c97c | ||
|
|
5ef73d3c08 | ||
|
|
26e1d1d81d | ||
|
|
a76f5498cb | ||
|
|
02e5c1fc44 | ||
|
|
844e9dd8e3 | ||
|
|
39f2ec83d5 | ||
|
|
e4d2af03a5 | ||
|
|
37616d69bf | ||
|
|
4e36f71dd8 | ||
|
|
b5877ac32a | ||
|
|
66075b3d9d | ||
|
|
524773f855 | ||
|
|
92de588a6e | ||
|
|
700f4b5b10 | ||
|
|
9c0a7b6778 | ||
|
|
9a54c66f68 | ||
|
|
83332178a0 | ||
|
|
2935118dab | ||
|
|
fb33c2acf1 | ||
|
|
989d431acf | ||
|
|
3c5914b5d9 | ||
|
|
8c48f72a3c | ||
|
|
2d385c163f | ||
|
|
4e1e6bf776 | ||
|
|
a8ce780718 | ||
|
|
0d50bc9563 | ||
|
|
31eff86578 | ||
|
|
35cefea3a8 | ||
|
|
4fc7700e7e | ||
|
|
3b2c776060 | ||
|
|
892f9f01f6 | ||
|
|
860a58847d | ||
|
|
103e67ab8e | ||
|
|
1ed90d2306 | ||
|
|
aff0b350f3 | ||
|
|
72256e7f8b | ||
|
|
8cdbcdcb8c | ||
|
|
218dba2c78 | ||
|
|
68b8230b99 | ||
|
|
9d872c3fd7 | ||
|
|
651b0be5ed | ||
|
|
cead33c09d | ||
|
|
80602c084f | ||
|
|
9f2b2de261 | ||
|
|
b0420b8b93 | ||
|
|
b47018cbab | ||
|
|
ea69ab6eaf | ||
|
|
92887401b2 | ||
|
|
df0bda6324 | ||
|
|
9d67808496 | ||
|
|
cf33a98f20 | ||
|
|
afbda344ec | ||
|
|
1079597584 | ||
|
|
8110b7ba4b | ||
|
|
af9b411a4c | ||
|
|
cd49d951d8 | ||
|
|
7d63c114aa | ||
|
|
af6f05ba07 | ||
|
|
46f8eb0cdb | ||
|
|
c543bb5a5b | ||
|
|
95ed02f0e4 | ||
|
|
87e94bc5a7 | ||
|
|
d1997089e4 | ||
|
|
57dd0177f9 | ||
|
|
ba76e5ee3d | ||
|
|
b757f18d53 | ||
|
|
76c93b842c | ||
|
|
e73bff5ddf | ||
|
|
7d5c0d754e | ||
|
|
e08a74b129 | ||
|
|
be07aafaf4 | ||
|
|
e2bf27e524 | ||
|
|
b0157adbe2 | ||
|
|
239593afb5 | ||
|
|
b97d764588 | ||
|
|
bf8e7af984 | ||
|
|
bf68c475e5 | ||
|
|
29624239ba | ||
|
|
4cb3c4918b | ||
|
|
26fa0d65e1 | ||
|
|
958baed3df | ||
|
|
40d6fb7565 | ||
|
|
a7551b7dbf | ||
|
|
9ed33c4dc4 | ||
|
|
6b18fbe8f7 | ||
|
|
53b9880ea8 | ||
|
|
62538664df | ||
|
|
f678fb16cc | ||
|
|
fe09aa1cd9 | ||
|
|
710decc610 | ||
|
|
5d481d3528 | ||
|
|
8bcd3b72c5 | ||
|
|
0a0da810e9 | ||
|
|
e630c046fe | ||
|
|
2857b5c53d | ||
|
|
0965c61f55 | ||
|
|
9dd318b176 | ||
|
|
f8beca720c | ||
|
|
d8f58dcc1d | ||
|
|
32aaaa350e | ||
|
|
0f6d1c6817 | ||
|
|
8c5a342a5a | ||
|
|
257401898b | ||
|
|
e7ff3f903a | ||
|
|
6f82638b5d | ||
|
|
0625ce51c4 | ||
|
|
f5670436d0 | ||
|
|
5d20a56ac8 | ||
|
|
020cf9713a | ||
|
|
fe1361fc9c | ||
|
|
36621be496 | ||
|
|
25690030d1 | ||
|
|
fcd6be3a0c | ||
|
|
ad8dfa487c | ||
|
|
7f6f54628d | ||
|
|
8ea0b072c6 | ||
|
|
0df6248226 | ||
|
|
26a132658e | ||
|
|
d02529ee86 | ||
|
|
0cec0fef51 | ||
|
|
e56f6ab75d | ||
|
|
a4980aa8f2 | ||
|
|
fd219b49be | ||
|
|
b90579aadc | ||
|
|
0b39d7f6b6 | ||
|
|
a44ce06162 | ||
|
|
f1eb2ab5d5 | ||
|
|
9a965bfba4 | ||
|
|
7349f37786 | ||
|
|
3d03dfaef7 | ||
|
|
5bf88eaff1 | ||
|
|
f3c4b2ba39 | ||
|
|
92f6fb4588 | ||
|
|
2d6d7fd618 | ||
|
|
3a1d997d5a | ||
|
|
5bbb259c95 | ||
|
|
b8e44767b3 | ||
|
|
6b486beb5c | ||
|
|
aab1265e4e | ||
|
|
676181a4be | ||
|
|
839e5b7c74 | ||
|
|
aff7003ceb | ||
|
|
66aa60f303 | ||
|
|
b196811cf9 | ||
|
|
3fdddadd53 | ||
|
|
7af2d1d3ac | ||
|
|
63670e3245 | ||
|
|
389931bf22 | ||
|
|
76a67d15a3 | ||
|
|
8e65f2d375 | ||
|
|
56737f5d67 | ||
|
|
20f8fae2f0 | ||
|
|
17b5d77d33 | ||
|
|
cbe32c88b6 | ||
|
|
dee291f3f6 | ||
|
|
0b20c8e13f | ||
|
|
c0af0173e9 | ||
|
|
79f4c4b5d2 | ||
|
|
31c8be2ee1 | ||
|
|
061b237032 | ||
|
|
d3466e201d | ||
|
|
c69c7d2194 | ||
|
|
05e1624e47 | ||
|
|
03e32412ca | ||
|
|
451a2376a8 | ||
|
|
167c774446 | ||
|
|
054262a002 | ||
|
|
ecbc3c537f | ||
|
|
d51bbfdfab | ||
|
|
ae343cddbe | ||
|
|
bb03fec604 | ||
|
|
248c9a6b00 | ||
|
|
dec5e0be5f | ||
|
|
bcbb29d94e | ||
|
|
3e2f995ba8 | ||
|
|
56b3b9d94d | ||
|
|
9b2ac0d443 | ||
|
|
3ee78c29cb | ||
|
|
548e829f2f | ||
|
|
749c161aaa | ||
|
|
aee6b99a47 | ||
|
|
700262e07b | ||
|
|
c4cd9d3ee8 | ||
|
|
235d8f2264 | ||
|
|
6268f84b45 | ||
|
|
e2b49931c3 | ||
|
|
9cfab5a7ea | ||
|
|
66114e4748 | ||
|
|
4ea9868285 | ||
|
|
2c09eacbd4 | ||
|
|
2d5c01f25d | ||
|
|
9610695701 | ||
|
|
b7062a2b75 | ||
|
|
3100d43af0 | ||
|
|
53606cbde5 | ||
|
|
ca6d1d24f4 | ||
|
|
928a8c75e8 | ||
|
|
693df2d6fb | ||
|
|
bc3cea0b86 | ||
|
|
feba3cd05e | ||
|
|
e6b31b8c45 | ||
|
|
79efc87ed2 | ||
|
|
e17b88ca74 | ||
|
|
0020a5ea4a | ||
|
|
5778167b01 | ||
|
|
2b11414445 | ||
|
|
e7b51ef61d | ||
|
|
ca969ee79b | ||
|
|
9ff62f9e28 | ||
|
|
5c5cbf2933 | ||
|
|
91c5caee63 | ||
|
|
7aa439efbb | ||
|
|
7baf49aa7e | ||
|
|
d7476c1de8 | ||
|
|
d3e99a6de8 | ||
|
|
893f9d50c3 | ||
|
|
a565766fcb | ||
|
|
89e517e47b | ||
|
|
39d51bb68f | ||
|
|
5e3168039a | ||
|
|
f75062694f | ||
|
|
cb3c3f18ee | ||
|
|
2415b29d45 | ||
|
|
7fb162be77 | ||
|
|
bf93834fd3 | ||
|
|
63452d1bb2 | ||
|
|
5e26dbd870 | ||
|
|
fb782d67ed | ||
|
|
864c91cd18 | ||
|
|
038479564b | ||
|
|
08c0dfc4ef | ||
|
|
019291b707 | ||
|
|
1d84bbb548 | ||
|
|
5ceb5c848e | ||
|
|
b00e94bae9 | ||
|
|
46f6584577 | ||
|
|
e3c651fcb9 | ||
|
|
86a85ba177 | ||
|
|
36a4cb2451 | ||
|
|
ab726e9490 | ||
|
|
b9f75395b6 | ||
|
|
c0e4f83d83 | ||
|
|
08e94694b2 | ||
|
|
5112fd4fd3 | ||
|
|
2aafc6a82e | ||
|
|
1f200d53f8 | ||
|
|
77a5c75007 | ||
|
|
c44d4357a7 | ||
|
|
2bf70e88ba | ||
|
|
442bb998e4 | ||
|
|
6f60a73c62 | ||
|
|
106a5a77e7 | ||
|
|
2f3f13f34c | ||
|
|
bc4a9a07b6 | ||
|
|
5ca5ee55ee | ||
|
|
08636b550f | ||
|
|
b2aab26ded | ||
|
|
6d629d40e6 | ||
|
|
6e433ec9a4 | ||
|
|
802a0229fa | ||
|
|
41b4b86033 | ||
|
|
63dca2712b | ||
|
|
e06d104e10 | ||
|
|
4ab2ee875e | ||
|
|
ac8debbb4b | ||
|
|
8a7a2071b6 | ||
|
|
df471cf5a0 | ||
|
|
79665cc552 | ||
|
|
9c6932b124 | ||
|
|
4e30caf894 | ||
|
|
1bbff54c07 | ||
|
|
81ccf2a860 | ||
|
|
463007b218 | ||
|
|
ee53fffc67 | ||
|
|
63351ed6b7 | ||
|
|
87ba6f6ccc | ||
|
|
efeceb3a5b | ||
|
|
bb6fddad09 | ||
|
|
def9f6b70c | ||
|
|
95bbbb1daa | ||
|
|
0c759b9016 | ||
|
|
cb2d2dd363 | ||
|
|
88948c4b66 | ||
|
|
799626cfdc | ||
|
|
ab82a8748f | ||
|
|
6f78840aec | ||
|
|
b94dc3c733 | ||
|
|
de3c6bc45b | ||
|
|
c17ae13fcf | ||
|
|
e936ecbabd | ||
|
|
0f5105fee2 | ||
|
|
07571ecc32 | ||
|
|
3a4bc97abb | ||
|
|
412966d8d0 | ||
|
|
d8bf6048c1 | ||
|
|
f13f72ea16 | ||
|
|
a7818227bd | ||
|
|
a4c45ecdcd | ||
|
|
a21671f1b7 | ||
|
|
3fc0349550 | ||
|
|
fa177c41b7 | ||
|
|
f3675fb838 | ||
|
|
72fd9184f4 | ||
|
|
2196020705 | ||
|
|
81465a50d6 | ||
|
|
a0ccbfcac5 | ||
|
|
eaa3cf6137 | ||
|
|
32d4e2f281 | ||
|
|
6454f6843b | ||
|
|
22e67d39b0 | ||
|
|
7efbf6fd66 | ||
|
|
eaf9c97f52 | ||
|
|
5f7cee768d | ||
|
|
9c3b0aa289 | ||
|
|
b3bf52bd9b | ||
|
|
1f07688881 | ||
|
|
aafa30dbf9 | ||
|
|
e8f2e5efd1 | ||
|
|
c39e5bc02c | ||
|
|
6576b5ef79 | ||
|
|
bec4b2d627 | ||
|
|
a36798534d | ||
|
|
dbd945e828 | ||
|
|
b5655bf8ee | ||
|
|
3637cf4512 | ||
|
|
4693d2aae8 | ||
|
|
ece49bc4dd | ||
|
|
f60115f18d | ||
|
|
90fdbc872e | ||
|
|
7d5ad5d030 | ||
|
|
bd0e7909a1 | ||
|
|
cf3229a3c9 | ||
|
|
407f5fa53a | ||
|
|
b1edce46ff | ||
|
|
551ed091e7 | ||
|
|
7645fa4e90 | ||
|
|
396ce79d22 | ||
|
|
60ad79fd64 | ||
|
|
2c9a6aa456 | ||
|
|
3577dfda9f | ||
|
|
31549f2851 | ||
|
|
c8ea3f869e | ||
|
|
bc01c9f7c6 | ||
|
|
592df35acf | ||
|
|
66f98aadf9 | ||
|
|
17e420f01b | ||
|
|
44f6d57832 | ||
|
|
ae2cb10382 | ||
|
|
d68e08c3fd | ||
|
|
3921e8c287 | ||
|
|
caf79d1657 | ||
|
|
7477ba64d2 | ||
|
|
e006261fcf | ||
|
|
2ddd9c2fc6 | ||
|
|
5a7253f89b | ||
|
|
b68bc0f0b8 | ||
|
|
edc4984f58 | ||
|
|
c8a2ca87ba | ||
|
|
4dcc9c42c8 | ||
|
|
912fa4a85c | ||
|
|
a64a4608be | ||
|
|
b20773f2f5 | ||
|
|
f9a440c708 | ||
|
|
d002768a5f | ||
|
|
e0fcb9f225 | ||
|
|
a7ed16c72f | ||
|
|
1129d1c145 | ||
|
|
ee599c7ab8 | ||
|
|
1a5be5bf91 | ||
|
|
db0020d428 | ||
|
|
138ca4299b | ||
|
|
e9af1ebd80 | ||
|
|
4d26e404b0 | ||
|
|
b41813fa23 | ||
|
|
b18796fd45 | ||
|
|
d44898ed8c | ||
|
|
bb246cb4fd | ||
|
|
17ceb3e721 | ||
|
|
8435c579c9 | ||
|
|
3b4eb893b6 | ||
|
|
54704bcee6 | ||
|
|
8bbfd862e4 | ||
|
|
c909de0271 | ||
|
|
bd7f80a64e | ||
|
|
2e15b5b271 | ||
|
|
0a61820f15 | ||
|
|
4b1af45cd6 | ||
|
|
756e3fcf39 | ||
|
|
bb34ec1be3 | ||
|
|
f98b86ae4d | ||
|
|
eaa9a869f2 | ||
|
|
d1f3dbf89b | ||
|
|
58c6208716 | ||
|
|
83eb252e82 | ||
|
|
fd7da4d2fc | ||
|
|
4f76c98cec | ||
|
|
b7186e5da9 | ||
|
|
b3276fb329 | ||
|
|
5d2a31e65e | ||
|
|
8eaa01f1bc | ||
|
|
9bee6e12b4 | ||
|
|
50b2de8ce2 | ||
|
|
78b9e608e9 | ||
|
|
944c91d842 | ||
|
|
a936b9fec8 | ||
|
|
1efdc626e0 | ||
|
|
afca969668 | ||
|
|
f72178f142 | ||
|
|
2f4d744078 | ||
|
|
8563129dd5 | ||
|
|
ef1427bc95 | ||
|
|
20c07aaca1 | ||
|
|
4470b3fdec | ||
|
|
1e4705d20b | ||
|
|
0a5ae621b4 | ||
|
|
4e588f6d0e | ||
|
|
f60c5e29de | ||
|
|
1662cfd97d | ||
|
|
8fdc0ab84d | ||
|
|
7c96fd391f | ||
|
|
2acbde70cc | ||
|
|
cb7d100315 | ||
|
|
d96e1bb8a8 | ||
|
|
d27a67f567 | ||
|
|
47ae974304 | ||
|
|
6ce168faa2 | ||
|
|
f9a8e1d9a7 | ||
|
|
18543534fb | ||
|
|
5349bd8d36 | ||
|
|
9a140571c3 | ||
|
|
a4e0dc8bb7 | ||
|
|
14788e2a65 | ||
|
|
c8118245e4 | ||
|
|
fcff23e0c1 | ||
|
|
85f07ca15d | ||
|
|
ed5a83c4f2 | ||
|
|
98e3ac0603 | ||
|
|
df01ef4e14 | ||
|
|
24a3e6872c | ||
|
|
3d491b63f2 | ||
|
|
65dda61ff3 | ||
|
|
6d72a784fc | ||
|
|
388e4a71e1 | ||
|
|
1f77c6468c | ||
|
|
a242c283f3 | ||
|
|
a09ed79242 | ||
|
|
5116469856 | ||
|
|
81c5583b5c | ||
|
|
9d1233fe24 | ||
|
|
43c59f8d3e | ||
|
|
3bebb7ff07 | ||
|
|
05409dacde | ||
|
|
65929eec4b | ||
|
|
3d7a04be8e | ||
|
|
0f1b8ecb39 | ||
|
|
177d48e5a6 | ||
|
|
8b6b7dec06 | ||
|
|
7011ef7615 | ||
|
|
a8beabcd23 | ||
|
|
c114ee8acb | ||
|
|
aa121e326b | ||
|
|
ad0c5a01dd | ||
|
|
b66d60dd7d | ||
|
|
14993ad169 | ||
|
|
dbf7147f22 | ||
|
|
d3a8de29e3 | ||
|
|
98c42569ea | ||
|
|
1deebf0833 | ||
|
|
3bc6b156a2 | ||
|
|
0a52c50c47 | ||
|
|
04c29294d6 | ||
|
|
9c28933882 | ||
|
|
a5d8aed6fb | ||
|
|
4c52e36a0e | ||
|
|
7c2403f470 | ||
|
|
99dfa52915 | ||
|
|
3c5b61eca4 | ||
|
|
2185479c01 | ||
|
|
fcbd48bc49 | ||
|
|
db03f4f408 | ||
|
|
2f0e0d2a3b | ||
|
|
1aeb5639c7 | ||
|
|
d14da8af12 | ||
|
|
38e529ec14 | ||
|
|
b44f055013 | ||
|
|
18aee37057 | ||
|
|
83b5b9051d | ||
|
|
e4141283f1 | ||
|
|
209ad19164 | ||
|
|
52afb8d9d1 | ||
|
|
ec6c1b0578 | ||
|
|
7e97a9b2a4 | ||
|
|
8230dd07c4 | ||
|
|
16e7826981 | ||
|
|
17b9ae5089 | ||
|
|
85b38bc0e1 | ||
|
|
ab8a9c8d36 | ||
|
|
c8fb6d9805 | ||
|
|
35d0d7956d | ||
|
|
1e6cc7e8a2 | ||
|
|
6dff9d06c9 | ||
|
|
6de31ead9d | ||
|
|
6dc8cd7031 | ||
|
|
60209027fc | ||
|
|
7d186672ec | ||
|
|
6dd757e70f | ||
|
|
56207f7f48 | ||
|
|
bf5dc8a282 | ||
|
|
0ec56ef0d3 | ||
|
|
07b49d0147 | ||
|
|
39d8b8f8ec | ||
|
|
50564c5db8 | ||
|
|
e9aad35e70 | ||
|
|
47d82ac120 | ||
|
|
4cb7d22657 | ||
|
|
e7992e356a | ||
|
|
0fd8f9d29f | ||
|
|
bf033c31af | ||
|
|
aa788a17d9 | ||
|
|
96c598d454 | ||
|
|
7cddf329d0 | ||
|
|
f95660406f | ||
|
|
338caebfaf | ||
|
|
77ba946861 | ||
|
|
cb37282a14 | ||
|
|
3d40aefef5 | ||
|
|
e7b0489294 | ||
|
|
2690fcdacd | ||
|
|
0cc6d69c66 | ||
|
|
3312d440c1 | ||
|
|
dba5650f1a | ||
|
|
81cab7acbf | ||
|
|
42cb2eb9bb | ||
|
|
1d0476e1b8 | ||
|
|
4ea2455958 | ||
|
|
2338c57357 | ||
|
|
019e1579f6 | ||
|
|
df547b2022 | ||
|
|
ce3b8b6f50 | ||
|
|
4e24ee66f5 | ||
|
|
f82495c1cc | ||
|
|
c78c88cf92 | ||
|
|
03b82e81f0 | ||
|
|
90fe6a7416 | ||
|
|
30014d640b | ||
|
|
2be2b7f459 | ||
|
|
659ae36ca6 | ||
|
|
c92a4bcf36 | ||
|
|
931786eadb | ||
|
|
068e8121dc | ||
|
|
4e938d98fc | ||
|
|
da3e214ecd | ||
|
|
e88799265f | ||
|
|
dcb717db48 | ||
|
|
9e78c0f9e1 | ||
|
|
3b0596a93c | ||
|
|
0c8593a958 | ||
|
|
4e75524d6f | ||
|
|
e17b8dba4b | ||
|
|
11dc206fac | ||
|
|
f2ebd47ded | ||
|
|
036ad99ba6 | ||
|
|
904830579c | ||
|
|
a37d380440 | ||
|
|
1d6889879d | ||
|
|
b54cd7fbd9 | ||
|
|
113b0ac446 | ||
|
|
e30061e2a0 | ||
|
|
2b406aa7cc | ||
|
|
6cf5bbed95 | ||
|
|
1579671259 | ||
|
|
567d8416ec | ||
|
|
644e848011 | ||
|
|
dc4eccb043 | ||
|
|
be8ea6bab3 | ||
|
|
246d42469f | ||
|
|
8890aa6618 | ||
|
|
2b2620c954 | ||
|
|
e594957c0b | ||
|
|
a3b2f18a32 | ||
|
|
742b28a3c8 | ||
|
|
8340c5ba1d | ||
|
|
d44935bc29 | ||
|
|
efcbae5554 | ||
|
|
73c22bf815 | ||
|
|
e715d9e5b5 | ||
|
|
d1c1995018 | ||
|
|
7fda7abbe6 | ||
|
|
bea8bd4057 | ||
|
|
5d3996ae03 | ||
|
|
3d5bc3bb0c | ||
|
|
2ec8022001 | ||
|
|
2dbbf72a6c | ||
|
|
fbbe0e06cf | ||
|
|
455ef1138f | ||
|
|
2398ef7efe | ||
|
|
f68c594a7e | ||
|
|
8004e4eda8 | ||
|
|
1e682a3e9a | ||
|
|
6546d987e5 | ||
|
|
e4195f7b60 | ||
|
|
27cdb68240 | ||
|
|
a59ea11aac | ||
|
|
5fde8f9f4b | ||
|
|
3d05606ad6 | ||
|
|
f2da244a3c | ||
|
|
c6e26b1323 | ||
|
|
1550d289df | ||
|
|
81a6d05621 | ||
|
|
78c372b2f8 | ||
|
|
59ec071908 | ||
|
|
687e67faed | ||
|
|
46e98d4660 | ||
|
|
fa0cf9c9fd | ||
|
|
0e851eb687 | ||
|
|
3c651f8633 | ||
|
|
2b5f1c28e8 | ||
|
|
7fea881d17 | ||
|
|
61de366e05 | ||
|
|
ada64bba0c | ||
|
|
ab582b92c9 | ||
|
|
506a6a7779 | ||
|
|
f87dcda391 | ||
|
|
2d94ad60f3 | ||
|
|
333ed98e37 | ||
|
|
69b5f8a1cc | ||
|
|
cefad1c76f | ||
|
|
8fe96b140a | ||
|
|
3b25a1a001 | ||
|
|
f4d98f177c | ||
|
|
9f4f38bb0d | ||
|
|
b42ebfde2f | ||
|
|
1bd73d7872 | ||
|
|
6d83f77fcf | ||
|
|
17c1070fc1 | ||
|
|
f86a493ba6 | ||
|
|
32119b6afd | ||
|
|
e11661eadc | ||
|
|
0fc2201d80 | ||
|
|
bbe96f67f6 | ||
|
|
f4b2d9b1df | ||
|
|
42d894fd5a | ||
|
|
e8c750c18f | ||
|
|
89cb84d784 | ||
|
|
daa6e8360a | ||
|
|
24429255dc | ||
|
|
7c55ae98e5 | ||
|
|
81ed21962f | ||
|
|
d9752ed970 | ||
|
|
c6293580d9 | ||
|
|
5ddb76c137 | ||
|
|
20893622d4 | ||
|
|
35445dbf2e | ||
|
|
fbe6e3c1e6 | ||
|
|
1d35922155 | ||
|
|
ea31174cc4 | ||
|
|
f5ea5f673c | ||
|
|
e76490880a | ||
|
|
e12bb1320c | ||
|
|
827e16cf93 | ||
|
|
1b61205281 | ||
|
|
269f2b4850 | ||
|
|
d346e35901 | ||
|
|
2f87691309 | ||
|
|
8e6c778a82 | ||
|
|
f36732f7d4 | ||
|
|
e63d60ab3d | ||
|
|
460f3fcfd6 | ||
|
|
1f52ab9a3f | ||
|
|
397a9cdf1f | ||
|
|
4560ef7ef7 | ||
|
|
dc41dff9a0 | ||
|
|
3e6d9d1b11 | ||
|
|
1513f45662 | ||
|
|
3e8426da1a | ||
|
|
bb29373e16 | ||
|
|
da7ac548c5 | ||
|
|
b37441eaa8 | ||
|
|
a546b77c10 | ||
|
|
392cb956d2 | ||
|
|
76273a4d86 | ||
|
|
eb32b41bd4 | ||
|
|
767456ca9a | ||
|
|
c12354138a | ||
|
|
1fd93a1fb8 | ||
|
|
9c36937a9e | ||
|
|
3d382e67b6 | ||
|
|
ecdcab7371 | ||
|
|
a5609f3cad | ||
|
|
5c0bc397c1 | ||
|
|
21e9131c65 | ||
|
|
8159e33fef | ||
|
|
d2411e380b | ||
|
|
a2017a0a75 | ||
|
|
16fcc4d61e | ||
|
|
b6b4909f3c | ||
|
|
773abf3028 | ||
|
|
f8f7c4fbff | ||
|
|
c84abfb542 | ||
|
|
656f66f567 | ||
|
|
75386b4355 | ||
|
|
434b3020a0 | ||
|
|
64b0adee30 | ||
|
|
6351dc030c | ||
|
|
f261690d76 | ||
|
|
de37982a64 | ||
|
|
4266a38c01 | ||
|
|
8daec77bb4 | ||
|
|
4267c78f68 | ||
|
|
2f7843687f | ||
|
|
1648eb78f0 | ||
|
|
2b8143b4fb | ||
|
|
b2d6e7c37e | ||
|
|
22d41a144f | ||
|
|
f71d52c5ba | ||
|
|
1a86438f32 | ||
|
|
20aadf26a5 | ||
|
|
d6514bc946 | ||
|
|
3f417198d7 | ||
|
|
62da2245c1 | ||
|
|
627fa8f89e | ||
|
|
13e24501e5 | ||
|
|
0002ec1a8e | ||
|
|
62d7948b67 | ||
|
|
54ca25571e | ||
|
|
a64bf2e97f | ||
|
|
029a5587e6 | ||
|
|
918ce84b1b | ||
|
|
4622e9fe01 | ||
|
|
d707979b7d | ||
|
|
0c224e2a22 | ||
|
|
b4b4ec2f89 | ||
|
|
07b297f7ef | ||
|
|
e7804062f3 | ||
|
|
efed7969fc | ||
|
|
c8a1edea1a | ||
|
|
8a0d2c9b6a | ||
|
|
784b0e8e40 | ||
|
|
9ac3cc23f7 | ||
|
|
0e1b88fd25 | ||
|
|
7084b38a5a | ||
|
|
7cba7fad95 | ||
|
|
73d67763c9 | ||
|
|
29217453ab | ||
|
|
eca5bdea71 | ||
|
|
34fe3f53c3 | ||
|
|
78353460d1 | ||
|
|
210c76bad1 | ||
|
|
d7326b927d | ||
|
|
a4cf749d6d | ||
|
|
b7d256687a | ||
|
|
ccce2eb137 | ||
|
|
46a0c1f7bf | ||
|
|
a84d6f4121 | ||
|
|
10793ebdda | ||
|
|
9c6bec3761 | ||
|
|
2ab4173e85 | ||
|
|
195db973dc | ||
|
|
b15148f9f7 | ||
|
|
ae6f669629 | ||
|
|
a50c66557e | ||
|
|
9a09822f7a | ||
|
|
0a3174cba9 | ||
|
|
d5414ece84 | ||
|
|
fc4de43db3 | ||
|
|
e4138b894c | ||
|
|
5b74430751 | ||
|
|
22f6d2d1b9 | ||
|
|
318e164a01 | ||
|
|
969d40f5d8 | ||
|
|
c7f8b4899a | ||
|
|
a81086493f | ||
|
|
b773f22bd2 | ||
|
|
2b34b86746 | ||
|
|
78c4350ff7 | ||
|
|
ecd33b0f54 | ||
|
|
7753eb32af | ||
|
|
9d3fbf8d27 | ||
|
|
7f3d099148 | ||
|
|
518ed97ed4 | ||
|
|
6b46ac2fde | ||
|
|
6b9f0f07ec | ||
|
|
553c7e9caa | ||
|
|
bef0826f9d | ||
|
|
8fa4ec20a8 | ||
|
|
5ad7562f17 | ||
|
|
b74d95894b | ||
|
|
562cd42344 | ||
|
|
078bdfc28f | ||
|
|
3c5e84bc44 | ||
|
|
e61a6a00d8 | ||
|
|
f7b1441050 | ||
|
|
d0e6689dc4 | ||
|
|
9af8dde878 | ||
|
|
bfed745758 | ||
|
|
cc22abba50 | ||
|
|
ca84177e87 | ||
|
|
4508991ca2 | ||
|
|
0b1ddecd32 | ||
|
|
59025f7d4c | ||
|
|
8c75651650 | ||
|
|
44ea2aee40 | ||
|
|
7401647d6a | ||
|
|
fbd496e663 | ||
|
|
e22818f51f | ||
|
|
cd5537cc26 | ||
|
|
1933194d35 | ||
|
|
aef08dcd75 | ||
|
|
fd4c49d3d2 | ||
|
|
c1518cb509 | ||
|
|
43e424d44d | ||
|
|
4dfd313d10 | ||
|
|
9e68f4cd2c | ||
|
|
3fe373e20c | ||
|
|
1f2852a369 | ||
|
|
abe4d91622 | ||
|
|
0649b18952 | ||
|
|
aee81c1533 | ||
|
|
451b8ea1e5 | ||
|
|
578cf90f85 | ||
|
|
869fa35353 | ||
|
|
4d8cfb05ee | ||
|
|
b9d9463cc9 | ||
|
|
2c01caa7be | ||
|
|
65e925ec22 | ||
|
|
1144956c99 | ||
|
|
cf586dcd75 | ||
|
|
94008f5a53 | ||
|
|
6c5dd4a120 | ||
|
|
e87490aad8 | ||
|
|
cb55cec3f0 | ||
|
|
8bfec9ec7e | ||
|
|
bf410b2258 | ||
|
|
6eaab67081 | ||
|
|
d1ff4b0ede | ||
|
|
5bc4dc297d | ||
|
|
79f8a5e87c | ||
|
|
5c0eec9c83 | ||
|
|
42f6dab4ce | ||
|
|
7bcb6a320e | ||
|
|
771acbea35 | ||
|
|
8520bbcf85 | ||
|
|
253838bba9 | ||
|
|
0f2a26b744 | ||
|
|
53db712015 | ||
|
|
6f2fc808cd | ||
|
|
6b2fdf5400 | ||
|
|
b2fa393673 | ||
|
|
5292d13ae6 | ||
|
|
bfa3a2948d | ||
|
|
c11fd843d0 | ||
|
|
70a374004d | ||
|
|
2340a58e8f | ||
|
|
6d696d94d8 | ||
|
|
57360e5fea | ||
|
|
5c8d6ee901 | ||
|
|
7850eda22e | ||
|
|
38bda84426 | ||
|
|
954267c830 | ||
|
|
0dc5437ddd | ||
|
|
36dbc16fcf | ||
|
|
d20cc4c45e | ||
|
|
8b9e376609 | ||
|
|
bc9395029b | ||
|
|
6a2af9ffe4 | ||
|
|
9005656062 | ||
|
|
965dc73351 | ||
|
|
5dc31fac5b | ||
|
|
4254382e7f | ||
|
|
9c0a8266ab | ||
|
|
407c8204aa | ||
|
|
e218aaaed2 | ||
|
|
d07a21fdaa | ||
|
|
e8b69e133e | ||
|
|
b02d2a7f8d | ||
|
|
b9e3c22a1e | ||
|
|
80ab030c4a | ||
|
|
5483919dd3 | ||
|
|
b21daf47a7 | ||
|
|
917ec1091a | ||
|
|
30bb9f4fcc | ||
|
|
626da4c8bb | ||
|
|
813462744b | ||
|
|
970b648145 | ||
|
|
b9fce4527a | ||
|
|
597b157f83 | ||
|
|
4f82ae38cf | ||
|
|
74e4012fee | ||
|
|
74d18be94a | ||
|
|
56788af48b | ||
|
|
e618b3d0aa | ||
|
|
9f9cfbd581 | ||
|
|
c2e5f3ac2f | ||
|
|
9ccf4f6083 | ||
|
|
eb3fb9ec1c | ||
|
|
69f0f8d8bf | ||
|
|
af7a73ec42 | ||
|
|
c0b68e7da5 | ||
|
|
050c88ca55 | ||
|
|
0b218833af | ||
|
|
cc4f5b9ff5 | ||
|
|
1645034f6e | ||
|
|
4a1e5c974c | ||
|
|
b08083173a | ||
|
|
c24e7a6939 | ||
|
|
ce99671583 | ||
|
|
b5e9f98fd1 | ||
|
|
d36e5cc0c1 | ||
|
|
13ae2d27c8 | ||
|
|
ea5c76f012 | ||
|
|
acb9b50d14 | ||
|
|
968fc7ad30 | ||
|
|
bb6d7598a1 | ||
|
|
cd9481670a | ||
|
|
505e9e278b | ||
|
|
7e59888fb2 | ||
|
|
74f2d7f1ea | ||
|
|
f319be61d2 | ||
|
|
2cc4c8f974 | ||
|
|
a3aa74013a | ||
|
|
509b3affd1 | ||
|
|
ad9b2b54dd | ||
|
|
247eb00963 | ||
|
|
c0b59a49bf | ||
|
|
b525afe154 | ||
|
|
b449263854 | ||
|
|
12550c3d0a | ||
|
|
803a4ffb7f | ||
|
|
57bfea4d70 | ||
|
|
86f460866a | ||
|
|
8515157916 | ||
|
|
5bd18dee49 | ||
|
|
88ea5e7d6c | ||
|
|
3839335508 | ||
|
|
b8e94b52aa | ||
|
|
eeda450405 | ||
|
|
d051bd7df2 | ||
|
|
690a265450 | ||
|
|
8bec0a3caf | ||
|
|
a89463367e | ||
|
|
05dbcbd917 | ||
|
|
774bde3e20 | ||
|
|
90589e0d26 | ||
|
|
be199235f1 | ||
|
|
1b2d67b027 | ||
|
|
7bc56fc864 | ||
|
|
c706ddc809 | ||
|
|
1b6b2ea140 | ||
|
|
c1db037fc2 | ||
|
|
838e9ea773 | ||
|
|
10efe3513c | ||
|
|
6d301092b2 | ||
|
|
5acb5da8fa | ||
|
|
3ad343b274 | ||
|
|
c5fd749b21 | ||
|
|
1f8e0f16c7 | ||
|
|
92babe7fbc | ||
|
|
fb684837f8 | ||
|
|
669413b184 | ||
|
|
a945a01767 | ||
|
|
b4664eafa5 | ||
|
|
34b06b83aa | ||
|
|
da14681077 | ||
|
|
53e91ad683 | ||
|
|
06434bef99 | ||
|
|
16fab0ced0 | ||
|
|
bc3e531447 | ||
|
|
af038e3306 | ||
|
|
1a06b83d9d | ||
|
|
bcc3cfd143 | ||
|
|
b73123c137 | ||
|
|
8c47f94172 | ||
|
|
b03e17ce22 | ||
|
|
c0ed352293 | ||
|
|
e4eb8794ff | ||
|
|
830ba03448 | ||
|
|
45b2f267de | ||
|
|
891c0d6657 | ||
|
|
8583352033 | ||
|
|
76ea81465e | ||
|
|
9f4b558936 | ||
|
|
773d69c569 | ||
|
|
f03997c927 | ||
|
|
2fc9d405f8 | ||
|
|
4278895995 | ||
|
|
af41c263ee | ||
|
|
0466d6ce83 | ||
|
|
3a4e1d6b11 | ||
|
|
818f697b6b | ||
|
|
83e0d926ac | ||
|
|
782f22325a | ||
|
|
e896a7c960 | ||
|
|
1bb0035b34 | ||
|
|
5cdae539a6 | ||
|
|
bf131b7a0e | ||
|
|
cb08de46b0 | ||
|
|
81f1c3d6b2 | ||
|
|
6b7da3b649 | ||
|
|
05888ae2c3 | ||
|
|
bc97156569 | ||
|
|
e9103eb796 | ||
|
|
62b8b30e3a | ||
|
|
81897253c5 | ||
|
|
a242c9fd12 | ||
|
|
b299220dd0 | ||
|
|
3883881afc | ||
|
|
9061853666 | ||
|
|
20c8da511f | ||
|
|
d7f46e039e | ||
|
|
0532524a50 | ||
|
|
0f0bbff14c | ||
|
|
ce7fbe1471 | ||
|
|
b53d96b9df | ||
|
|
a184f63c00 | ||
|
|
75fb028f1a | ||
|
|
190c0d500a | ||
|
|
663fc784c1 | ||
|
|
38b985defc | ||
|
|
9d5cdea95c | ||
|
|
004c2a4646 | ||
|
|
05d88731e7 | ||
|
|
5b0d244c8a | ||
|
|
60cf844f63 | ||
|
|
02eba06a6d | ||
|
|
c9e148f4d0 | ||
|
|
d7f3e79ce8 | ||
|
|
5549a80e69 | ||
|
|
82f7202ec3 | ||
|
|
77c1db6b25 | ||
|
|
adb7165807 | ||
|
|
d1cfa84f06 | ||
|
|
f9aa080fc8 | ||
|
|
6d47e327cb | ||
|
|
a2f0d32c5f | ||
|
|
4e019a7e84 | ||
|
|
d3c7c6bfe4 | ||
|
|
ddc4cfb197 | ||
|
|
43696d91fc | ||
|
|
69ec7ea23b | ||
|
|
5b0a58372b | ||
|
|
38e2650cde | ||
|
|
307ba20f0a | ||
|
|
1659a731ad | ||
|
|
f28fcde90c | ||
|
|
21cda21b2e | ||
|
|
576d34e9bb | ||
|
|
d6b992ef50 | ||
|
|
f4c8931d7c | ||
|
|
8a17ff2ca3 | ||
|
|
a5681a75bb | ||
|
|
e6b1299293 | ||
|
|
01de38ce97 | ||
|
|
35940f28d2 | ||
|
|
1c1b40ff24 | ||
|
|
31cc9849e4 | ||
|
|
61fb2a0bbe | ||
|
|
0c5af4c6f0 | ||
|
|
bde04d8a4a | ||
|
|
9bbe2ba80d | ||
|
|
1a5e9d287d | ||
|
|
116f04d42a | ||
|
|
92e15f4252 | ||
|
|
192410420f | ||
|
|
5f9db6489a | ||
|
|
dcc97f4f26 | ||
|
|
513398c984 | ||
|
|
10955e3f56 | ||
|
|
261f6daf69 | ||
|
|
b352a194ea | ||
|
|
1c9095a9f4 | ||
|
|
3b69b83b3d | ||
|
|
882e92bbcf | ||
|
|
a5cfaabd13 | ||
|
|
8323d867fb | ||
|
|
d88b99a7f8 | ||
|
|
9bea92f35e | ||
|
|
1fe3aad25f | ||
|
|
10063eaaeb | ||
|
|
7b7c76c8d1 | ||
|
|
ebe0e1ade7 | ||
|
|
b1ac2ebb49 | ||
|
|
348e72ac37 | ||
|
|
fb9df5ff0e | ||
|
|
ad9f31c499 | ||
|
|
4ba0f902ce | ||
|
|
6606a7aef1 | ||
|
|
9b878148cf | ||
|
|
a1de3a1536 | ||
|
|
187e007653 | ||
|
|
6fb4f79f80 | ||
|
|
785eb8ab39 | ||
|
|
f096bf1949 | ||
|
|
a406bfe19f | ||
|
|
664610f283 | ||
|
|
cdc204710f | ||
|
|
b762aafdb2 | ||
|
|
4e1b6a00b0 | ||
|
|
1a7a7dd335 | ||
|
|
d16b967b7b | ||
|
|
9ec45a1730 | ||
|
|
41448ef7eb | ||
|
|
ebbf785701 | ||
|
|
82f9351414 | ||
|
|
b19f05af19 | ||
|
|
8336fe3f66 | ||
|
|
af1fc53e10 | ||
|
|
8607c95c6e | ||
|
|
3e76a51c4b | ||
|
|
8aabf3eb6b | ||
|
|
5c339648ba | ||
|
|
cd453664eb | ||
|
|
a7cb7125b2 | ||
|
|
e8366602f3 | ||
|
|
c25a23ae78 | ||
|
|
6fbafcfc36 | ||
|
|
05940b916f | ||
|
|
dbfcf35084 | ||
|
|
2dfe48d4b2 | ||
|
|
90c2e21788 | ||
|
|
9eb5cd69c5 | ||
|
|
72fee60900 | ||
|
|
d4fb9fc79a | ||
|
|
a4b3be8323 | ||
|
|
30a39f57ed | ||
|
|
3660aa3fc8 | ||
|
|
f970ac02f2 | ||
|
|
4d114bc2e8 | ||
|
|
ea0d53d0e6 | ||
|
|
8a2c0853c2 | ||
|
|
28c77b2890 | ||
|
|
4c3b4017eb | ||
|
|
a4240a7d89 | ||
|
|
c3e4f343a4 | ||
|
|
168077ad1b | ||
|
|
7679f019f9 | ||
|
|
f80ed523bb | ||
|
|
e58132b6b3 | ||
|
|
f98810d87f | ||
|
|
e3e5bf1651 | ||
|
|
99af4a6dc7 | ||
|
|
14510f9130 | ||
|
|
f9ae0d266e | ||
|
|
2ecc9ac10f | ||
|
|
2a0b8957fc | ||
|
|
4dc289f2bc | ||
|
|
107856f57d | ||
|
|
5eb4d27a83 | ||
|
|
8a4302a8d9 | ||
|
|
db5b37b221 | ||
|
|
34a191446f | ||
|
|
2a3e9c143f | ||
|
|
85b38f8119 | ||
|
|
9f70e7dce2 | ||
|
|
d73222875a | ||
|
|
a90098666d | ||
|
|
6f06c75fdd | ||
|
|
6977f1adaa | ||
|
|
67beeca698 | ||
|
|
acc6684e2d | ||
|
|
7eb4818739 | ||
|
|
a1caf22474 | ||
|
|
588887b9d8 | ||
|
|
2c480cc45b | ||
|
|
068eff9c94 | ||
|
|
ff627dd7dc | ||
|
|
bcf6a24b9f | ||
|
|
714907d498 | ||
|
|
14660ed0ae | ||
|
|
3632e53f12 | ||
|
|
f0f6455969 | ||
|
|
24546658b8 | ||
|
|
2fc728cce9 | ||
|
|
0ec1de2e8e | ||
|
|
8ec6a350fd | ||
|
|
2b824537eb | ||
|
|
c9caebca28 | ||
|
|
5fdae984db | ||
|
|
f6500d6c08 | ||
|
|
b3b04a5346 | ||
|
|
7aee43c2ff | ||
|
|
376ddbb5ff | ||
|
|
dc00c53731 | ||
|
|
eadfa783f7 | ||
|
|
5e0e644b5e | ||
|
|
e4a75a75d2 | ||
|
|
1d16a3cbfd | ||
|
|
8b27bb6fb4 | ||
|
|
3cf1db1e6f | ||
|
|
c2d0b2fb86 | ||
|
|
99dde4d4e1 | ||
|
|
0845baa72e | ||
|
|
1567fd4feb | ||
|
|
edf1bac058 | ||
|
|
f02a193bda | ||
|
|
a9dff223ed | ||
|
|
2bfb414495 | ||
|
|
d55b82a6ea | ||
|
|
c58ffc6cac | ||
|
|
6dfd2d49bb | ||
|
|
dc0a866277 | ||
|
|
32f07d81d4 | ||
|
|
44460362c5 | ||
|
|
1c5537bb55 | ||
|
|
2636ac0b31 | ||
|
|
e5cfe759b1 | ||
|
|
a6f7df72b5 | ||
|
|
5b4788825d | ||
|
|
c0355cb2b2 | ||
|
|
2eac1b3721 | ||
|
|
78aa4ce6c5 | ||
|
|
dd7bd118af | ||
|
|
225c6efe3e | ||
|
|
fa3a2b729b | ||
|
|
2a3e3dde0a | ||
|
|
878ce83448 | ||
|
|
db5d1850a9 | ||
|
|
9b6b4e4199 | ||
|
|
1b7a06b909 | ||
|
|
0925c6706e | ||
|
|
f5829310b6 | ||
|
|
43ab056313 | ||
|
|
57ef6f1b7e | ||
|
|
0525a0b3cd | ||
|
|
7a4cbec022 | ||
|
|
705f791e12 | ||
|
|
69f836575c | ||
|
|
f82b8ad49f | ||
|
|
2e388b32f3 | ||
|
|
de1e4abf0f | ||
|
|
c37c3d32aa | ||
|
|
01e252085c | ||
|
|
45b8764670 | ||
|
|
a21c6dda36 | ||
|
|
82be8d7fbd | ||
|
|
97ae13a27f | ||
|
|
edd2d6a630 | ||
|
|
8475e0a99c | ||
|
|
02e3d1823f | ||
|
|
6b6f522f1c | ||
|
|
80d695239c | ||
|
|
d3684df6e3 | ||
|
|
d2bf82d232 | ||
|
|
e6f4b337ce | ||
|
|
f4e58d9bee | ||
|
|
af9e77a5bb | ||
|
|
1d9af232b9 | ||
|
|
60b6c85864 | ||
|
|
709c301dda | ||
|
|
37dc6a1217 | ||
|
|
ba82989e97 | ||
|
|
731273c296 | ||
|
|
2a11d9e7ed | ||
|
|
67dea8fd5e | ||
|
|
8aff7316e5 | ||
|
|
6331300806 | ||
|
|
64d04e1d78 | ||
|
|
6258893aa8 | ||
|
|
3e27868760 | ||
|
|
cbf8301a89 | ||
|
|
1601a12e20 | ||
|
|
4420511e02 | ||
|
|
bbfe3c7366 | ||
|
|
64d31c8324 | ||
|
|
e93860101c | ||
|
|
04444aa03a | ||
|
|
6eba798cd8 | ||
|
|
c5555c2909 | ||
|
|
56164b9446 | ||
|
|
9f40bb4b1e | ||
|
|
d67323d35f | ||
|
|
3f26095281 | ||
|
|
d63871957d | ||
|
|
553c692b9a | ||
|
|
4a71ab5f5d | ||
|
|
3fbdff674e | ||
|
|
e6aad6eabc | ||
|
|
3b1d307fad | ||
|
|
66fc4c2294 | ||
|
|
a21e4b836d | ||
|
|
3159181c5c | ||
|
|
770cac9b87 | ||
|
|
ec4afe0e11 | ||
|
|
163d51770d | ||
|
|
364a5c50f0 | ||
|
|
581f09eb9b | ||
|
|
d75bc354cf | ||
|
|
5e3f00f11d | ||
|
|
ffe83d24ce | ||
|
|
ae874c44f5 | ||
|
|
e80269b61c | ||
|
|
2c4d5fb0f8 | ||
|
|
1fe222852a | ||
|
|
60ae87a3cb | ||
|
|
7f092ad31d | ||
|
|
fd8090e13d | ||
|
|
4aba2aab4c | ||
|
|
8c03b0a6cd | ||
|
|
e87fda3f3a | ||
|
|
4cabd6c2f1 | ||
|
|
f38361c7c7 | ||
|
|
ca3d10e7a2 | ||
|
|
e4cb9071d0 | ||
|
|
2b2777b3da | ||
|
|
83fd96a876 | ||
|
|
c1b1eaf847 | ||
|
|
f63cc22f44 | ||
|
|
3da1632e4b | ||
|
|
0bf4624839 | ||
|
|
0d38dfb385 | ||
|
|
70fff1167b | ||
|
|
196c300be5 | ||
|
|
a894f9a70b | ||
|
|
9e3c258c90 | ||
|
|
0893082326 | ||
|
|
18d12c1faf | ||
|
|
46d9dd7bea | ||
|
|
4fa562a283 | ||
|
|
1f02c8320b | ||
|
|
774aff1d17 | ||
|
|
74c142a1ac | ||
|
|
06d604796f | ||
|
|
f1db095fdc | ||
|
|
bac5bf46b5 | ||
|
|
a0f085e415 | ||
|
|
c69f13dda6 | ||
|
|
f6362b3aa5 | ||
|
|
4433325abb | ||
|
|
f2e5197568 | ||
|
|
bffcd3adb7 | ||
|
|
20e22c43f0 | ||
|
|
99f0194b80 | ||
|
|
a5422fd789 | ||
|
|
fc5203c3ba | ||
|
|
5deefc5f35 | ||
|
|
40531f4d4e | ||
|
|
78358057e6 | ||
|
|
a6b7b5ca61 | ||
|
|
0b71b4fc7d | ||
|
|
4b6c177af6 | ||
|
|
48c665b641 | ||
|
|
506f7cf410 | ||
|
|
a5cec0370e | ||
|
|
2e92adff81 | ||
|
|
1e3a3b909b | ||
|
|
1dbc41619f | ||
|
|
e4237abdbf | ||
|
|
b2e1ff0d5a | ||
|
|
790c34cd8a | ||
|
|
1e175429c8 | ||
|
|
575cdf8f5b | ||
|
|
02948e09c5 | ||
|
|
20b6dbe5ac | ||
|
|
328b6fcaa0 | ||
|
|
42355f3bec | ||
|
|
37a84f8cea | ||
|
|
f1ad8a734a | ||
|
|
870cdb19e3 | ||
|
|
56e5ce0bba | ||
|
|
576015fffe | ||
|
|
5f3d34b027 | ||
|
|
01bb105808 | ||
|
|
d9125a5204 | ||
|
|
93a26dca36 | ||
|
|
5c539b99d8 | ||
|
|
9e622bbfbd | ||
|
|
283a25162e | ||
|
|
0c44eec377 | ||
|
|
0cbdf88b21 | ||
|
|
2f06f0b7d2 | ||
|
|
cee9d21b7c | ||
|
|
c03afcce33 | ||
|
|
5e9ee92011 | ||
|
|
ad212d694f | ||
|
|
9530b2802b | ||
|
|
b4e79d57ea | ||
|
|
7efd36ebe8 | ||
|
|
9f90802fb2 | ||
|
|
18f4cd4587 | ||
|
|
fc01905134 | ||
|
|
91523553fb | ||
|
|
ca449b9952 | ||
|
|
3e0eade2f3 | ||
|
|
68cca25635 | ||
|
|
050fb4330e | ||
|
|
14d43bda1c | ||
|
|
34a8158284 | ||
|
|
8871842863 | ||
|
|
9392a26f81 | ||
|
|
8eac39bd50 | ||
|
|
2c8407581c | ||
|
|
b89349d0ee | ||
|
|
f554a6f649 |
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
* text=auto
|
||||
*.php text eol=crlf
|
||||
*.js text eol=crlf
|
||||
*.json text eol=crlf
|
||||
*.md text eol=crlf
|
||||
*.less text eol=crlf
|
||||
*.css text eol=crlf
|
||||
*.tpl text eol=crlf
|
||||
*.html text eol=crlf
|
||||
|
||||
*.png binary
|
||||
17
.github/CONTRIBUTING.md
vendored
Normal file
17
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
## Pull Requests
|
||||
|
||||
Before we can merge your pull request you need to accept our CLA [here](https://github.com/espocrm/cla). It's very simple to do.
|
||||
|
||||
See [Code Style Guidelines](https://github.com/espocrm/espocrm/wiki/Code-Style-Guidelines).
|
||||
|
||||
Branches:
|
||||
|
||||
* *hotfix/** – upcoming maintenance release; fixes should be pushed to this branch;
|
||||
* *master* – develop branch; new features should be pushed to this branch;
|
||||
* *stable* – last stable release.
|
||||
|
||||
## Issues
|
||||
|
||||
When reporting a possible bug please provide detail steps so that we will be able to reproduce the issue. Please try not to use phrases like "very big bug", "huge issue", etc. No need to use exclamation marks as well.
|
||||
|
||||
Note that we don't provide developer help or any kind of support on Github. Please use our [forum](https://forum.espocrm.com) for this.
|
||||
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
...
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**EspoCRM version**
|
||||
Specify the EspoCRM version (or versions) on which the bug occurs.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
contact_links:
|
||||
- name: EspoCRM forum
|
||||
url: https://forum.espocrm.com/
|
||||
about: Please use our forum to ask questions not related to product development
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for EspoCRM
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
9
.github/SECURITY.md
vendored
Normal file
9
.github/SECURITY.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
If you believe you have discovered a vulnerability in EspoCRM please contacts us via [this](https://www.espocrm.com/contacts/) or [this](https://www.espocrm.com/support/) forms.
|
||||
|
||||
## Supported versions
|
||||
|
||||
For severe vulnerabilities we provide fixes for 2 minor versions (the second number in the version string) back from the current stable version. Separate patches or manual fix guidelines will be provided for more old versions.
|
||||
14
.gitignore
vendored
14
.gitignore
vendored
@@ -4,16 +4,22 @@
|
||||
/data/preferences/*
|
||||
/data/.backup/*
|
||||
/data/config.php
|
||||
/data/config-internal.php
|
||||
/data/tmp/*
|
||||
/build
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
/npm-debug.log
|
||||
/test.php
|
||||
/main.html
|
||||
|
||||
/tests/unit/testData/cache/*
|
||||
!/tests/unit/testData/cache/.data
|
||||
/tests/integration/config.php
|
||||
composer.phar
|
||||
vendor/
|
||||
.phpunit.result.cache
|
||||
/composer.phar
|
||||
/vendor/
|
||||
/custom/Espo/Custom/*
|
||||
/install/config.php
|
||||
/custom/Espo/Modules/*
|
||||
!/custom/Espo/Custom/.htaccess
|
||||
!/custom/Espo/Modules/.htaccess
|
||||
/install/config.php
|
||||
|
||||
50
.htaccess
50
.htaccess
@@ -1,24 +1,44 @@
|
||||
<ifModule mod_headers.c>
|
||||
Header always set Access-Control-Allow-Methods "POST, GET, PUT, PATCH, DELETE"
|
||||
Header always set Access-Control-Allow-Methods "POST, GET, PUT, PATCH, DELETE"
|
||||
</ifModule>
|
||||
|
||||
DirectoryIndex index.php index.html
|
||||
DirectoryIndex index.php
|
||||
|
||||
Options -Indexes
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteEngine On
|
||||
|
||||
# PROTECTED DIRECTORIES
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^/?(api|client)/ - [F]
|
||||
# Forbid access. Not actual as redirect to `public` is applied.
|
||||
# An extra security measure if redirect not fired.
|
||||
RewriteRule ^/?data/ - [F]
|
||||
RewriteRule ^/?application/ - [F]
|
||||
RewriteRule ^/?custom/ - [F]
|
||||
RewriteRule ^/?vendor/ - [F]
|
||||
RewriteRule /?web\.config - [F]
|
||||
|
||||
RewriteRule ^/?data/ - [F]
|
||||
RewriteRule ^/?application/ - [F]
|
||||
RewriteRule ^/?custom/ - [F]
|
||||
RewriteRule ^/?vendor/ - [F]
|
||||
RewriteRule ^/?client/?$ - [F]
|
||||
#END PROTECTED DIRECTORIES
|
||||
# Forbid `public` dir.
|
||||
RewriteCond %{ENV:REDIRECT_STATUS} !=200
|
||||
RewriteRule ^/?public/? - [F,L]
|
||||
|
||||
RewriteRule .* - [E=HTTP_ESPO_CGI_AUTH:%{HTTP:Authorization}]
|
||||
# Skip redirect for `client` dir.
|
||||
RewriteRule ^client/ - [L]
|
||||
|
||||
RewriteRule reset/?$ reset.html [QSA,L]
|
||||
</IfModule>
|
||||
# {#dev}
|
||||
# Skip redirect for `node_modules` dir. Actual only for dev environment.
|
||||
RewriteRule ^node_modules/ - [L]
|
||||
# {/dev}
|
||||
|
||||
# Store base path.
|
||||
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
|
||||
RewriteRule ^(.*)$ - [E=BASE:%1]
|
||||
|
||||
# Add trailing slash.
|
||||
RewriteCond %{DOCUMENT_ROOT}/%{ENV:BASE}/public/$1 -d
|
||||
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=301,NE]
|
||||
|
||||
# Rewrite to `public` dir.
|
||||
RewriteRule ^((?!public/).*)$ %{ENV:BASE}/public/$1 [L,NC]
|
||||
|
||||
RewriteRule .* - [E=HTTP_ESPO_CGI_AUTH:%{HTTP:Authorization}]
|
||||
</IfModule>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
## Pull Requests
|
||||
|
||||
Before we can merge your pull request you need to accept our CLA [here](https://github.com/espocrm/cla). It's very simple to do.
|
||||
|
||||
[Code Style Guidelines](https://github.com/espocrm/espocrm/wiki/Code-Style-Guidelines).
|
||||
|
||||
## Issues
|
||||
|
||||
We don't provide developer help or any kind of support on github. Please use our [forum](https://forum.espocrm.com) for this.
|
||||
407
Gruntfile.js
407
Gruntfile.js
@@ -2,7 +2,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -19,111 +19,67 @@
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* * `grunt` - full build
|
||||
* * `grunt dev` - build only items needed for development
|
||||
* * `grunt offline` - skips *composer install*
|
||||
* * `grant release` - full build plus upgrade packages`
|
||||
* * `grant tests` - build and run tests
|
||||
*/
|
||||
/**
|
||||
* * `grunt` - full build
|
||||
* * `grunt dev` - build only items needed for development (takes less time)
|
||||
* * `grunt offline` - build but skip *composer install*
|
||||
* * `grant release` - full build plus upgrade packages`
|
||||
* * `grant test` - build for tests running
|
||||
* * `grant run-tests` - build and run unit and integration tests
|
||||
*/
|
||||
|
||||
module.exports = function (grunt) {
|
||||
const fs = require('fs');
|
||||
const cp = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
var jsFilesToMinify = [
|
||||
'client/lib/jquery-2.1.4.min.js',
|
||||
'client/lib/underscore-min.js',
|
||||
'client/lib/es6-promise.min.js',
|
||||
'client/lib/backbone-min.js',
|
||||
'client/lib/handlebars.js',
|
||||
'client/lib/base64.js',
|
||||
'client/lib/jquery-ui.min.js',
|
||||
'client/lib/jquery.ui.touch-punch.min.js',
|
||||
'client/lib/moment.min.js',
|
||||
'client/lib/moment-timezone.min.js',
|
||||
'client/lib/moment-timezone-data.js',
|
||||
'client/lib/jquery.timepicker.min.js',
|
||||
'client/lib/jquery.autocomplete.js',
|
||||
'client/lib/bootstrap.min.js',
|
||||
'client/lib/bootstrap-datepicker.js',
|
||||
'client/lib/bull.js',
|
||||
'client/lib/marked.min.js',
|
||||
'client/lib/autobahn.js',
|
||||
module.exports = grunt => {
|
||||
|
||||
'client/src/namespace.js',
|
||||
'client/src/exceptions.js',
|
||||
'client/src/loader.js',
|
||||
'client/src/utils.js',
|
||||
const pkg = grunt.file.readJSON('package.json');
|
||||
const bundleConfig = require('./frontend/bundle-config.json');
|
||||
|
||||
'client/src/acl.js',
|
||||
'client/src/model.js',
|
||||
'client/src/model-offline.js',
|
||||
'client/src/ajax.js',
|
||||
'client/src/controller.js',
|
||||
let jsFilesToBundle = getBundleLibList().concat(bundleConfig.jsFiles);
|
||||
let jsFilesToCopy = getCopyLibDataList();
|
||||
|
||||
'client/src/ui.js',
|
||||
'client/src/acl-manager.js',
|
||||
'client/src/cache.js',
|
||||
'client/src/storage.js',
|
||||
'client/src/models/settings.js',
|
||||
'client/src/language.js',
|
||||
'client/src/metadata.js',
|
||||
'client/src/field-manager.js',
|
||||
'client/src/models/user.js',
|
||||
'client/src/models/preferences.js',
|
||||
'client/src/model-factory.js',
|
||||
'client/src/collection-factory.js',
|
||||
'client/src/pre-loader.js',
|
||||
'client/src/controllers/base.js',
|
||||
'client/src/router.js',
|
||||
'client/src/date-time.js',
|
||||
'client/src/layout-manager.js',
|
||||
'client/src/theme-manager.js',
|
||||
'client/src/session-storage.js',
|
||||
'client/src/view-helper.js',
|
||||
'client/src/page-title.js',
|
||||
let libFilesToMinify = jsFilesToCopy
|
||||
.filter(item => item.minify)
|
||||
.reduce((map, item) => (
|
||||
map[item.dest] = item.dest,
|
||||
map
|
||||
), {});
|
||||
|
||||
'client/src/app.js'
|
||||
];
|
||||
let currentPath = path.dirname(fs.realpathSync(__filename));
|
||||
|
||||
function camelCaseToHyphen (string){
|
||||
if (string == null) {
|
||||
return string;
|
||||
}
|
||||
return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
}
|
||||
let themeList = [];
|
||||
|
||||
var fs = require('fs');
|
||||
var cp = require('child_process');
|
||||
var path = require('path');
|
||||
|
||||
var currentPath = path.dirname(fs.realpathSync(__filename));
|
||||
|
||||
var themeList = [];
|
||||
fs.readdirSync('application/Espo/Resources/metadata/themes').forEach(function (file) {
|
||||
fs.readdirSync('application/Espo/Resources/metadata/themes').forEach(file => {
|
||||
themeList.push(file.substr(0, file.length - 5));
|
||||
});
|
||||
|
||||
var cssminFilesData = {};
|
||||
var lessData = {};
|
||||
themeList.forEach(function (theme) {
|
||||
var name = camelCaseToHyphen(theme);
|
||||
var files = {};
|
||||
let cssminFilesData = {};
|
||||
|
||||
let lessData = {};
|
||||
|
||||
themeList.forEach(theme => {
|
||||
let name = camelCaseToHyphen(theme);
|
||||
|
||||
let files = {};
|
||||
|
||||
files['client/css/espo/'+name+'.css'] = 'frontend/less/'+name+'/main.less';
|
||||
files['client/css/espo/'+name+'-iframe.css'] = 'frontend/less/'+name+'/iframe/main.less';
|
||||
|
||||
cssminFilesData['client/css/espo/'+name+'.css'] = 'client/css/espo/'+name+'.css';
|
||||
cssminFilesData['client/css/espo/'+name+'-iframe.css'] = 'client/css/espo/'+name+'-iframe.css';
|
||||
var o = {
|
||||
|
||||
let o = {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
},
|
||||
files: files
|
||||
files: files,
|
||||
};
|
||||
|
||||
lessData[theme] = o;
|
||||
});
|
||||
|
||||
var pkg = grunt.file.readJSON('package.json');
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: pkg,
|
||||
|
||||
@@ -133,11 +89,11 @@ module.exports = function (grunt) {
|
||||
mode: 0755,
|
||||
create: [
|
||||
'build/tmp',
|
||||
]
|
||||
},
|
||||
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
clean: {
|
||||
start: ['build/EspoCRM-*'],
|
||||
final: ['build/tmp'],
|
||||
@@ -145,27 +101,48 @@ module.exports = function (grunt) {
|
||||
beforeFinal: {
|
||||
src: [
|
||||
'build/tmp/custom/Espo/Custom/*',
|
||||
'build/tmp/custom/Espo/Modules/*',
|
||||
'!build/tmp/custom/Espo/Custom/.htaccess',
|
||||
'!build/tmp/custom/Espo/Modules/.htaccess',
|
||||
'build/tmp/install/config.php',
|
||||
'build/tmp/vendor/*/*/.git',
|
||||
'build/tmp/custom/Espo/Custom/*',
|
||||
'build/tmp/client/custom/*',
|
||||
'!build/tmp/client/custom/modules',
|
||||
'build/tmp/client/custom/modules/*',
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
less: lessData,
|
||||
|
||||
cssmin: {
|
||||
themes: {
|
||||
files: cssminFilesData
|
||||
}
|
||||
files: cssminFilesData,
|
||||
},
|
||||
},
|
||||
|
||||
uglify: {
|
||||
options: {
|
||||
mangle: false,
|
||||
mangle: true,
|
||||
sourceMap: true,
|
||||
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
|
||||
output: {
|
||||
comments: /^!/,
|
||||
},
|
||||
},
|
||||
bundle: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
|
||||
},
|
||||
files: {
|
||||
'build/tmp/client/espo.min.js': jsFilesToBundle,
|
||||
},
|
||||
},
|
||||
lib: {
|
||||
files: libFilesToMinify,
|
||||
},
|
||||
'build/tmp/client/espo.min.js': jsFilesToMinify.map(function (item) {
|
||||
return '' + item;
|
||||
})
|
||||
},
|
||||
|
||||
copy: {
|
||||
options: {
|
||||
mode: true,
|
||||
@@ -182,11 +159,14 @@ module.exports = function (grunt) {
|
||||
'img/**',
|
||||
'css/**',
|
||||
'sounds/**',
|
||||
'custom/**'
|
||||
'custom/**',
|
||||
],
|
||||
dest: 'build/tmp/client',
|
||||
},
|
||||
frontendLib: {
|
||||
files: jsFilesToCopy,
|
||||
},
|
||||
frontendCommitedLib: {
|
||||
expand: true,
|
||||
dot: true,
|
||||
cwd: 'client/lib',
|
||||
@@ -197,24 +177,24 @@ module.exports = function (grunt) {
|
||||
expand: true,
|
||||
dot: true,
|
||||
src: [
|
||||
'api/**',
|
||||
'application/**',
|
||||
'custom/**',
|
||||
'data/.data',
|
||||
'install/**',
|
||||
'portal/**',
|
||||
'vendor/**',
|
||||
'html/**',
|
||||
'public/**',
|
||||
'install/**',
|
||||
'bin/**',
|
||||
'bootstrap.php',
|
||||
'cron.php',
|
||||
'daemon.php',
|
||||
'rebuild.php',
|
||||
'clear_cache.php',
|
||||
'preload.php',
|
||||
'upgrade.php',
|
||||
'extension.php',
|
||||
'websocket.php',
|
||||
'command.php',
|
||||
'oauth-callback.php',
|
||||
'index.php',
|
||||
'LICENSE.txt',
|
||||
'.htaccess',
|
||||
@@ -230,6 +210,7 @@ module.exports = function (grunt) {
|
||||
dest: 'build/EspoCRM-<%= pkg.version %>/',
|
||||
},
|
||||
},
|
||||
|
||||
chmod: {
|
||||
php: {
|
||||
options: {
|
||||
@@ -245,20 +226,20 @@ module.exports = function (grunt) {
|
||||
'build/EspoCRM-<%= pkg.version %>/client/**/*.tpl',
|
||||
'build/EspoCRM-<%= pkg.version %>/**/*.html',
|
||||
'build/EspoCRM-<%= pkg.version %>/**/*.txt',
|
||||
]
|
||||
],
|
||||
},
|
||||
folders: {
|
||||
options: {
|
||||
mode: '755'
|
||||
},
|
||||
src: [
|
||||
'build/EspoCRM-<%= pkg.version %>/install',
|
||||
'build/EspoCRM-<%= pkg.version %>/portal',
|
||||
'build/EspoCRM-<%= pkg.version %>/api',
|
||||
'build/EspoCRM-<%= pkg.version %>/api/v1',
|
||||
'build/EspoCRM-<%= pkg.version %>/api/v1/portal-access',
|
||||
'build/EspoCRM-<%= pkg.version %>/public/install',
|
||||
'build/EspoCRM-<%= pkg.version %>/public/portal',
|
||||
'build/EspoCRM-<%= pkg.version %>/public/api',
|
||||
'build/EspoCRM-<%= pkg.version %>/public/api/v1',
|
||||
'build/EspoCRM-<%= pkg.version %>/public/api/v1/portal-access',
|
||||
'build/EspoCRM-<%= pkg.version %>',
|
||||
]
|
||||
],
|
||||
},
|
||||
foldersWritable: {
|
||||
options: {
|
||||
@@ -274,79 +255,125 @@ module.exports = function (grunt) {
|
||||
'build/EspoCRM-<%= pkg.version %>/application/Espo/Modules',
|
||||
]
|
||||
},
|
||||
executable: {
|
||||
options: {
|
||||
mode: '754'
|
||||
},
|
||||
src: [
|
||||
'build/EspoCRM-<%= pkg.version %>/bin/*',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
replace: {
|
||||
version: {
|
||||
options: {
|
||||
patterns: [
|
||||
{
|
||||
match: 'version',
|
||||
replacement: '<%= pkg.version %>'
|
||||
replacement: '<%= pkg.version %>',
|
||||
}
|
||||
]
|
||||
},
|
||||
files: [
|
||||
{
|
||||
src: 'build/tmp/application/Espo/Core/defaults/config.php',
|
||||
dest: 'build/tmp/application/Espo/Core/defaults/config.php'
|
||||
src: 'build/tmp/application/Espo/Resources/defaults/config.php',
|
||||
dest: 'build/tmp/application/Espo/Resources/defaults/config.php',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
dev: {
|
||||
options: {
|
||||
patterns: [
|
||||
{
|
||||
match: /\# \{\#dev\}(.*)\{\/dev\}/gs,
|
||||
replacement: '',
|
||||
}
|
||||
]
|
||||
},
|
||||
files: [
|
||||
{
|
||||
src: 'build/tmp/.htaccess',
|
||||
dest: 'build/tmp/.htaccess',
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
grunt.registerTask("chmod-folders", function() {
|
||||
cp.execSync("find . -type d -exec chmod 755 {} + ", {stdio: 'ignore', cwd: 'build/EspoCRM-' + pkg.version});
|
||||
grunt.registerTask('chmod-folders', () => {
|
||||
cp.execSync(
|
||||
"find . -type d -exec chmod 755 {} + ",
|
||||
{
|
||||
stdio: 'ignore',
|
||||
cwd: 'build/EspoCRM-' + pkg.version,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
grunt.registerTask("composer", function() {
|
||||
grunt.registerTask('composer-install', () => {
|
||||
cp.execSync("composer install --no-dev", {stdio: 'ignore'});
|
||||
});
|
||||
|
||||
grunt.registerTask('composer-install-dev', () => {
|
||||
cp.execSync("composer install", {stdio: 'ignore'});
|
||||
});
|
||||
|
||||
grunt.registerTask("upgrade", function() {
|
||||
grunt.registerTask('upgrade', () => {
|
||||
cp.execSync("node diff --all --vendor", {stdio: 'inherit'});
|
||||
});
|
||||
|
||||
grunt.registerTask("unit-tests", function() {
|
||||
cp.execSync("phpunit --bootstrap=vendor/autoload.php tests/unit", {stdio: 'inherit'});
|
||||
grunt.registerTask('unit-tests-run', () => {
|
||||
cp.execSync("vendor/bin/phpunit ./tests/unit", {stdio: 'inherit'});
|
||||
});
|
||||
|
||||
grunt.registerTask("integration-tests", function() {
|
||||
cp.execSync("phpunit --bootstrap=vendor/autoload.php tests/integration", {stdio: 'inherit'});
|
||||
grunt.registerTask('integration-tests-run', () => {
|
||||
cp.execSync("vendor/bin/phpunit ./tests/integration", {stdio: 'inherit'});
|
||||
});
|
||||
|
||||
grunt.registerTask("zip", function() {
|
||||
var fs = require('fs');
|
||||
grunt.registerTask('zip', () => {
|
||||
const archiver = require('archiver');
|
||||
|
||||
var resolve = this.async();
|
||||
let resolve = this.async();
|
||||
|
||||
var folder = 'EspoCRM-' + pkg.version;
|
||||
let folder = 'EspoCRM-' + pkg.version;
|
||||
|
||||
var zipPath = 'build/' + folder +'.zip';
|
||||
if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
|
||||
let zipPath = 'build/' + folder +'.zip';
|
||||
|
||||
var archiver = require('archiver');
|
||||
var archive = archiver('zip');
|
||||
if (fs.existsSync(zipPath)) {
|
||||
fs.unlinkSync(zipPath);
|
||||
}
|
||||
|
||||
archive.on('error', function (err) {
|
||||
let archive = archiver('zip');
|
||||
|
||||
archive.on('error', err => {
|
||||
grunt.fail.warn(err);
|
||||
});
|
||||
var zipOutput = fs.createWriteStream(zipPath);
|
||||
zipOutput.on('close', function () {
|
||||
|
||||
let zipOutput = fs.createWriteStream(zipPath);
|
||||
|
||||
zipOutput.on('close', () => {
|
||||
console.log("EspoCRM package has been built.");
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
archive.directory(currentPath + '/build/' + folder, folder).pipe(zipOutput);
|
||||
archive
|
||||
.directory(currentPath + '/build/' + folder, folder)
|
||||
.pipe(zipOutput)
|
||||
.finalize();
|
||||
});
|
||||
|
||||
archive.finalize();
|
||||
grunt.registerTask('npm-install', () => {
|
||||
cp.execSync("npm install", {stdio: 'ignore'});
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-mkdir');
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify-es');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-replace');
|
||||
grunt.loadNpmTasks('grunt-chmod');
|
||||
@@ -356,10 +383,12 @@ module.exports = function (grunt) {
|
||||
'mkdir:tmp',
|
||||
'less',
|
||||
'cssmin',
|
||||
'uglify',
|
||||
'uglify:bundle',
|
||||
'copy:frontendFolders',
|
||||
'copy:frontendLib',
|
||||
'copy:frontendCommitedLib',
|
||||
'copy:backend',
|
||||
'uglify:lib',
|
||||
'replace',
|
||||
'clean:beforeFinal',
|
||||
'copy:final',
|
||||
@@ -367,29 +396,125 @@ module.exports = function (grunt) {
|
||||
'chmod:php',
|
||||
'chmod:folders',
|
||||
'chmod:foldersWritable',
|
||||
'chmod:executable',
|
||||
'clean:final',
|
||||
]);
|
||||
|
||||
grunt.registerTask('default', [
|
||||
'composer',
|
||||
grunt.registerTask('build', [
|
||||
'composer-install',
|
||||
'npm-install',
|
||||
'offline',
|
||||
]);
|
||||
|
||||
grunt.registerTask('default', [
|
||||
'build',
|
||||
]);
|
||||
|
||||
grunt.registerTask('release', [
|
||||
'default',
|
||||
'build',
|
||||
'upgrade',
|
||||
'zip',
|
||||
'clean:release',
|
||||
]);
|
||||
|
||||
grunt.registerTask('tests', [
|
||||
'default',
|
||||
'unit-tests',
|
||||
'integration-tests',
|
||||
grunt.registerTask('run-tests', [
|
||||
'test',
|
||||
'unit-tests-run',
|
||||
'integration-tests-run',
|
||||
]);
|
||||
|
||||
grunt.registerTask('run-unit-tests', [
|
||||
'composer-install-dev',
|
||||
'unit-tests-run',
|
||||
]);
|
||||
|
||||
grunt.registerTask('run-integration-tests', [
|
||||
'test',
|
||||
'integration-tests-run',
|
||||
]);
|
||||
|
||||
grunt.registerTask('dev', [
|
||||
'composer',
|
||||
'composer-install-dev',
|
||||
'less',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test', [
|
||||
'composer-install-dev',
|
||||
'npm-install',
|
||||
'offline',
|
||||
]);
|
||||
};
|
||||
|
||||
function getBundleLibList() {
|
||||
const libs = require('./frontend/libs.json');
|
||||
|
||||
let list = [];
|
||||
|
||||
libs.forEach(item => {
|
||||
if (!item.bundle) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.files) {
|
||||
item.files.forEach(item => {
|
||||
list.push(item.src);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.src) {
|
||||
throw new Error("No lib src.");
|
||||
}
|
||||
|
||||
list.push(item.src);
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function getCopyLibDataList() {
|
||||
const libs = require('./frontend/libs.json');
|
||||
|
||||
let list = [];
|
||||
|
||||
libs.forEach(item => {
|
||||
if (item.bundle) {
|
||||
return;
|
||||
}
|
||||
|
||||
let minify = item.minify;
|
||||
|
||||
if (item.files) {
|
||||
item.files.forEach(item => {
|
||||
list.push({
|
||||
src: item.src,
|
||||
dest: 'build/tmp/' + (item.dest || 'client/lib/' + item.src.split('/').pop()),
|
||||
minify: minify,
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.src) {
|
||||
throw new Error("No lib src.");
|
||||
}
|
||||
|
||||
list.push({
|
||||
src: item.src,
|
||||
dest: 'build/tmp/' + (item.dest || 'client/lib/' + item.src.split('/').pop()),
|
||||
minify: minify,
|
||||
});
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function camelCaseToHyphen(string){
|
||||
if (string === null) {
|
||||
return string;
|
||||
}
|
||||
|
||||
return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
}
|
||||
|
||||
74
README.md
74
README.md
@@ -1,21 +1,21 @@
|
||||
## EspoCRM
|
||||
|
||||
<a href='https://www.espocrm.com'>EspoCRM is an Open Source CRM</a> (Customer Relationship Management) software that allows you to see, enter and evaluate all your company relationships regardless of the type. People, companies or opportunities - all in an easy and intuitive interface.
|
||||
[EspoCRM is an Open Source CRM](https://www.espocrm.com) (Customer Relationship Management) software that allows you to see, enter and evaluate all your company relationships regardless of the type. People, companies or opportunities - all in an easy and intuitive interface.
|
||||
|
||||
It's a web application with a frontend designed as a single page application based on backbone.js and a REST API backend written in PHP.
|
||||
It's a web application with a frontend designed as a single page application and REST API backend written in PHP.
|
||||
|
||||
Download the latest release from our [website](https://www.espocrm.com).
|
||||
[Download](https://www.espocrm.com/download/) the latest release from our website.
|
||||
|
||||
### Requirements
|
||||
|
||||
* PHP 7.2 and later (with pdo, json, gd, openssl, zip, imap, mbstring, curl extensions);
|
||||
* PHP 7.3 and later (with pdo, json, gd, openssl, zip, imap, mbstring, curl extensions);
|
||||
* MySQL 5.7 (and later), or MariaDB 10.1 (and later).
|
||||
|
||||
For more information about server configuration see [this article](https://www.espocrm.com/documentation/administration/server-configuration/).
|
||||
For more information about server configuration see [this article](https://docs.espocrm.com/administration/server-configuration/).
|
||||
|
||||
### Documentation
|
||||
|
||||
Documentation for administrators, users and developers is available [here](https://www.espocrm.com/documentation/).
|
||||
Documentation for administrators, users and developers is available [here](https://docs.espocrm.com).
|
||||
|
||||
### How to report a bug
|
||||
|
||||
@@ -23,34 +23,15 @@ Create an issue [here](https://github.com/espocrm/espocrm/issues) or post on our
|
||||
|
||||
### How to install a stable version
|
||||
|
||||
[Download](https://www.espocrm.com/download/) the latest version. See the [instructions](https://www.espocrm.com/documentation/administration/installation/) about installation.
|
||||
[Download](https://www.espocrm.com/download/) the latest version. See the [instructions](https://docs.espocrm.com/administration/installation/) about installation.
|
||||
|
||||
### Getting started (for developers)
|
||||
### Development
|
||||
|
||||
1. Clone repository to your local computer.
|
||||
2. Change to the project's root directory.
|
||||
3. Install [composer](https://getcomposer.org/doc/00-intro.md).
|
||||
4. Run `composer install` if composer is installed globally or `php composer.phar install` if locally.
|
||||
* [Getting started](https://docs.espocrm.com/development/how-to-start)
|
||||
* [Running tests](https://docs.espocrm.com/development/tests)
|
||||
* [Making translation](https://docs.espocrm.com/development/translation)
|
||||
|
||||
Never update composer dependencies if you are going to contribute code back.
|
||||
|
||||
Now you can build. Build will create compiled css files.
|
||||
|
||||
To compose a proper config.php and populate database you can run install by opening `http(s)://{YOUR_CRM_URL}/install` location in a browser. Then open `data/config.php` file and add `isDeveloperMode => true`.
|
||||
|
||||
### How to build (for developers)
|
||||
|
||||
You need to have nodejs and Grunt CLI installed.
|
||||
|
||||
1. Change to the project's root directory.
|
||||
2. Install project dependencies with `npm install`.
|
||||
3. Run Grunt with `grunt`.
|
||||
|
||||
The build will be created in the `build` directory.
|
||||
|
||||
Upgrade packages can be built with `grunt upgrade`.
|
||||
|
||||
### How to contribute (for developers)
|
||||
### How to contribute
|
||||
|
||||
Before we can merge your pull request you need to accept our CLA [here](https://github.com/espocrm/cla). It's very simple to do.
|
||||
|
||||
@@ -60,37 +41,6 @@ Branches:
|
||||
* *master* – develop branch; new features should be pushed to this branch;
|
||||
* *stable* – last stable release.
|
||||
|
||||
### Running tests (for developers)
|
||||
|
||||
You need to have *phpunit* installed.
|
||||
|
||||
Unit tests:
|
||||
|
||||
```
|
||||
phpunit --bootstrap=vendor/autoload.php tests/unit
|
||||
```
|
||||
|
||||
Integration tests:
|
||||
|
||||
```
|
||||
phpunit --bootstrap=vendor/autoload.php tests/integration
|
||||
```
|
||||
|
||||
### How to make a translation
|
||||
|
||||
Build po file with command:
|
||||
`node po.js en_EN`
|
||||
(specify needed language instead of en_EN)
|
||||
|
||||
After that translate the generated po file.
|
||||
|
||||
Build json files from the translated po file:
|
||||
|
||||
1. Put your po file espocrm-en_EN.po into `build` directory
|
||||
2. Run `node lang.js en_EN`
|
||||
|
||||
Json files will be created in build directory grouped by folders.
|
||||
|
||||
### License
|
||||
|
||||
EspoCRM is published under the GNU GPLv3 [license](https://raw.githubusercontent.com/espocrm/espocrm/master/LICENSE.txt).
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
require_once('../../../bootstrap.php');
|
||||
|
||||
if (!empty($_GET['portalId'])) {
|
||||
$portalId = $_GET['portalId'];
|
||||
} else {
|
||||
$portalId = explode('/', $_SERVER['REQUEST_URI'])[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
}
|
||||
|
||||
$app = new \Espo\Core\Portal\Application($portalId);
|
||||
$app->run();
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class Attachment extends \Espo\Core\Acl\Base
|
||||
{
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->get('parentType') === 'Settings') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$parent = null;
|
||||
$hasParent = false;
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
$hasParent = true;
|
||||
$parent = $this->getEntityManager()->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
} else if ($entity->get('relatedId') && $entity->get('relatedType')) {
|
||||
$hasParent = true;
|
||||
$parent = $this->getEntityManager()->getEntity($entity->get('relatedType'), $entity->get('relatedId'));
|
||||
}
|
||||
|
||||
if ($hasParent) {
|
||||
if ($parent) {
|
||||
if ($parent->getEntityType() === 'Note') {
|
||||
if ($parent->get('parentId') && $parent->get('parentType')) {
|
||||
$parentOfParent = $this->getEntityManager()->getEntity($parent->get('parentType'), $parent->get('parentId'));
|
||||
if ($parentOfParent && $this->getAclManager()->checkEntity($user, $parentOfParent)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ($this->getAclManager()->checkEntity($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'read')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class EmailAddress extends \Espo\Core\Acl\Base
|
||||
{
|
||||
public function checkEditInEntity(EntityUser $user, Entity $entity, Entity $excludeEntity)
|
||||
{
|
||||
$id = $entity->id;
|
||||
|
||||
$isFobidden = false;
|
||||
|
||||
$repository = $this->getEntityManager()->getRepository('EmailAddress');
|
||||
|
||||
if (!$user->isAdmin()) {
|
||||
$entityWithSameAddressList = $repository->getEntityListByAddressId($id, $excludeEntity);
|
||||
foreach ($entityWithSameAddressList as $e) {
|
||||
if (!$this->getAclManager()->check($user, $e, 'edit')) {
|
||||
$isFobidden = true;
|
||||
if (
|
||||
$e->getEntityType() === 'User' &&
|
||||
$e->isPortal() &&
|
||||
$excludeEntity->getEntityType() === 'Contact' &&
|
||||
$e->get('contactId') === $excludeEntity->id
|
||||
) {
|
||||
$isFobidden = false;
|
||||
}
|
||||
if ($isFobidden) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !$isFobidden;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class Note extends \Espo\Core\Acl\Base
|
||||
{
|
||||
protected $deleteThresholdPeriod = '1 month';
|
||||
|
||||
protected $editThresholdPeriod = '7 days';
|
||||
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
if ($entity->get('type') === 'Post' && $user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityCreate(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
$parent = $this->getEntityManager()->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
if ($parent) {
|
||||
if ($this->getAclManager()->checkEntity($user, $parent, 'stream')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkEntityEdit(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'edit')) {
|
||||
if ($this->checkIsOwner($user, $entity)) {
|
||||
$createdAt = $entity->get('createdAt');
|
||||
if ($createdAt) {
|
||||
$noteEditThresholdPeriod = '-' . $this->getConfig()->get('noteEditThresholdPeriod', $this->editThresholdPeriod);
|
||||
$dt = new \DateTime();
|
||||
$dt->modify($noteEditThresholdPeriod);
|
||||
try {
|
||||
if ($dt->format('U') > (new \DateTime($createdAt))->format('U')) {
|
||||
return false;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'delete')) {
|
||||
if ($this->checkIsOwner($user, $entity)) {
|
||||
$createdAt = $entity->get('createdAt');
|
||||
if ($createdAt) {
|
||||
$deleteThresholdPeriod = '-' . $this->getConfig()->get('noteDeleteThresholdPeriod', $this->deleteThresholdPeriod);
|
||||
$dt = new \DateTime();
|
||||
$dt->modify($deleteThresholdPeriod);
|
||||
try {
|
||||
if ($dt->format('U') > (new \DateTime($createdAt))->format('U')) {
|
||||
return false;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class PhoneNumber extends \Espo\Core\Acl\Base
|
||||
{
|
||||
public function checkEditInEntity(EntityUser $user, Entity $entity, Entity $excludeEntity)
|
||||
{
|
||||
$id = $entity->id;
|
||||
|
||||
$isFobidden = false;
|
||||
|
||||
$repository = $this->getEntityManager()->getRepository('PhoneNumber');
|
||||
|
||||
if (!$user->isAdmin()) {
|
||||
$entityWithSameNumberList = $repository->getEntityListByPhoneNumberId($id, $excludeEntity);
|
||||
foreach ($entityWithSameNumberList as $e) {
|
||||
if (!$this->getAclManager()->check($user, $e, 'edit')) {
|
||||
$isFobidden = true;
|
||||
if (
|
||||
$e->getEntityType() === 'User' &&
|
||||
$e->isPortal() &&
|
||||
$excludeEntity->getEntityType() === 'Contact' &&
|
||||
$e->get('contactId') === $excludeEntity->id
|
||||
) {
|
||||
$isFobidden = false;
|
||||
}
|
||||
if ($isFobidden) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !$isFobidden;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class Webhook extends \Espo\Core\Acl\Base
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
return $user->id === $entity->get('userId') && $user->isApi();
|
||||
}
|
||||
|
||||
public function checkEntityCreate(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
if (!$data) return false;
|
||||
if ($user->isApi() && $user->id === $entity->get('userId')) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
if (!$data) return false;
|
||||
if ($user->isApi() && $user->id === $entity->get('userId')) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
if (!$data) return false;
|
||||
if ($user->isApi() && $user->id === $entity->get('userId')) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityEdit(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
if (!$data) return false;
|
||||
if ($user->isApi() && $user->id === $entity->get('userId')) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\AclPortal;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
|
||||
class Attachment extends \Espo\Core\AclPortal\Base
|
||||
{
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->get('parentType') === 'Settings') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$parent = null;
|
||||
$hasParent = false;
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
$hasParent = true;
|
||||
$parent = $this->getEntityManager()->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
} else if ($entity->get('relatedId') && $entity->get('relatedType')) {
|
||||
$hasParent = true;
|
||||
$parent = $this->getEntityManager()->getEntity($entity->get('relatedType'), $entity->get('relatedId'));
|
||||
}
|
||||
|
||||
if ($hasParent) {
|
||||
if ($parent) {
|
||||
if ($parent->getEntityType() === 'Note') {
|
||||
if ($parent->get('parentId') && $parent->get('parentType')) {
|
||||
$parentOfParent = $this->getEntityManager()->getEntity($parent->get('parentType'), $parent->get('parentId'));
|
||||
if ($parentOfParent && $this->getAclManager()->checkEntity($user, $parentOfParent)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ($this->getAclManager()->checkEntity($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'read')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\ActionHistoryRecord;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
return $entity->get('userId') === $user->getId();
|
||||
}
|
||||
}
|
||||
153
application/Espo/Classes/Acl/Attachment/AccessChecker.php
Normal file
153
application/Espo/Classes/Acl/Attachment/AccessChecker.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Attachment;
|
||||
|
||||
use Espo\Entities\{
|
||||
User,
|
||||
Note,
|
||||
};
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
ORM\EntityManager,
|
||||
AclManager,
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(
|
||||
DefaultAccessChecker $defaultAccessChecker,
|
||||
AclManager $aclManager,
|
||||
EntityManager $entityManager
|
||||
) {
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('parentType') === 'Settings') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$parent = null;
|
||||
|
||||
$hasParent = false;
|
||||
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
$hasParent = true;
|
||||
|
||||
$parent = $this->entityManager->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
}
|
||||
else if ($entity->get('relatedId') && $entity->get('relatedType')) {
|
||||
$hasParent = true;
|
||||
|
||||
$parent = $this->entityManager->getEntity($entity->get('relatedType'), $entity->get('relatedId'));
|
||||
}
|
||||
|
||||
if (!$parent || !$hasParent) {
|
||||
if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($parent->getEntityType() === 'Note') {
|
||||
$result = $this->checkEntityReadNoteParent($user, $parent);
|
||||
|
||||
if ($result !== null) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
else if ($this->aclManager->checkEntity($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function checkEntityReadNoteParent(User $user, Note $note): ?bool
|
||||
{
|
||||
if ($note->getTargetType() === Note::TARGET_TEAMS) {
|
||||
$intersect = array_intersect(
|
||||
$note->getLinkMultipleIdList('teams'),
|
||||
$user->getLinkMultipleIdList('teams')
|
||||
);
|
||||
|
||||
if (count($intersect)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($note->getTargetType() === Note::TARGET_USERS) {
|
||||
$isRelated = $this->entityManager
|
||||
->getRDBRepository('Note')
|
||||
->getRelation($note, 'users')
|
||||
->isRelated($user);
|
||||
|
||||
if ($isRelated) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$note->getParentId() || !$note->getParentType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntity($note->getParentType(), $note->getParentId());
|
||||
|
||||
if ($parent && $this->aclManager->checkEntity($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,22 +27,26 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\AclPortal;
|
||||
namespace Espo\Classes\Acl\Attachment;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Account extends \Espo\Core\AclPortal\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkInAccount(User $user, Entity $entity)
|
||||
private const ATTR_CREATED_BY_ID = 'createdById';
|
||||
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
$accountIdList = $user->getLinkMultipleIdList('accounts');
|
||||
if (count($accountIdList)) {
|
||||
if (in_array($entity->id, $accountIdList)) {
|
||||
return true;
|
||||
}
|
||||
if ($user->getId() === $entity->get(self::ATTR_CREATED_BY_ID)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,27 +27,30 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
namespace Espo\Classes\Acl\AuthToken;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Import extends \Espo\Core\Acl\Base
|
||||
use Espo\Core\{
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
private $defaultAccessChecker;
|
||||
|
||||
public function __construct(DefaultAccessChecker $defaultAccessChecker)
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
if ($user->id === $entity->get('createdById')) return true;
|
||||
|
||||
return false;
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(EntityUser $user, Entity $entity, $data)
|
||||
public function checkCreate(User $user, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
if ($user->id === $entity->get('createdById')) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,93 +27,101 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
namespace Espo\Classes\Acl\Email;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Email extends \Espo\Core\Acl\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\Table,
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDSChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDSChecker
|
||||
{
|
||||
protected $ownerUserIdAttribute = 'usersIds';
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
public function __construct(DefaultAccessChecker $defaultAccessChecker)
|
||||
{
|
||||
if ($this->checkEntity($user, $entity, $data, 'read')) {
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($data === false) {
|
||||
if ($data->isFalse()) {
|
||||
return false;
|
||||
}
|
||||
if (is_object($data)) {
|
||||
if ($data->read === false || $data->read === 'no') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data->getRead() === Table::LEVEL_NO) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$entity->has('usersIds')) {
|
||||
$entity->loadLinkMultipleField('users');
|
||||
}
|
||||
|
||||
$userIdList = $entity->get('usersIds');
|
||||
if (is_array($userIdList) && in_array($user->id, $userIdList)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
if ($user->id === $entity->get('assignedUserId')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->hasLinkMultipleId('assignedUsers', $user->id)) {
|
||||
if (is_array($userIdList) && in_array($user->getId(), $userIdList)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(EntityUser $user, Entity $entity, $data)
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($data === false) {
|
||||
if ($data->isFalse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data->delete === 'own') {
|
||||
if ($user->id === $entity->get('assignedUserId')) {
|
||||
if ($data->getDelete() === Table::LEVEL_OWN) {
|
||||
if ($user->getId() === $entity->get('assignedUserId')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
if ($user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers');
|
||||
if (count($assignedUserIdList) === 1 && $entity->hasLinkMultipleId('assignedUsers', $user->id)) {
|
||||
|
||||
if (
|
||||
count($assignedUserIdList) === 1 &&
|
||||
$entity->hasLinkMultipleId('assignedUsers', $user->getId())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'delete')) {
|
||||
if ($this->defaultAccessChecker->checkEntityDelete($user, $entity, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($data->edit !== 'no' || $data->create !== 'no') {
|
||||
if ($entity->get('createdById') === $user->id) {
|
||||
if ($entity->get('status') !== 'Sent' && $entity->get('status') !== 'Archived') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($data->getEdit() === Table::LEVEL_NO && $data->getCreate() === Table::LEVEL_NO) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->get('createdById') !== $user->getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->get('status') !== 'Sent' && $entity->get('status') !== 'Archived') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
51
application/Espo/Classes/Acl/Email/AssignmentChecker.php
Normal file
51
application/Espo/Classes/Acl/Email/AssignmentChecker.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Email;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\DefaultAssignmentChecker,
|
||||
};
|
||||
|
||||
class AssignmentChecker extends DefaultAssignmentChecker
|
||||
{
|
||||
protected function isPermittedAssignedUser(User $user, Entity $entity): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isPermittedAssignedUsers(User $user, Entity $entity): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,46 +27,46 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\AclPortal;
|
||||
namespace Espo\Classes\Acl\Email;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Email extends \Espo\Core\AclPortal\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\DefaultOwnershipChecker,
|
||||
Acl\OwnershipOwnChecker,
|
||||
Acl\OwnershipTeamChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker, OwnershipTeamChecker
|
||||
{
|
||||
protected $ownerUserIdAttribute = 'usersIds';
|
||||
private $defaultOwnershipChecker;
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
public function __construct(DefaultOwnershipChecker $defaultOwnershipChecker)
|
||||
{
|
||||
if ($this->checkEntity($user, $entity, $data, 'read')) {
|
||||
$this->defaultOwnershipChecker = $defaultOwnershipChecker;
|
||||
}
|
||||
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($user->getId() === $entity->get('assignedUserId')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($data === false) {
|
||||
return false;
|
||||
}
|
||||
if (is_object($data)) {
|
||||
if ($data->read === false || $data->read === 'no') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$entity->has('usersIds')) {
|
||||
$entity->loadLinkMultipleField('users');
|
||||
}
|
||||
$userIdList = $entity->get('usersIds');
|
||||
if (is_array($userIdList) && in_array($user->id, $userIdList)) {
|
||||
if ($user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->hasLinkMultipleId('assignedUsers', $user->getId())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
public function checkTeam(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return $this->defaultOwnershipChecker->checkTeam($user, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\EmailFilter;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if (!$entity->has('parentId') || !$entity->has('parentType')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parentType = $entity->get('parentType');
|
||||
$parentId = $entity->get('parentId');
|
||||
|
||||
if (!$parentType || !$parentId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntity($parentType, $parentId);
|
||||
|
||||
if (!$parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($parent->getEntityType() === 'User') {
|
||||
return $parent->getId() === $user->getId();
|
||||
}
|
||||
|
||||
if ($parent->has('assignedUserId') && $parent->get('assignedUserId') === $user->getId()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
84
application/Espo/Classes/Acl/Import/AccessChecker.php
Normal file
84
application/Espo/Classes/Acl/Import/AccessChecker.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Import;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\ScopeData,
|
||||
Acl\AccessEntityReadChecker,
|
||||
Acl\AccessEntityDeleteChecker,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityReadChecker, AccessEntityDeleteChecker
|
||||
{
|
||||
public function check(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $data->isTrue();
|
||||
}
|
||||
|
||||
public function checkRead(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $data->isTrue();
|
||||
}
|
||||
|
||||
public function checkDelete(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $data->isTrue();
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
172
application/Espo/Classes/Acl/Note/AccessChecker.php
Normal file
172
application/Espo/Classes/Acl/Note/AccessChecker.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Note;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
AclManager,
|
||||
ORM\EntityManager,
|
||||
Utils\Config,
|
||||
};
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private const EDIT_PERIOD = '7 days';
|
||||
|
||||
private const DELETE_PERIOD = '1 month';
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
private $config;
|
||||
|
||||
public function __construct(
|
||||
DefaultAccessChecker $defaultAccessChecker,
|
||||
AclManager $aclManager,
|
||||
EntityManager $entityManager,
|
||||
Config $config
|
||||
) {
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
$parentId = $entity->get('parentId');
|
||||
$parentType = $entity->get('parentType');
|
||||
|
||||
if (!$parentId || !$parentType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntity($parentType, $parentId);
|
||||
|
||||
if ($parent && $this->aclManager->checkEntityStream($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$this->defaultAccessChecker->checkEntityEdit($user, $entity, $data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkOwnershipOwn($user, $entity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$createdAt = $entity->get('createdAt');
|
||||
|
||||
if (!$createdAt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$noteEditThresholdPeriod =
|
||||
'-' . $this->config->get('noteEditThresholdPeriod', self::EDIT_PERIOD);
|
||||
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify($noteEditThresholdPeriod);
|
||||
|
||||
try {
|
||||
if ($dt->format('U') > (new DateTime($createdAt))->format('U')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$this->defaultAccessChecker->checkEntityDelete($user, $entity, $data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkOwnershipOwn($user, $entity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$createdAt = $entity->get('createdAt');
|
||||
|
||||
if (!$createdAt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$deleteThresholdPeriod =
|
||||
'-' . $this->config->get('noteDeleteThresholdPeriod', self::DELETE_PERIOD);
|
||||
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify($deleteThresholdPeriod);
|
||||
|
||||
try {
|
||||
if ($dt->format('U') > (new DateTime($createdAt))->format('U')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,22 +27,25 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\ORM\DB\Query;
|
||||
namespace Espo\Classes\Acl\Note;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\IEntity;
|
||||
use Espo\ORM\EntityFactory;
|
||||
use PDO;
|
||||
|
||||
class Mysql extends Base
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function limit($sql, $offset, $limit)
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if (!is_null($offset) && !is_null($limit)) {
|
||||
$offset = intval($offset);
|
||||
$limit = intval($limit);
|
||||
$sql .= " LIMIT {$offset}, {$limit}";
|
||||
|
||||
if ($entity->get('type') === 'Post' && $user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
return $sql;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,19 +27,24 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\AclPortal;
|
||||
namespace Espo\Classes\Acl\Notification;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Notification extends \Espo\Core\AclPortal\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($user->id === $entity->get('userId')) {
|
||||
if ($user->getId() === $entity->get('userId')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
63
application/Espo/Classes/Acl/Portal/AccessChecker.php
Normal file
63
application/Espo/Classes/Acl/Portal/AccessChecker.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Portal;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
Acl\Table,
|
||||
AclManager,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
public function __construct(DefaultAccessChecker $defaultAccessChecker, AclManager $aclManager)
|
||||
{
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
}
|
||||
|
||||
public function check(User $user, ScopeData $data): bool
|
||||
{
|
||||
$level = $this->aclManager->getPermissionLevel($user, 'portal');
|
||||
|
||||
return $level === Table::LEVEL_YES;
|
||||
}
|
||||
}
|
||||
89
application/Espo/Classes/Acl/ScheduledJob/AccessChecker.php
Normal file
89
application/Espo/Classes/Acl/ScheduledJob/AccessChecker.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\ScheduledJob;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
public function __construct(DefaultAccessChecker $defaultAccessChecker)
|
||||
{
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
}
|
||||
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('isInternal')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('isInternal')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityRead($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('isInternal')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityEdit($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('isInternal')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityDelete($user, $entity, $data);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,15 +27,22 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
namespace Espo\Classes\Acl\Team;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Team extends \Espo\Core\Acl\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkInTeam(\Espo\Entities\User $user, Entity $entity)
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
$userTeamIdList = $user->getLinkMultipleIdList('teams');
|
||||
return in_array($entity->id, $userTeamIdList);
|
||||
|
||||
return in_array($entity->getId(), $userTeamIdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,72 +27,103 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
namespace Espo\Classes\Acl\User;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class User extends \Espo\Core\Acl\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\Table,
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDSChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
AclManager,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDSChecker
|
||||
{
|
||||
public function checkIsOwner(\Espo\Entities\User $user, Entity $entity)
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
public function __construct(DefaultAccessChecker $defaultAccessChecker, AclManager $aclManager)
|
||||
{
|
||||
return $user->id === $entity->id;
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
}
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if (!$user->isAdmin() && $entity->isPortal()) {
|
||||
if ($this->getAclManager()->get($user, 'portalPermission') === 'yes') {
|
||||
if (!$user->isAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->isSuperAdmin() && !$user->isSuperAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->isPortal()) {
|
||||
if ($this->aclManager->getPermissionLevel($user, 'portal') === Table::LEVEL_YES) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $this->checkEntity($user, $entity, $data, 'read');
|
||||
}
|
||||
|
||||
public function checkEntityCreate(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if (!$user->isAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->isSuperAdmin() && !$user->isSuperAdmin()) {
|
||||
return false;
|
||||
}
|
||||
return $this->checkEntity($user, $entity, $data, 'create');
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityRead($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityDelete(EntityUser $user, Entity $entity, $data)
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->id === 'system') {
|
||||
return false;
|
||||
}
|
||||
if (!$user->isAdmin()) {
|
||||
return false;
|
||||
}
|
||||
if ($entity->isSystem()) {
|
||||
return false;
|
||||
}
|
||||
if ($entity->isSuperAdmin() && !$user->isSuperAdmin()) {
|
||||
return false;
|
||||
}
|
||||
return parent::checkEntityDelete($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityEdit(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($entity->id === 'system') {
|
||||
return false;
|
||||
}
|
||||
if ($entity->isSystem()) {
|
||||
return false;
|
||||
}
|
||||
if (!$user->isAdmin()) {
|
||||
if ($user->id !== $entity->id) {
|
||||
if ($user->getId() !== $entity->getId()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->isSuperAdmin() && !$user->isSuperAdmin()) {
|
||||
return false;
|
||||
}
|
||||
return $this->checkEntity($user, $entity, $data, 'edit');
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityEdit($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if (!$user->isAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->isSystem()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->isSuperAdmin() && !$user->isSuperAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityDelete($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityStream(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->aclManager->checkUserPermission($user, $entity, 'user');
|
||||
}
|
||||
}
|
||||
61
application/Espo/Classes/Acl/User/OwnershipChecker.php
Normal file
61
application/Espo/Classes/Acl/User/OwnershipChecker.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\User;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
Acl\OwnershipTeamChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker, OwnershipTeamChecker
|
||||
{
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
return $user->getId() === $entity->getId();
|
||||
}
|
||||
|
||||
public function checkTeam(User $user, Entity $entity): bool
|
||||
{
|
||||
$intersect = array_intersect(
|
||||
$user->getLinkMultipleIdList('teams'),
|
||||
$entity->getLinkMultipleIdList('teams')
|
||||
);
|
||||
|
||||
if (count($intersect)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
107
application/Espo/Classes/Acl/Webhook/AccessChecker.php
Normal file
107
application/Espo/Classes/Acl/Webhook/AccessChecker.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Webhook;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\ScopeData,
|
||||
Acl\DefaultAccessChecker,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
public function __construct(DefaultAccessChecker $defaultAccessChecker)
|
||||
{
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
}
|
||||
|
||||
public function check(User $user, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$user->isApi()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data->isFalse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntityInternal($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntityInternal($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntityInternal($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntityInternal($user, $entity, $data);
|
||||
}
|
||||
|
||||
private function checkEntityInternal(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($data->isFalse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($user->isApi() && $user->getId() === $entity->get('userId')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
46
application/Espo/Classes/Acl/Webhook/OwnershipChecker.php
Normal file
46
application/Espo/Classes/Acl/Webhook/OwnershipChecker.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Acl\Webhook;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
return $user->getId() === $entity->get('userId') && $user->isApi();
|
||||
}
|
||||
}
|
||||
158
application/Espo/Classes/AclPortal/Attachment/AccessChecker.php
Normal file
158
application/Espo/Classes/AclPortal/Attachment/AccessChecker.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AclPortal\Attachment;
|
||||
|
||||
use Espo\Entities\{
|
||||
User,
|
||||
Note,
|
||||
};
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
ORM\EntityManager,
|
||||
Portal\AclManager,
|
||||
Acl\ScopeData,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Portal\Acl\DefaultAccessChecker,
|
||||
Portal\Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(
|
||||
DefaultAccessChecker $defaultAccessChecker,
|
||||
AclManager $aclManager,
|
||||
EntityManager $entityManager
|
||||
) {
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('parentType') === 'Settings') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$parent = null;
|
||||
$hasParent = false;
|
||||
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
$hasParent = true;
|
||||
|
||||
$parent = $this->entityManager->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
}
|
||||
else if ($entity->get('relatedId') && $entity->get('relatedType')) {
|
||||
$hasParent = true;
|
||||
|
||||
$parent = $this->entityManager->getEntity($entity->get('relatedType'), $entity->get('relatedId'));
|
||||
}
|
||||
|
||||
if (!$hasParent) {
|
||||
if ($entity->get('createdById') === $user->getId()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($parent->getEntityType() === 'Note') {
|
||||
$result = $this->checkEntityReadNoteParent($user, $parent);
|
||||
|
||||
if ($result !== null) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
else if ($this->aclManager->checkEntity($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function checkEntityReadNoteParent(User $user, Note $note): ?bool
|
||||
{
|
||||
if ($note->isInternal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($note->getTargetType() === Note::TARGET_PORTALS) {
|
||||
$intersect = array_intersect(
|
||||
$note->getLinkMultipleIdList('portals'),
|
||||
$user->getLinkMultipleIdList('portals')
|
||||
);
|
||||
|
||||
if (count($intersect)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($note->getTargetType() === Note::TARGET_USERS) {
|
||||
$isRelated = $this->entityManager
|
||||
->getRDBRepository('Note')
|
||||
->getRelation($note, 'users')
|
||||
->isRelated($user);
|
||||
|
||||
if ($isRelated) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$note->getParentId() || !$note->getParentType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntity($note->getParentType(), $note->getParentId());
|
||||
|
||||
if ($parent && $this->aclManager->checkEntity($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AclPortal\Attachment;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
private const ATTR_CREATED_BY_ID = 'createdById';
|
||||
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($user->getId() === $entity->get(self::ATTR_CREATED_BY_ID)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
83
application/Espo/Classes/AclPortal/Email/AccessChecker.php
Normal file
83
application/Espo/Classes/AclPortal/Email/AccessChecker.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AclPortal\Email;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Portal\AclManager,
|
||||
Acl\Table,
|
||||
Acl\ScopeData,
|
||||
Acl\AccessEntityCREDSChecker,
|
||||
Portal\Acl\DefaultAccessChecker,
|
||||
Portal\Acl\Traits\DefaultAccessCheckerDependency,
|
||||
};
|
||||
|
||||
class AccessChecker implements AccessEntityCREDSChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
public function __construct(
|
||||
DefaultAccessChecker $defaultAccessChecker,
|
||||
AclManager $aclManager
|
||||
) {
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($data->isFalse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data->getRead() === Table::LEVEL_NO) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$userIdList = $entity->getLinkMultipleIdLIst('users');
|
||||
|
||||
if (is_array($userIdList) && in_array($user->getId(), $userIdList)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,19 +27,24 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Acl;
|
||||
namespace Espo\Classes\AclPortal\Email;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Notification extends \Espo\Core\Acl\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($user->id === $entity->get('userId')) {
|
||||
if ($user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
189
application/Espo/Classes/AclPortal/Note/AccessChecker.php
Normal file
189
application/Espo/Classes/AclPortal/Note/AccessChecker.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AclPortal\Note;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Portal\AclManager,
|
||||
Acl\ScopeData,
|
||||
Acl\AccessEntityCREDChecker,
|
||||
Portal\Acl\DefaultAccessChecker,
|
||||
Portal\Acl\Traits\DefaultAccessCheckerDependency,
|
||||
ORM\EntityManager,
|
||||
Utils\Config,
|
||||
};
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
class AccessChecker implements AccessEntityCREDChecker
|
||||
{
|
||||
use DefaultAccessCheckerDependency;
|
||||
|
||||
private const EDIT_PERIOD = '7 days';
|
||||
|
||||
private const DELETE_PERIOD = '1 month';
|
||||
|
||||
private $defaultAccessChecker;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
private $config;
|
||||
|
||||
public function __construct(
|
||||
DefaultAccessChecker $defaultAccessChecker,
|
||||
AclManager $aclManager,
|
||||
EntityManager $entityManager,
|
||||
Config $config
|
||||
) {
|
||||
$this->defaultAccessChecker = $defaultAccessChecker;
|
||||
$this->aclManager = $aclManager;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
$parentId = $entity->get('parentId');
|
||||
$parentType = $entity->get('parentType');
|
||||
|
||||
if (!$parentId || !$parentType) {
|
||||
return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data);
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntity($parentType, $parentId);
|
||||
|
||||
if ($parent && $this->aclManager->checkEntityStream($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if ($entity->get('type') !== 'Post') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->get('type') === 'Post' && $entity->get('targetType')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$entity->get('parentId') || !$entity->get('parentType')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
|
||||
if ($parent) {
|
||||
if ($this->aclManager->checkEntityStream($user, $parent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if (!$this->defaultAccessChecker->checkEntityEdit($user, $entity, $data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkOwnershipOwn($user, $entity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$createdAt = $entity->get('createdAt');
|
||||
|
||||
if (!$createdAt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$noteEditThresholdPeriod =
|
||||
'-' . $this->config->get('noteEditThresholdPeriod', self::EDIT_PERIOD);
|
||||
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify($noteEditThresholdPeriod);
|
||||
|
||||
try {
|
||||
if ($dt->format('U') > (new DateTime($createdAt))->format('U')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
if (!$this->defaultAccessChecker->checkEntityDelete($user, $entity, $data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkOwnershipOwn($user, $entity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$createdAt = $entity->get('createdAt');
|
||||
|
||||
if (!$createdAt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$deleteThresholdPeriod =
|
||||
'-' . $this->config->get('noteDeleteThresholdPeriod', self::DELETE_PERIOD);
|
||||
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify($deleteThresholdPeriod);
|
||||
|
||||
try {
|
||||
if ($dt->format('U') > (new DateTime($createdAt))->format('U')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
50
application/Espo/Classes/AclPortal/Note/OwnershipChecker.php
Normal file
50
application/Espo/Classes/AclPortal/Note/OwnershipChecker.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AclPortal\Note;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($entity->get('type') === 'Post' && $user->getId() === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,22 +27,24 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\AclPortal;
|
||||
namespace Espo\Classes\AclPortal\Notification;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Contact extends \Espo\Core\AclPortal\Base
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkIsOwnContact(User $user, Entity $entity)
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
$contactId = $user->get('contactId');
|
||||
if ($contactId) {
|
||||
if ($entity->id === $contactId) {
|
||||
return true;
|
||||
}
|
||||
if ($user->getId() === $entity->get('userId')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
46
application/Espo/Classes/AclPortal/User/OwnershipChecker.php
Normal file
46
application/Espo/Classes/AclPortal/User/OwnershipChecker.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AclPortal\User;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl\OwnershipOwnChecker,
|
||||
};
|
||||
|
||||
class OwnershipChecker implements OwnershipOwnChecker
|
||||
{
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
return $user->getId() === $entity->getId();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,41 +27,63 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\EntryPoints;
|
||||
namespace Espo\Classes\AddressFormatters;
|
||||
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\{
|
||||
Field\Address,
|
||||
Field\Address\AddressFormatter,
|
||||
};
|
||||
|
||||
class Portal extends \Espo\Core\EntryPoints\Base
|
||||
class Formatter1 implements AddressFormatter
|
||||
{
|
||||
public static $authRequired = false;
|
||||
|
||||
public function run($data = array())
|
||||
public function format(Address $address): string
|
||||
{
|
||||
if (!empty($_GET['id'])) {
|
||||
$id = $_GET['id'];
|
||||
} else if (!empty($data['id'])) {
|
||||
$id = $data['id'];
|
||||
} else {
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
$id = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
$result = '';
|
||||
|
||||
if (!isset($id)) {
|
||||
$url = $_SERVER['REDIRECT_URL'];
|
||||
$id = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
$street = $address->getStreet();
|
||||
$city = $address->getCity();
|
||||
$country = $address->getCountry();
|
||||
$state = $address->getState();
|
||||
$postalCode = $address->getPostalCode();
|
||||
|
||||
if ($street) {
|
||||
$result .= $street;
|
||||
}
|
||||
|
||||
if ($city || $state || $postalCode) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
if (!$id) {
|
||||
$id = $this->getConfig()->get('defaultPortalId');
|
||||
if ($city) {
|
||||
$result .= $city;
|
||||
}
|
||||
if (!$id) {
|
||||
throw new NotFound();
|
||||
|
||||
if ($state && $city) {
|
||||
$result .= ', ';
|
||||
}
|
||||
|
||||
if ($state) {
|
||||
$result .= $state;
|
||||
}
|
||||
|
||||
if ($postalCode && ($state || $city)) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
if ($postalCode) {
|
||||
$result .= $postalCode;
|
||||
}
|
||||
}
|
||||
|
||||
$application = new \Espo\Core\Portal\Application($id);
|
||||
$application->setBasePath($this->getContainer()->get('clientManager')->getBasePath());
|
||||
$application->runClient();
|
||||
if ($country) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
$result .= $country;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
91
application/Espo/Classes/AddressFormatters/Formatter2.php
Normal file
91
application/Espo/Classes/AddressFormatters/Formatter2.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AddressFormatters;
|
||||
|
||||
use Espo\Core\{
|
||||
Field\Address,
|
||||
Field\Address\AddressFormatter,
|
||||
};
|
||||
|
||||
class Formatter2 implements AddressFormatter
|
||||
{
|
||||
public function format(Address $address): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
$street = $address->getStreet();
|
||||
$city = $address->getCity();
|
||||
$country = $address->getCountry();
|
||||
$state = $address->getState();
|
||||
$postalCode = $address->getPostalCode();
|
||||
|
||||
if ($street) {
|
||||
$result .= $street;
|
||||
}
|
||||
|
||||
if ($city || $postalCode) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
if ($postalCode) {
|
||||
$result .= $postalCode;
|
||||
}
|
||||
|
||||
if ($postalCode && $city) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
if ($city) {
|
||||
$result .= $city;
|
||||
}
|
||||
}
|
||||
|
||||
if ($state || $country) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
if ($state) {
|
||||
$result .= $state;
|
||||
}
|
||||
|
||||
if ($state && $country) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
if ($country) {
|
||||
$result .= $country;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
89
application/Espo/Classes/AddressFormatters/Formatter3.php
Normal file
89
application/Espo/Classes/AddressFormatters/Formatter3.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AddressFormatters;
|
||||
|
||||
use Espo\Core\{
|
||||
Field\Address,
|
||||
Field\Address\AddressFormatter,
|
||||
};
|
||||
|
||||
class Formatter3 implements AddressFormatter
|
||||
{
|
||||
public function format(Address $address): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
$street = $address->getStreet();
|
||||
$city = $address->getCity();
|
||||
$country = $address->getCountry();
|
||||
$state = $address->getState();
|
||||
$postalCode = $address->getPostalCode();
|
||||
|
||||
if ($country) {
|
||||
$result .= $country;
|
||||
}
|
||||
|
||||
if ($city || $state || $postalCode) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
if ($state) {
|
||||
$result .= $state;
|
||||
}
|
||||
|
||||
if ($state && $postalCode) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
if ($postalCode) {
|
||||
$result .= $postalCode;
|
||||
}
|
||||
|
||||
if ($city && ($state || $postalCode)) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
if ($city) {
|
||||
$result .= $city;
|
||||
}
|
||||
}
|
||||
|
||||
if ($street) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
$result .= $street;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
89
application/Espo/Classes/AddressFormatters/Formatter4.php
Normal file
89
application/Espo/Classes/AddressFormatters/Formatter4.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AddressFormatters;
|
||||
|
||||
use Espo\Core\{
|
||||
Field\Address,
|
||||
Field\Address\AddressFormatter,
|
||||
};
|
||||
|
||||
class Formatter4 implements AddressFormatter
|
||||
{
|
||||
public function format(Address $address): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
$street = $address->getStreet();
|
||||
$city = $address->getCity();
|
||||
$country = $address->getCountry();
|
||||
$state = $address->getState();
|
||||
$postalCode = $address->getPostalCode();
|
||||
|
||||
if ($street) {
|
||||
$result .= $street;
|
||||
}
|
||||
|
||||
if ($city) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
$result .= $city;
|
||||
}
|
||||
|
||||
if ($country || $state || $postalCode) {
|
||||
if ($result) {
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
if ($country) {
|
||||
$result .= $country;
|
||||
}
|
||||
|
||||
if ($state && $country) {
|
||||
$result .= ' - ';
|
||||
}
|
||||
|
||||
if ($state) {
|
||||
$result .= $state;
|
||||
}
|
||||
|
||||
if ($postalCode && ($state || $country)) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
if ($postalCode) {
|
||||
$result .= $postalCode;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
120
application/Espo/Classes/AppInfo/Binding.php
Normal file
120
application/Espo/Classes/AppInfo/Binding.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AppInfo;
|
||||
|
||||
use Espo\Core\{
|
||||
Utils\Module,
|
||||
Binding\EspoBindingLoader,
|
||||
Binding\Binding as BindingItem,
|
||||
Console\Command\Params,
|
||||
};
|
||||
|
||||
class Binding
|
||||
{
|
||||
private $module;
|
||||
|
||||
public function __construct(Module $module)
|
||||
{
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
public function process(Params $params): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
$bindingLoader = new EspoBindingLoader($this->module);
|
||||
|
||||
$data = $bindingLoader->load();
|
||||
|
||||
$keyList = $data->getGlobalKeyList();
|
||||
|
||||
$result .= "Global:\n\n";
|
||||
|
||||
foreach ($keyList as $key) {
|
||||
$result .= $this->printItem($key, $data->getGlobal($key));
|
||||
}
|
||||
|
||||
$contextList = $data->getContextList();
|
||||
|
||||
foreach ($contextList as $context) {
|
||||
$result .= "Context: {$context}\n\n";
|
||||
|
||||
$keyList = $data->getContextKeyList($context);
|
||||
|
||||
foreach ($keyList as $key) {
|
||||
$result .= $this->printItem($key, $data->getContext($context, $key), true);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function printItem(string $key, BindingItem $binding): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
$tab = ' ';
|
||||
|
||||
$result .= $tab . "Key: {$key}\n";
|
||||
|
||||
$type = $binding->getType();
|
||||
$value = $binding->getValue();
|
||||
|
||||
$typeString = [
|
||||
BindingItem::IMPLEMENTATION_CLASS_NAME => 'Implementation',
|
||||
BindingItem::CONTAINER_SERVICE => 'Service',
|
||||
BindingItem::VALUE => 'Value',
|
||||
BindingItem::CALLBACK => 'Callback',
|
||||
BindingItem::FACTORY_CLASS_NAME => 'Factory',
|
||||
][$type];
|
||||
|
||||
$result .= $tab . "Type: {$typeString}\n";
|
||||
|
||||
if ($type == BindingItem::IMPLEMENTATION_CLASS_NAME || $type == BindingItem::CONTAINER_SERVICE) {
|
||||
$result .= $tab . "Value: {$value}\n";
|
||||
}
|
||||
|
||||
if ($type == BindingItem::VALUE) {
|
||||
if (is_string($value) || is_int($value) || is_float($value)) {
|
||||
$result .= $tab . "Value: {$value}\n";
|
||||
}
|
||||
|
||||
if (is_bool($value)) {
|
||||
$valueString = $value ? 'true' : 'false';
|
||||
|
||||
$result .= $tab . "Value: {$valueString}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$result .= "\n";
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
109
application/Espo/Classes/AppInfo/Container.php
Normal file
109
application/Espo/Classes/AppInfo/Container.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AppInfo;
|
||||
|
||||
use Espo\Core\{
|
||||
Container as ContainerService,
|
||||
Utils\Metadata,
|
||||
Console\Command\Params,
|
||||
};
|
||||
|
||||
class Container
|
||||
{
|
||||
private $container;
|
||||
|
||||
private $metadata;
|
||||
|
||||
public function __construct(ContainerService $container, Metadata $metadata)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
public function process(Params $params): string
|
||||
{
|
||||
$nameOnly = $params->hasFlag('nameOnly');
|
||||
|
||||
$result = '';
|
||||
|
||||
$serviceList = [
|
||||
'injectableFactory',
|
||||
'config',
|
||||
'log',
|
||||
'fileManager',
|
||||
'dataManager',
|
||||
'metadata',
|
||||
'user',
|
||||
];
|
||||
|
||||
$fileList = scandir('application/Espo/Core/Loaders');
|
||||
|
||||
if (file_exists('custom/Espo/Custom/Core/Loaders')) {
|
||||
$fileList = array_merge($fileList, scandir('custom/Espo/Custom/Core/Loaders'));
|
||||
}
|
||||
|
||||
foreach ($fileList as $file) {
|
||||
if (substr($file, -4) === '.php') {
|
||||
$name = lcfirst(substr($file, 0, -4));
|
||||
|
||||
if (!in_array($name, $serviceList) && $this->container->has($name)) {
|
||||
$serviceList[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->metadata->get(['app', 'containerServices']) ?? [] as $name => $data) {
|
||||
if (!in_array($name, $serviceList)) {
|
||||
$serviceList[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
sort($serviceList);
|
||||
|
||||
if ($nameOnly) {
|
||||
foreach ($serviceList as $name) {
|
||||
$result .= $name . "\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
foreach ($serviceList as $name) {
|
||||
$result .= $name . "\n";
|
||||
|
||||
$obj = $this->container->get($name);
|
||||
$result .= get_class($obj) . "\n";
|
||||
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
68
application/Espo/Classes/AppInfo/Jobs.php
Normal file
68
application/Espo/Classes/AppInfo/Jobs.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AppInfo;
|
||||
|
||||
use Espo\Core\Console\Command\Params;
|
||||
use Espo\Core\Utils\ClassFinder;
|
||||
use Espo\Core\Job\MetadataProvider;
|
||||
|
||||
class Jobs
|
||||
{
|
||||
private $classFinder;
|
||||
|
||||
private $metadataProvider;
|
||||
|
||||
public function __construct(ClassFinder $classFinder, MetadataProvider $metadataProvider)
|
||||
{
|
||||
$this->classFinder = $classFinder;
|
||||
$this->metadataProvider = $metadataProvider;
|
||||
}
|
||||
|
||||
public function process(Params $params): string
|
||||
{
|
||||
$result = "Available jobs:\n\n";
|
||||
|
||||
$list = array_map(
|
||||
function ($item) {
|
||||
return ' ' . $item;
|
||||
},
|
||||
array_unique(
|
||||
array_merge(
|
||||
array_keys($this->classFinder->getMap('Jobs')),
|
||||
$this->metadataProvider->getScheduledJobNameList()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
asort($list);
|
||||
|
||||
return $result . implode("\n", $list) . "\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AppParams;
|
||||
|
||||
use Espo\Core\{
|
||||
Acl,
|
||||
Select\SelectBuilderFactory,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of entity types for which a PDF template exists.
|
||||
*/
|
||||
class TemplateEntityTypeList
|
||||
{
|
||||
protected $acl;
|
||||
protected $selectBuilderFactory;
|
||||
protected $entityManager;
|
||||
|
||||
public function __construct(Acl $acl, SelectBuilderFactory $selectBuilderFactory, EntityManager $entityManager)
|
||||
{
|
||||
$this->acl = $acl;
|
||||
$this->selectBuilderFactory = $selectBuilderFactory;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function get() : array
|
||||
{
|
||||
if (!$this->acl->checkScope('Template')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
|
||||
$query = $this->selectBuilderFactory
|
||||
->create()
|
||||
->from('Template')
|
||||
->withAccessControlFilter()
|
||||
->buildQueryBuilder()
|
||||
->select(['entityType'])
|
||||
->group(['entityType'])
|
||||
->build();
|
||||
|
||||
$templateCollection = $this->entityManager
|
||||
->getRepository('Template')
|
||||
->clone($query)
|
||||
->find();
|
||||
|
||||
foreach ($templateCollection as $template) {
|
||||
$list[] = $template->get('entityType');
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
296
application/Espo/Classes/AssignmentNotificators/Email.php
Normal file
296
application/Espo/Classes/AssignmentNotificators/Email.php
Normal file
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\AssignmentNotificators;
|
||||
|
||||
use Espo\Services\Email as EmailService;
|
||||
use Espo\Services\Stream as StreamService;
|
||||
|
||||
use Espo\Core\Notification\AssignmentNotificator;
|
||||
use Espo\Core\Notification\AssignmentNotificator\Params;
|
||||
use Espo\Core\Notification\UserEnabledChecker;
|
||||
use Espo\Core\ServiceFactory;
|
||||
use Espo\Core\AclManager;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\Entities\Notification;
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
class Email implements AssignmentNotificator
|
||||
{
|
||||
private const DAYS_THRESHOLD = 2;
|
||||
|
||||
private $streamService = null;
|
||||
|
||||
private $user;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
private $serviceFactory;
|
||||
|
||||
private $aclManager;
|
||||
|
||||
private $userChecker;
|
||||
|
||||
public function __construct(
|
||||
User $user,
|
||||
EntityManager $entityManager,
|
||||
UserEnabledChecker $userChecker,
|
||||
ServiceFactory $serviceFactory,
|
||||
AclManager $aclManager
|
||||
) {
|
||||
$this->user = $user;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->userChecker = $userChecker;
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
$this->aclManager = $aclManager;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
if (!in_array($entity->get('status'), ['Archived', 'Sent', 'Being Imported'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($params->getOption('isJustSent')) {
|
||||
$previousUserIdList = [];
|
||||
}
|
||||
else {
|
||||
$previousUserIdList = $entity->getFetched('usersIds');
|
||||
|
||||
if (!is_array($previousUserIdList)) {
|
||||
$previousUserIdList = [];
|
||||
}
|
||||
}
|
||||
|
||||
$dateSent = $entity->get('dateSent');
|
||||
|
||||
if (!$dateSent) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$dt = new DateTime($dateSent);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$dt) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($dt->diff(new DateTime())->days > self::DAYS_THRESHOLD) {
|
||||
return;
|
||||
}
|
||||
|
||||
$emailUserIdList = $entity->get('usersIds');
|
||||
|
||||
if (is_null($emailUserIdList) || !is_array($emailUserIdList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userIdList = [];
|
||||
|
||||
foreach ($emailUserIdList as $userId) {
|
||||
if (
|
||||
!in_array($userId, $userIdList) &&
|
||||
!in_array($userId, $previousUserIdList) &&
|
||||
$userId !== $this->user->getId()
|
||||
) {
|
||||
$userIdList[] = $userId;
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'emailId' => $entity->getId(),
|
||||
'emailName' => $entity->get('name'),
|
||||
];
|
||||
|
||||
if (!$entity->has('from')) {
|
||||
$this->entityManager->getRepository('Email')->loadFromField($entity);
|
||||
}
|
||||
|
||||
if (!$entity->has('to')) {
|
||||
$this->entityManager->getRepository('Email')->loadToField($entity);
|
||||
}
|
||||
|
||||
$person = null;
|
||||
|
||||
$from = $entity->get('from');
|
||||
|
||||
if ($from) {
|
||||
$person = $this->entityManager
|
||||
->getRepository('EmailAddress')
|
||||
->getEntityByAddress($from, null, ['User', 'Contact', 'Lead']);
|
||||
|
||||
if ($person) {
|
||||
$data['personEntityType'] = $person->getEntityType();
|
||||
$data['personEntityName'] = $person->get('name');
|
||||
$data['personEntityId'] = $person->getId();
|
||||
}
|
||||
}
|
||||
|
||||
$userIdFrom = null;
|
||||
|
||||
if ($person && $person->getEntityType() === 'User') {
|
||||
$userIdFrom = $person->id;
|
||||
}
|
||||
|
||||
if (empty($data['personEntityId'])) {
|
||||
$data['fromString'] = EmailService::parseFromName($entity->get('fromString'));
|
||||
|
||||
if (empty($data['fromString']) && $from) {
|
||||
$data['fromString'] = $from;
|
||||
}
|
||||
}
|
||||
|
||||
$parent = null;
|
||||
|
||||
if ($entity->get('parentId') && $entity->get('parentType')) {
|
||||
$parent = $this->entityManager->getEntity($entity->get('parentType'), $entity->get('parentId'));
|
||||
}
|
||||
|
||||
$account = null;
|
||||
|
||||
if ($entity->get('accountId')) {
|
||||
$account = $this->entityManager->getEntity('Account', $entity->get('accountId'));
|
||||
}
|
||||
|
||||
foreach ($userIdList as $userId) {
|
||||
if (!$userId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($userIdFrom === $userId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($entity->getLinkMultipleColumn('users', 'inTrash', $userId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->userChecker->checkAssignment('Email', $userId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
$params->getOption('isBeingImported') ||
|
||||
$params->getOption('isJustSent')
|
||||
) {
|
||||
$folderId = $entity->getLinkMultipleColumn('users', 'folderId', $userId);
|
||||
|
||||
if ($folderId) {
|
||||
if (
|
||||
$this->entityManager
|
||||
->getRepository('EmailFolder')
|
||||
->where([
|
||||
'id' => $folderId,
|
||||
'skipNotifications' => true,
|
||||
])
|
||||
->count()
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$user = $this->entityManager->getEntity('User', $userId);
|
||||
|
||||
if (!$user) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($user->isPortal()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkScope($user, 'Email')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isArchivedOrBeingImported =
|
||||
$entity->get('status') === 'Archived' ||
|
||||
$params->getOption('isBeingImported');
|
||||
|
||||
if (
|
||||
$isArchivedOrBeingImported &&
|
||||
$parent &&
|
||||
$this->getStreamService()->checkIsFollowed($parent, $userId)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
$isArchivedOrBeingImported &&
|
||||
$account &&
|
||||
$this->getStreamService()->checkIsFollowed($account, $userId)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existing = $this->entityManager
|
||||
->getRepository(Notification::ENTITY_TYPE)
|
||||
->where([
|
||||
'type' => Notification::TYPE_EMAIL_RECEIVED,
|
||||
'userId' => $userId,
|
||||
'relatedId' => $entity->getId(),
|
||||
'relatedType' => 'Email',
|
||||
])
|
||||
->select(['id'])
|
||||
->findOne();
|
||||
|
||||
if ($existing) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->entityManager->createEntity(Notification::ENTITY_TYPE, [
|
||||
'type' => Notification::TYPE_EMAIL_RECEIVED,
|
||||
'userId' => $userId,
|
||||
'data' => $data,
|
||||
'relatedId' => $entity->getId(),
|
||||
'relatedType' => 'Email',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getStreamService(): StreamService
|
||||
{
|
||||
if (empty($this->streamService)) {
|
||||
$this->streamService = $this->serviceFactory->create('Stream');
|
||||
}
|
||||
|
||||
return $this->streamService;
|
||||
}
|
||||
}
|
||||
71
application/Espo/Classes/Cleanup/Reminders.php
Normal file
71
application/Espo/Classes/Cleanup/Reminders.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Cleanup;
|
||||
|
||||
use Espo\Core\Cleanup\Cleanup;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class Reminders implements Cleanup
|
||||
{
|
||||
private $config;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
private $cleanupRemindersPeriod = '15 days';
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupRemindersPeriod', $this->cleanupRemindersPeriod);
|
||||
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify($period);
|
||||
|
||||
$delete = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('Reminder')
|
||||
->where([
|
||||
'remindAt<' => $dt->format('Y-m-d'),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
}
|
||||
77
application/Espo/Classes/Cleanup/TwoFactorCodes.php
Normal file
77
application/Espo/Classes/Cleanup/TwoFactorCodes.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Cleanup;
|
||||
|
||||
use Espo\Core\Cleanup\Cleanup;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\DateTime as DateTimeUtil;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use Espo\Entities\TwoFactorCode;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class TwoFactorCodes implements Cleanup
|
||||
{
|
||||
private const PERIOD = '5 days';
|
||||
|
||||
private $config;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupTwoFactorCodesPeriod', self::PERIOD);
|
||||
|
||||
$from = (new DateTime())
|
||||
->modify($period)
|
||||
->format(DateTimeUtil::SYSTEM_DATE_TIME_FORMAT);
|
||||
|
||||
$query = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from(TwoFactorCode::ENTITY_TYPE)
|
||||
->where([
|
||||
'createdAt<' => $from,
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager
|
||||
->getQueryExecutor()
|
||||
->execute($query);
|
||||
}
|
||||
}
|
||||
91
application/Espo/Classes/Cleanup/WebhookQueue.php
Normal file
91
application/Espo/Classes/Cleanup/WebhookQueue.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Cleanup;
|
||||
|
||||
use Espo\Core\Cleanup\Cleanup;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class WebhookQueue implements Cleanup
|
||||
{
|
||||
private $cleanupWebhookQueuePeriod = '10 days';
|
||||
|
||||
private $config;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupWebhookQueuePeriod', $this->cleanupWebhookQueuePeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
|
||||
$datetime->modify($period);
|
||||
$from = $datetime->format('Y-m-d H:i:s');
|
||||
|
||||
$query1 = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('WebhookQueueItem')
|
||||
->where([
|
||||
'DATE:(createdAt)<' => $from,
|
||||
'OR' => [
|
||||
'status!=' => 'Pending',
|
||||
'deleted' => true,
|
||||
],
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query1);
|
||||
|
||||
$query2 = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('WebhookEventQueueItem')
|
||||
->where([
|
||||
'DATE:(createdAt)<' => $from,
|
||||
'OR' => [
|
||||
'isProcessed' => true,
|
||||
'deleted' => true,
|
||||
],
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query2);
|
||||
}
|
||||
}
|
||||
132
application/Espo/Classes/ConsoleCommands/Import.php
Normal file
132
application/Espo/Classes/ConsoleCommands/Import.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\ConsoleCommands;
|
||||
|
||||
use Espo\Tools\Import\Service;
|
||||
|
||||
use Espo\Core\{
|
||||
Console\Command,
|
||||
Console\Command\Params,
|
||||
Console\IO,
|
||||
};
|
||||
|
||||
use Throwable;
|
||||
|
||||
class Import implements Command
|
||||
{
|
||||
private $service;
|
||||
|
||||
public function __construct(Service $service)
|
||||
{
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
public function run(Params $params, IO $io) : void
|
||||
{
|
||||
$id = $params->getOption('id');
|
||||
$filePath = $params->getOption('file');
|
||||
$paramsId = $params->getOption('paramsId');
|
||||
|
||||
$forceResume = $params->hasFlag('resume');
|
||||
$revert = $params->hasFlag('revert');
|
||||
|
||||
if (!$id && $filePath) {
|
||||
if (!$paramsId) {
|
||||
$io->writeLine("You need to specify --params-id option.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file_exists($filePath)) {
|
||||
$io->writeLine("File not found.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$contents = file_get_contents($filePath);
|
||||
|
||||
try {
|
||||
$result = $this->service->importContentsWithParamsId($contents, $paramsId);
|
||||
|
||||
$resultId = $result->getId();
|
||||
$countCreated = $result->getCountCreated();
|
||||
$countUpdated = $result->getCountUpdated();
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$io->writeLine("Error occurred: ". $e->getMessage() . "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$io->writeLine("Finished. Import ID: {$resultId}. Created: {$countCreated}. Updated: {$countUpdated}.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($id && $revert) {
|
||||
$io->writeLine("Reverting import...");
|
||||
|
||||
try {
|
||||
$this->service->revert($id);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$io->writeLine("Error occurred: " . $e->getMessage() . "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$io->writeLine("Finished.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
$io->writeLine("Running import, this may take a while...");
|
||||
|
||||
try {
|
||||
$result = $this->service->importById($id, true, $forceResume);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$io->writeLine("Error occurred: " . $e->getMessage() . "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$countCreated = $result->getCountCreated();
|
||||
$countUpdated = $result->getCountUpdated();
|
||||
|
||||
$io->writeLine("Finished. Created: {$countCreated}. Updated: {$countUpdated}.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$io->writeLine("Not enough params passed.");
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,18 +27,20 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\Layout\Defaults;
|
||||
namespace Espo\Classes\DefaultLayouts;
|
||||
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
class DefaultSidePanelType
|
||||
{
|
||||
protected $metadata;
|
||||
|
||||
public function __construct(\Espo\Core\Utils\Metadata $metadata)
|
||||
public function __construct(Metadata $metadata)
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
public function get(string $scope) : array
|
||||
public function get(string $scope): array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
104
application/Espo/Classes/DuplicateWhereBuilders/Company.php
Normal file
104
application/Espo/Classes/DuplicateWhereBuilders/Company.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\DuplicateWhereBuilders;
|
||||
|
||||
use Espo\Core\Duplicate\WhereBuilder;
|
||||
|
||||
use Espo\ORM\{
|
||||
Query\Part\Condition as Cond,
|
||||
Query\Part\WhereItem,
|
||||
Query\Part\Where\OrGroup,
|
||||
Entity,
|
||||
};
|
||||
|
||||
class Company implements WhereBuilder
|
||||
{
|
||||
public function build(Entity $entity): ?WhereItem
|
||||
{
|
||||
$orBuilder = OrGroup::createBuilder();
|
||||
|
||||
$toCheck = false;
|
||||
|
||||
if ($entity->get('name')) {
|
||||
$orBuilder->add(
|
||||
Cond::equal(
|
||||
Cond::column('name'),
|
||||
$entity->get('name')
|
||||
),
|
||||
);
|
||||
|
||||
$toCheck = true;
|
||||
}
|
||||
|
||||
if (
|
||||
($entity->get('emailAddress') || $entity->get('emailAddressData')) &&
|
||||
(
|
||||
$entity->isNew() ||
|
||||
$entity->isAttributeChanged('emailAddress') ||
|
||||
$entity->isAttributeChanged('emailAddressData')
|
||||
)
|
||||
) {
|
||||
foreach ($this->getEmailAddressList($entity) as $emailAddress) {
|
||||
$orBuilder->add(
|
||||
Cond::equal(
|
||||
Cond::column('emailAddress'),
|
||||
$emailAddress
|
||||
)
|
||||
);
|
||||
|
||||
$toCheck = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$toCheck) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $orBuilder->build();
|
||||
}
|
||||
|
||||
private function getEmailAddressList(Entity $entity): array
|
||||
{
|
||||
if ($entity->get('emailAddressData')) {
|
||||
/* @var $eaGroup EmailAddressGroup */
|
||||
$eaGroup = $entity->getValueObject('emailAddress');
|
||||
|
||||
return $eaGroup->getAddressList();
|
||||
}
|
||||
|
||||
if ($entity->get('emailAddress')) {
|
||||
return [
|
||||
$entity->get('emailAddress')
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
113
application/Espo/Classes/DuplicateWhereBuilders/Person.php
Normal file
113
application/Espo/Classes/DuplicateWhereBuilders/Person.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\DuplicateWhereBuilders;
|
||||
|
||||
use Espo\Core\{
|
||||
Duplicate\WhereBuilder,
|
||||
Field\EmailAddressGroup,
|
||||
};
|
||||
|
||||
use Espo\ORM\{
|
||||
Query\Part\Condition as Cond,
|
||||
Query\Part\WhereItem,
|
||||
Query\Part\Where\OrGroup,
|
||||
Entity,
|
||||
};
|
||||
|
||||
class Person implements WhereBuilder
|
||||
{
|
||||
public function build(Entity $entity): ?WhereItem
|
||||
{
|
||||
$orBuilder = OrGroup::createBuilder();
|
||||
|
||||
$toCheck = false;
|
||||
|
||||
if ($entity->get('firstName') || $entity->get('lastName')) {
|
||||
$orBuilder->add(
|
||||
Cond::and(
|
||||
Cond::equal(
|
||||
Cond::column('firstName'),
|
||||
$entity->get('firstName')
|
||||
),
|
||||
Cond::equal(
|
||||
Cond::column('lastName'),
|
||||
$entity->get('lastName')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$toCheck = true;
|
||||
}
|
||||
|
||||
if (
|
||||
($entity->get('emailAddress') || $entity->get('emailAddressData')) &&
|
||||
(
|
||||
$entity->isNew() ||
|
||||
$entity->isAttributeChanged('emailAddress') ||
|
||||
$entity->isAttributeChanged('emailAddressData')
|
||||
)
|
||||
) {
|
||||
foreach ($this->getEmailAddressList($entity) as $emailAddress) {
|
||||
$orBuilder->add(
|
||||
Cond::equal(
|
||||
Cond::column('emailAddress'),
|
||||
$emailAddress
|
||||
)
|
||||
);
|
||||
|
||||
$toCheck = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$toCheck) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $orBuilder->build();
|
||||
}
|
||||
|
||||
private function getEmailAddressList(Entity $entity): array
|
||||
{
|
||||
if ($entity->get('emailAddressData')) {
|
||||
/* @var $eaGroup EmailAddressGroup */
|
||||
$eaGroup = $entity->getValueObject('emailAddress');
|
||||
|
||||
return $eaGroup->getAddressList();
|
||||
}
|
||||
|
||||
if ($entity->get('emailAddress')) {
|
||||
return [
|
||||
$entity->get('emailAddress')
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Email;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use Espo\Repositories\Email as EmailRepository;
|
||||
|
||||
class AddressDataLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
/* @var $repository EmailRepository */
|
||||
$repository = $this->entityManager->getRepository('Email');
|
||||
|
||||
$repository->loadFromField($entity);
|
||||
$repository->loadToField($entity);
|
||||
$repository->loadCcField($entity);
|
||||
$repository->loadBccField($entity);
|
||||
$repository->loadReplyToField($entity);
|
||||
$repository->loadNameHash($entity);
|
||||
}
|
||||
}
|
||||
205
application/Espo/Classes/FieldProcessing/Email/IcsDataLoader.php
Normal file
205
application/Espo/Classes/FieldProcessing/Email/IcsDataLoader.php
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Email;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\Repositories\EmailAddress as EmailAddressRepository;
|
||||
use Espo\Entities\EmailAddress;
|
||||
use Espo\Entities\Email;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
Mail\Event\Event as EspoEvent,
|
||||
Mail\Event\EventFactory,
|
||||
Utils\Log,
|
||||
};
|
||||
|
||||
use ICal\ICal;
|
||||
use ICal\Event;
|
||||
|
||||
use Throwable;
|
||||
|
||||
class IcsDataLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
private $log;
|
||||
|
||||
private $entityTypeLinkMap = [
|
||||
'User' => 'users',
|
||||
'Contact' => 'contacts',
|
||||
'Lead' => 'leads',
|
||||
];
|
||||
|
||||
public function __construct(EntityManager $entityManager, Log $log)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->log = $log;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
$icsContents = $entity->get('icsContents');
|
||||
|
||||
if ($icsContents === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ical = new ICal();
|
||||
|
||||
$ical->initString($icsContents);
|
||||
|
||||
/* @var $event Event */
|
||||
$event = $ical->events()[0] ?? null;
|
||||
|
||||
if ($event === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->status === 'CANCELLED') {
|
||||
return;
|
||||
}
|
||||
|
||||
$espoEvent = EventFactory::createFromU01jmg3Ical($ical);
|
||||
|
||||
$valueMap = (object) [
|
||||
'sourceEmailId' => $entity->getId(),
|
||||
];
|
||||
|
||||
try {
|
||||
$valueMap->name = $espoEvent->getName();
|
||||
$valueMap->description = $espoEvent->getDescription();
|
||||
$valueMap->dateStart = $espoEvent->getDateStart();
|
||||
$valueMap->dateEnd = $espoEvent->getDateEnd();
|
||||
$valueMap->location = $espoEvent->getLocation();
|
||||
$valueMap->isAllDay = $espoEvent->isAllDay();
|
||||
|
||||
if ($espoEvent->isAllDay()) {
|
||||
$valueMap->dateStartDate = $espoEvent->getDateStart();
|
||||
$valueMap->dateEndDate = $espoEvent->getDateEnd();
|
||||
}
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->log->warning("Error while converting ICS event '" . $entity->getId() . "': " . $e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* @var $emailAddressRepository EmailAddressRepository */
|
||||
$emailAddressRepository = $this->entityManager->getRepository(EmailAddress::ENTITY_TYPE);
|
||||
|
||||
$attendeeEmailAddressList = $espoEvent->getAttendeeEmailAddressList();
|
||||
|
||||
$organizerEmailAddress = $espoEvent->getOrganizerEmailAddress();
|
||||
|
||||
if ($organizerEmailAddress) {
|
||||
$attendeeEmailAddressList[] = $organizerEmailAddress;
|
||||
}
|
||||
|
||||
foreach ($attendeeEmailAddressList as $address) {
|
||||
$personEntity = $emailAddressRepository->getEntityByAddress($address);
|
||||
|
||||
if (!$personEntity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$link = $this->entityTypeLinkMap[$personEntity->getEntityType()] ?? null;
|
||||
|
||||
if (!$link) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$idsAttribute = $link . 'Ids';
|
||||
$namesAttribute = $link . 'Names';
|
||||
|
||||
$idList = $valueMap->$idsAttribute ?? [];
|
||||
$nameMap = $valueMap->$namesAttribute ?? (object) [];
|
||||
|
||||
$idList[] = $personEntity->getId();
|
||||
$nameMap->{$personEntity->getId()} = $personEntity->get('name');
|
||||
|
||||
$valueMap->$idsAttribute = $idList;
|
||||
$valueMap->$namesAttribute = $nameMap;
|
||||
}
|
||||
|
||||
$eventData = (object) [
|
||||
'valueMap' => $valueMap,
|
||||
'uid' => $espoEvent->getUid(),
|
||||
'createdEvent' => null,
|
||||
];
|
||||
|
||||
$this->loadCreatedEvent($entity, $espoEvent, $eventData);
|
||||
|
||||
$entity->set('icsEventData', $eventData);
|
||||
|
||||
$entity->set('icsEventDateStart', $espoEvent->getDateStart());
|
||||
|
||||
if ($espoEvent->isAllDay()) {
|
||||
$entity->set('icsEventDateStartDate', $espoEvent->getDateStart());
|
||||
}
|
||||
}
|
||||
|
||||
private function loadCreatedEvent(Entity $entity, EspoEvent $espoEvent, object $eventData): void
|
||||
{
|
||||
$emailSameEvent = $this->entityManager
|
||||
->getRDBRepository(Email::ENTITY_TYPE)
|
||||
->where([
|
||||
'icsEventUid' => $espoEvent->getUid(),
|
||||
'id!=' => $entity->getId()
|
||||
])
|
||||
->findOne();
|
||||
|
||||
if (!$emailSameEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!$emailSameEvent->get('createdEventId') ||
|
||||
!$emailSameEvent->get('createdEventType')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$createdEvent = $this->entityManager
|
||||
->getEntity($emailSameEvent->get('createdEventType'), $emailSameEvent->get('createdEventId'));
|
||||
|
||||
if (!$createdEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eventData->createdEvent = (object) [
|
||||
'id' => $createdEvent->getId(),
|
||||
'entityType' => $emailSameEvent->getEntityType(),
|
||||
'name' => $createdEvent->get('name'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Email;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use Espo\Entities\Email;
|
||||
use Espo\Entities\User;
|
||||
|
||||
class StringDataLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
private $user;
|
||||
|
||||
private $fromEmailAddressNameCache = [];
|
||||
|
||||
public function __construct(EntityManager $entityManager, User $user)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
$userEmailAdddressIdList = [];
|
||||
|
||||
$emailAddressCollection = $this->entityManager
|
||||
->getRDBRepository('User')
|
||||
->getRelation($this->user, 'emailAddresses')
|
||||
->select(['id'])
|
||||
->find();
|
||||
|
||||
foreach ($emailAddressCollection as $emailAddress) {
|
||||
$userEmailAdddressIdList[] = $emailAddress->getId();
|
||||
}
|
||||
|
||||
if (
|
||||
in_array($entity->get('fromEmailAddressId'), $userEmailAdddressIdList) ||
|
||||
$entity->get('createdById') === $this->user->getId() && $entity->get('status') === Email::STATUS_SENT
|
||||
) {
|
||||
$entity->loadLinkMultipleField('toEmailAddresses');
|
||||
|
||||
$idList = $entity->get('toEmailAddressesIds');
|
||||
$names = $entity->get('toEmailAddressesNames');
|
||||
|
||||
if (empty($idList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($idList as $emailAddressId) {
|
||||
$person = $this->entityManager
|
||||
->getRepository('EmailAddress')
|
||||
->getEntityByAddressId($emailAddressId, null, true);
|
||||
|
||||
$list[] = $person ? $person->get('name') : $names->$emailAddressId;
|
||||
}
|
||||
|
||||
$entity->set('personStringData', 'To: ' . implode(', ', $list));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$fromEmailAddressId = $entity->get('fromEmailAddressId');
|
||||
|
||||
if (!$fromEmailAddressId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!array_key_exists($fromEmailAddressId, $this->fromEmailAddressNameCache)) {
|
||||
$person = $this->entityManager
|
||||
->getRepository('EmailAddress')
|
||||
->getEntityByAddressId($fromEmailAddressId, null, true);
|
||||
|
||||
$fromName = $person ? $person->get('name') : null;
|
||||
|
||||
$this->fromEmailAddressNameCache[$fromEmailAddressId] = $fromName;
|
||||
}
|
||||
|
||||
$fromName =
|
||||
$this->fromEmailAddressNameCache[$fromEmailAddressId] ??
|
||||
$entity->get('fromName') ??
|
||||
$entity->get('fromEmailAddressName');
|
||||
|
||||
$entity->set('personStringData', $fromName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Email;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
class UserColumnsLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
private $user;
|
||||
|
||||
public function __construct(EntityManager $entityManager, User $user)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
$emailUser = $this->entityManager
|
||||
->getRepository('EmailUser')
|
||||
->select(['isRead', 'isImportant', 'inTrash'])
|
||||
->where([
|
||||
'deleted' => false,
|
||||
'userId' => $this->user->getId(),
|
||||
'emailId' => $entity->getId(),
|
||||
])
|
||||
->findOne();
|
||||
|
||||
if (!$emailUser) {
|
||||
$entity->set('isRead', null);
|
||||
$entity->clear('isImportant');
|
||||
$entity->clear('inTrash');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$entity->set([
|
||||
'isRead' => $emailUser->get('isRead'),
|
||||
'isImportant' => $emailUser->get('isImportant'),
|
||||
'inTrash' => $emailUser->get('inTrash'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Import;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use Espo\Repositories\Import as ImportRepository;
|
||||
|
||||
class CountsLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
/* @var $repository ImportRepository */
|
||||
$repository = $this->entityManager->getRepository('Import');
|
||||
|
||||
$importedCount = $repository->countResultRecords($entity, 'imported');
|
||||
$duplicateCount = $repository->countResultRecords($entity, 'duplicates');
|
||||
$updatedCount = $repository->countResultRecords($entity, 'updated');
|
||||
|
||||
$entity->set([
|
||||
'importedCount' => $importedCount,
|
||||
'duplicateCount' => $duplicateCount,
|
||||
'updatedCount' => $updatedCount,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Note;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
};
|
||||
|
||||
use Espo\Entities\Note;
|
||||
|
||||
class AttachmentsLoader implements Loader
|
||||
{
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
/* @var $entity Note */
|
||||
$entity->loadAttachments();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\Portal;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
class UrlLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
$this->entityManager
|
||||
->getRepository('Portal')
|
||||
->loadUrlField($entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\FieldProcessing\User;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
FieldProcessing\Loader,
|
||||
FieldProcessing\Loader\Params,
|
||||
ORM\EntityManager,
|
||||
Acl,
|
||||
Acl\Table,
|
||||
};
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
class LastAccessLoader implements Loader
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
private $acl;
|
||||
|
||||
public function __construct(EntityManager $entityManager, Acl $acl)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->acl = $acl;
|
||||
}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
$forbiddenFieldList = $this->acl
|
||||
->getScopeForbiddenFieldList($entity->getEntityType(), Table::ACTION_READ);
|
||||
|
||||
if (in_array('lastAccess', $forbiddenFieldList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$authToken = $this->entityManager
|
||||
->getRDBRepository('AuthToken')
|
||||
->select(['id', 'lastAccess'])
|
||||
->where([
|
||||
'userId' => $entity->getId(),
|
||||
])
|
||||
->order('lastAccess', 'DESC')
|
||||
->findOne();
|
||||
|
||||
$lastAccess = null;
|
||||
|
||||
if ($authToken) {
|
||||
$lastAccess = $authToken->get('lastAccess');
|
||||
}
|
||||
|
||||
$dt = null;
|
||||
|
||||
if ($lastAccess) {
|
||||
try {
|
||||
$dt = new DateTime($lastAccess);
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
$where = [
|
||||
'userId' => $entity->getId(),
|
||||
'isDenied' => false,
|
||||
];
|
||||
|
||||
if ($dt) {
|
||||
$where['requestTime>'] = $dt->format('U');
|
||||
}
|
||||
|
||||
$authLogRecord = $this->entityManager
|
||||
->getRDBRepository('AuthLogRecord')
|
||||
->select(['id', 'createdAt'])
|
||||
->where($where)
|
||||
->order('requestTime', true)
|
||||
->findOne();
|
||||
|
||||
if ($authLogRecord) {
|
||||
$lastAccess = $authLogRecord->get('createdAt');
|
||||
}
|
||||
|
||||
$entity->set('lastAccess', $lastAccess);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class ArrayIntType extends ArrayType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,36 +27,59 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class ArrayType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use StdClass;
|
||||
|
||||
class ArrayType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
public function checkMaxCount(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkMaxCount(Entity $entity, string $field, int $validationValue): bool
|
||||
{
|
||||
if (!$this->isNotEmpty($entity, $field)) return true;
|
||||
if (!$this->isNotEmpty($entity, $field)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$list = $entity->get($field);
|
||||
if (count($list) > $validationValue) return false;
|
||||
|
||||
if (count($list) > $validationValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkArray(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function rawCheckArray(StdClass $data, string $field): bool
|
||||
{
|
||||
if (!$entity->has($field) || $entity->get($field) === null) return true;
|
||||
if (isset($data->$field) && $data->$field !== null && !is_array($data->$field)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_array($entity->get($field));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
if (!$entity->has($field) || $entity->get($field) === null) return false;
|
||||
if (!$entity->has($field) || $entity->get($field) === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$list = $entity->get($field);
|
||||
if (!is_array($list)) return false;
|
||||
if (count($list)) return true;
|
||||
|
||||
if (!is_array($list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count($list)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class ChecklistType extends ArrayType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,11 +27,13 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class CurrencyType extends FloatType
|
||||
{
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return
|
||||
$entity->has($field) && $entity->get($field) !== null &&
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,16 +27,18 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class DateType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class DateType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,19 +27,27 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class DatetimeOptionalType extends DatetimeType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
if ($entity->has($field) && $entity->get($field) !== null) return true;
|
||||
if ($entity->has($field . 'Date') && $entity->get($field . 'Date') !== null) return true;
|
||||
if ($entity->has($field) && $entity->get($field) !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->has($field . 'Date') && $entity->get($field . 'Date') !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class DatetimeType extends DateType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,48 +27,65 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class EmailType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class EmailType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) return true;
|
||||
if ($this->isNotEmpty($entity, $field)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$dataList = $entity->get($field . 'Data');
|
||||
if (!is_array($dataList)) return false;
|
||||
|
||||
if (!is_array($dataList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($dataList as $item) {
|
||||
if (!empty($item->emailAddress)) return true;
|
||||
if (!empty($item->emailAddress)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEmailAddress(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkEmailAddress(Entity $entity, string $field): bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) {
|
||||
$address = $entity->get($field);
|
||||
|
||||
if (!filter_var($address, FILTER_VALIDATE_EMAIL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$dataList = $entity->get($field . 'Data');
|
||||
if (is_array($dataList)) {
|
||||
foreach ($dataList as $item) {
|
||||
if (empty($item->emailAddress)) continue;
|
||||
$address = $item->emailAddress;
|
||||
if (!filter_var($address, FILTER_VALIDATE_EMAIL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_array($dataList)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($dataList as $item) {
|
||||
if (empty($item->emailAddress)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$address = $item->emailAddress;
|
||||
|
||||
if (!filter_var($address, FILTER_VALIDATE_EMAIL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,16 +27,18 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class EnumType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class EnumType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class FileType extends LinkType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class FloatType extends IntType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class ImageType extends FileType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,30 +27,44 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class IntType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class IntType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
public function checkMax(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkMax(Entity $entity, string $field, $validationValue): bool
|
||||
{
|
||||
if (!$this->isNotEmpty($entity, $field)) return true;
|
||||
if ($entity->get($field) > $validationValue) return false;
|
||||
if (!$this->isNotEmpty($entity, $field)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->get($field) > $validationValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkMin(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkMin(Entity $entity, string $field, $validationValue): bool
|
||||
{
|
||||
if (!$this->isNotEmpty($entity, $field)) return true;
|
||||
if ($entity->get($field) < $validationValue) return false;
|
||||
if (!$this->isNotEmpty($entity, $field)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($entity->get($field) < $validationValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,29 +27,39 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\AclPortal;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class KnowledgeBaseArticle extends \Espo\Core\AclPortal\Base
|
||||
use StdClass;
|
||||
|
||||
class JsonArrayType
|
||||
{
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
public function rawCheckArray(StdClass $data, string $field): bool
|
||||
{
|
||||
if (!$this->checkEntity($user, $entity, $data, 'read')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($entity->get('status') !== 'Published') return false;
|
||||
|
||||
$portalIdList = $entity->getLinkMultipleIdList('portals');
|
||||
|
||||
if ($user->get('portalId') && !in_array($user->get('portalId'), $portalIdList)) {
|
||||
if (isset($data->$field) && $data->$field !== null && !is_array($data->$field)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
if (!$entity->has($field) || $entity->get($field) === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$list = $entity->get($field);
|
||||
|
||||
if (!is_array($list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count($list)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,11 +27,13 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class LinkMultipleType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class LinkMultipleType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return count($entity->getLinkMultipleIdList($field)) > 0;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,16 +27,22 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class LinkParentType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class LinkParentType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
$idAttribute = $field . 'Id';
|
||||
$typeAttribute = $field . 'Type';
|
||||
|
||||
if (!$entity->has($idAttribute) || $entity->get($idAttribute) === '' || $entity->get($idAttribute) === null) {
|
||||
if (
|
||||
!$entity->has($idAttribute) ||
|
||||
$entity->get($idAttribute) === '' ||
|
||||
$entity->get($idAttribute) === null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,11 +27,13 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class LinkType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class LinkType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
$idAttribute = $field . 'Id';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,7 +27,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class MultiEnumType extends ArrayType
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,23 +27,45 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class PersonNameType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Utils\FieldUtil,
|
||||
};
|
||||
|
||||
class PersonNameType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
private $fieldUtil;
|
||||
|
||||
public function __construct(FieldUtil $fieldUtil)
|
||||
{
|
||||
$this->fieldUtil = $fieldUtil;
|
||||
}
|
||||
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
$isEmpty = true;
|
||||
foreach ($this->getActualAttributeList($entity, $field) as $attribute) {
|
||||
|
||||
$attributeList = $this->fieldUtil->getActualAttributeList($entity->getEntityType(), $field);
|
||||
|
||||
foreach ($attributeList as $attribute) {
|
||||
if ($attribute === 'salutation' . ucfirst($field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($entity->has($attribute) && $entity->get($attribute) !== '') {
|
||||
$isEmpty = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($isEmpty) return false;
|
||||
|
||||
if ($isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,25 +27,34 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class PhoneType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class PhoneType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) return true;
|
||||
if ($this->isNotEmpty($entity, $field)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$dataList = $entity->get($field . 'Data');
|
||||
if (!is_array($dataList)) return false;
|
||||
|
||||
if (!is_array($dataList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($dataList as $item) {
|
||||
if (!empty($item->phoneNumber)) return true;
|
||||
if (!empty($item->phoneNumber)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,27 +27,31 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
class VarcharType extends BaseType
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class VarcharType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field): bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
public function checkMaxLength(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkMaxLength(Entity $entity, string $field, int $validationValue): bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) {
|
||||
$value = $entity->get($field);
|
||||
|
||||
if (mb_strlen($value) > $validationValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, string $field): bool
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null;
|
||||
}
|
||||
109
application/Espo/Classes/JobPreparators/CheckEmailAccounts.php
Normal file
109
application/Espo/Classes/JobPreparators/CheckEmailAccounts.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\JobPreparators;
|
||||
|
||||
use Espo\Core\Utils\DateTime;
|
||||
use Espo\Core\Job\Job\Status;
|
||||
use Espo\Core\Job\Preparator;
|
||||
use Espo\Core\Job\Preparator\Data;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use Espo\Entities\Job as JobEntity;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
class CheckEmailAccounts implements Preparator
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function prepare(Data $data, DateTimeImmutable $executeTime): void
|
||||
{
|
||||
$collection = $this->entityManager
|
||||
->getRDBRepository('EmailAccount')
|
||||
->join('assignedUser', 'assignedUserAdditional')
|
||||
->where([
|
||||
'status' => 'Active',
|
||||
'useImap' => true,
|
||||
'assignedUserAdditional.isActive' => true,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($collection as $entity) {
|
||||
$running = $this->entityManager
|
||||
->getRDBRepository(JobEntity::ENTITY_TYPE)
|
||||
->where([
|
||||
'scheduledJobId' => $data->getId(),
|
||||
'status' => [
|
||||
Status::RUNNING,
|
||||
Status::READY,
|
||||
],
|
||||
'targetType' => 'EmailAccount',
|
||||
'targetId' => $entity->getId(),
|
||||
])
|
||||
->findOne();
|
||||
|
||||
if ($running) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$countPending = $this->entityManager
|
||||
->getRDBRepository(JobEntity::ENTITY_TYPE)
|
||||
->where([
|
||||
'scheduledJobId' => $data->getId(),
|
||||
'status' => Status::PENDING,
|
||||
'targetType' => 'EmailAccount',
|
||||
'targetId' => $entity->getId(),
|
||||
])
|
||||
->count();
|
||||
|
||||
if ($countPending > 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$jobEntity = $this->entityManager->getEntity(JobEntity::ENTITY_TYPE);
|
||||
|
||||
$jobEntity->set([
|
||||
'name' => $data->getName(),
|
||||
'scheduledJobId' => $data->getId(),
|
||||
'executeTime' => $executeTime->format(DateTime::SYSTEM_DATE_TIME_FORMAT),
|
||||
'targetType' => 'EmailAccount',
|
||||
'targetId' => $entity->getId(),
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($jobEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
application/Espo/Classes/JobPreparators/CheckInboundEmails.php
Normal file
107
application/Espo/Classes/JobPreparators/CheckInboundEmails.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\JobPreparators;
|
||||
|
||||
use Espo\Core\Utils\DateTime;
|
||||
use Espo\Core\Job\Job\Status;
|
||||
use Espo\Core\Job\Preparator;
|
||||
use Espo\Core\Job\Preparator\Data;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use Espo\Entities\Job as JobEntity;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
class CheckInboundEmails implements Preparator
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function prepare(Data $data, DateTimeImmutable $executeTime): void
|
||||
{
|
||||
$collection = $this->entityManager
|
||||
->getRDBRepository('InboundEmail')
|
||||
->where([
|
||||
'status' => 'Active',
|
||||
'useImap' => true,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($collection as $entity) {
|
||||
$running = $this->entityManager
|
||||
->getRDBRepository(JobEntity::ENTITY_TYPE)
|
||||
->where([
|
||||
'scheduledJobId' => $data->getId(),
|
||||
'status' => [
|
||||
Status::RUNNING,
|
||||
Status::READY,
|
||||
],
|
||||
'targetType' => 'InboundEmail',
|
||||
'targetId' => $entity->getId(),
|
||||
])
|
||||
->findOne();
|
||||
|
||||
if ($running) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$countPending = $this->entityManager
|
||||
->getRDBRepository(JobEntity::ENTITY_TYPE)
|
||||
->where([
|
||||
'scheduledJobId' => $data->getId(),
|
||||
'status' => Status::PENDING,
|
||||
'targetType' => 'InboundEmail',
|
||||
'targetId' => $entity->getId(),
|
||||
])
|
||||
->count();
|
||||
|
||||
if ($countPending > 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$jobEntity = $this->entityManager->getEntity(JobEntity::ENTITY_TYPE);
|
||||
|
||||
$jobEntity->set([
|
||||
'name' => $data->getName(),
|
||||
'scheduledJobId' => $data->getId(),
|
||||
'executeTime' => $executeTime->format(DateTime::SYSTEM_DATE_TIME_FORMAT),
|
||||
'targetType' => 'InboundEmail',
|
||||
'targetId' => $entity->getId(),
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($jobEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,47 +27,71 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Jobs;
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
use \Espo\Core\Exceptions;
|
||||
use Espo\Core\{
|
||||
Utils\Config,
|
||||
ORM\EntityManager,
|
||||
Job\JobDataLess,
|
||||
};
|
||||
|
||||
class AuthTokenControl extends \Espo\Core\Jobs\Base
|
||||
use DateTime;
|
||||
|
||||
class AuthTokenControl implements JobDataLess
|
||||
{
|
||||
public function run()
|
||||
private $config;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
$authTokenLifetime = $this->getConfig()->get('authTokenLifetime');
|
||||
$authTokenMaxIdleTime = $this->getConfig()->get('authTokenMaxIdleTime');
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$authTokenLifetime = $this->config->get('authTokenLifetime');
|
||||
$authTokenMaxIdleTime = $this->config->get('authTokenMaxIdleTime');
|
||||
|
||||
if (!$authTokenLifetime && !$authTokenMaxIdleTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
$whereClause = array(
|
||||
'isActive' => true
|
||||
);
|
||||
$whereClause = [
|
||||
'isActive' => true,
|
||||
];
|
||||
|
||||
if ($authTokenLifetime) {
|
||||
$dt = new \DateTime();
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify('-' . $authTokenLifetime . ' hours');
|
||||
|
||||
$authTokenLifetimeThreshold = $dt->format('Y-m-d H:i:s');
|
||||
|
||||
$whereClause['createdAt<'] = $authTokenLifetimeThreshold;
|
||||
}
|
||||
|
||||
if ($authTokenMaxIdleTime) {
|
||||
$dt = new \DateTime();
|
||||
$dt = new DateTime();
|
||||
|
||||
$dt->modify('-' . $authTokenMaxIdleTime . ' hours');
|
||||
|
||||
$authTokenMaxIdleTimeThreshold = $dt->format('Y-m-d H:i:s');
|
||||
|
||||
$whereClause['lastAccess<'] = $authTokenMaxIdleTimeThreshold;
|
||||
}
|
||||
|
||||
$tokenList = $this->getEntityManager()->getRepository('AuthToken')->where($whereClause)->limit(0, 500)->find();
|
||||
$tokenList = $this->entityManager
|
||||
->getRepository('AuthToken')
|
||||
->where($whereClause)
|
||||
->limit(0, 500)
|
||||
->find();
|
||||
|
||||
foreach ($tokenList as $token) {
|
||||
$token->set('isActive', false);
|
||||
$this->getEntityManager()->saveEntity($token);
|
||||
|
||||
$this->entityManager->saveEntity($token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
83
application/Espo/Classes/Jobs/CheckEmailAccounts.php
Normal file
83
application/Espo/Classes/Jobs/CheckEmailAccounts.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
use Espo\Services\EmailAccount as Service;
|
||||
|
||||
use Espo\Core\{
|
||||
Job\Job,
|
||||
Job\Job\Data,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use Throwable;
|
||||
|
||||
class CheckEmailAccounts implements Job
|
||||
{
|
||||
private $service;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(Service $service, EntityManager $entityManager)
|
||||
{
|
||||
$this->service = $service;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function run(Data $data): void
|
||||
{
|
||||
$targetId = $data->getTargetId();
|
||||
|
||||
if (!$targetId) {
|
||||
throw new Error("No target.");
|
||||
}
|
||||
|
||||
$entity = $this->entityManager->getEntity('EmailAccount', $targetId);
|
||||
|
||||
if (!$entity) {
|
||||
throw new Error("Job CheckEmailAccounts '{$targetId}': EmailAccount does not exist.", -1);
|
||||
}
|
||||
|
||||
if ($entity->get('status') !== 'Active') {
|
||||
throw new Error("Job CheckEmailAccounts '{$targetId}': EmailAccount is not active.", -1);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->service->fetchFromMailServer($entity);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
throw new Error(
|
||||
'Job CheckEmailAccounts ' . $entity->getId() . ': [' . $e->getCode() . '] ' .$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
application/Espo/Classes/Jobs/CheckInboundEmails.php
Normal file
83
application/Espo/Classes/Jobs/CheckInboundEmails.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
use Espo\Services\InboundEmail as Service;
|
||||
|
||||
use Espo\Core\{
|
||||
Job\Job,
|
||||
Job\Job\Data,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use Throwable;
|
||||
|
||||
class CheckInboundEmails implements Job
|
||||
{
|
||||
private $service;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(Service $service, EntityManager $entityManager)
|
||||
{
|
||||
$this->service = $service;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function run(Data $data): void
|
||||
{
|
||||
$targetId = $data->getTargetId();
|
||||
|
||||
if (!$targetId) {
|
||||
throw new Error("No target.");
|
||||
}
|
||||
|
||||
$entity = $this->entityManager->getEntity('InboundEmail', $targetId);
|
||||
|
||||
if (!$entity) {
|
||||
throw new Error("Job CheckInboundEmails '{$targetId}': InboundEmail does not exist.", -1);
|
||||
}
|
||||
|
||||
if ($entity->get('status') !== 'Active') {
|
||||
throw new Error("Job CheckInboundEmails '{$targetId}': InboundEmail is not active.", -1);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->service->fetchFromMailServer($entity);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
throw new Error(
|
||||
'Job CheckInboundEmails ' . $entity->getId() . ': [' . $e->getCode() . '] ' .$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,28 +27,27 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Jobs;
|
||||
|
||||
use Espo\Core\Exceptions;
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
class CheckNewExtensionVersion extends CheckNewVersion
|
||||
{
|
||||
public function run()
|
||||
public function run(): void
|
||||
{
|
||||
if (!$this->getConfig()->get('adminNotifications') || !$this->getConfig()->get('adminNotificationsNewExtensionVersion')) {
|
||||
return true;
|
||||
if (
|
||||
!$this->config->get('adminNotifications') ||
|
||||
!$this->config->get('adminNotificationsNewExtensionVersion')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$job = $this->getEntityManager()->getEntity('Job');
|
||||
$job->set(array(
|
||||
$job = $this->entityManager->getEntity('Job');
|
||||
$job->set([
|
||||
'name' => 'Check for new versions of installed extensions (job)',
|
||||
'serviceName' => 'AdminNotifications',
|
||||
'methodName' => 'jobCheckNewExtensionVersion',
|
||||
'executeTime' => $this->getRunTime()
|
||||
));
|
||||
'executeTime' => $this->getRunTime(),
|
||||
]);
|
||||
|
||||
$this->getEntityManager()->saveEntity($job);
|
||||
|
||||
return true;
|
||||
$this->entityManager->saveEntity($job);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,29 +27,47 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Jobs;
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
use Espo\Core\Exceptions;
|
||||
use Espo\Core\{
|
||||
Utils\Config,
|
||||
ORM\EntityManager,
|
||||
Job\JobDataLess,
|
||||
};
|
||||
|
||||
class CheckNewVersion extends \Espo\Core\Jobs\Base
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
|
||||
class CheckNewVersion implements JobDataLess
|
||||
{
|
||||
public function run()
|
||||
protected $config;
|
||||
|
||||
protected $entityManager;
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
if (!$this->getConfig()->get('adminNotifications') || !$this->getConfig()->get('adminNotificationsNewVersion')) {
|
||||
return true;
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
if (!$this->config->get('adminNotifications') || !$this->config->get('adminNotificationsNewVersion')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$job = $this->getEntityManager()->getEntity('Job');
|
||||
$job->set(array(
|
||||
$job = $this->entityManager->getEntity('Job');
|
||||
|
||||
$job->set([
|
||||
'name' => 'Check for New Version (job)',
|
||||
'serviceName' => 'AdminNotifications',
|
||||
'methodName' => 'jobCheckNewVersion',
|
||||
'executeTime' => $this->getRunTime()
|
||||
));
|
||||
'executeTime' => $this->getRunTime(),
|
||||
]);
|
||||
|
||||
$this->getEntityManager()->saveEntity($job);
|
||||
$this->entityManager->saveEntity($job);
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
protected function getRunTime()
|
||||
@@ -57,16 +75,26 @@ class CheckNewVersion extends \Espo\Core\Jobs\Base
|
||||
$hour = rand(0, 4);
|
||||
$minute = rand(0, 59);
|
||||
|
||||
$nextDay = new \DateTime('+ 1 day');
|
||||
$nextDay = new DateTime('+ 1 day');
|
||||
$time = $nextDay->format('Y-m-d') . ' ' . $hour . ':' . $minute . ':00';
|
||||
|
||||
$timeZone = $this->getConfig()->get('timeZone');
|
||||
$timeZone = $this->config->get('timeZone');
|
||||
|
||||
if (empty($timeZone)) {
|
||||
$timeZone = 'UTC';
|
||||
}
|
||||
|
||||
$datetime = new \DateTime($time, new \DateTimeZone($timeZone));
|
||||
$datetime = new DateTime($time, new DateTimeZone($timeZone));
|
||||
|
||||
return $datetime->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
return $datetime->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For backward compatibility.
|
||||
* @deprecated
|
||||
*/
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->entityManager;
|
||||
}
|
||||
}
|
||||
751
application/Espo/Classes/Jobs/Cleanup.php
Normal file
751
application/Espo/Classes/Jobs/Cleanup.php
Normal file
@@ -0,0 +1,751 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
use Espo\Core\Record\ServiceContainer;
|
||||
|
||||
use Espo\Core\{
|
||||
Utils\Config,
|
||||
ORM\EntityManager,
|
||||
Job\JobDataLess,
|
||||
Utils\Metadata,
|
||||
Utils\File\Manager as FileManager,
|
||||
InjectableFactory,
|
||||
Select\SelectBuilderFactory,
|
||||
Utils\Log,
|
||||
};
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use DateTime;
|
||||
use SplFileInfo;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
|
||||
class Cleanup implements JobDataLess
|
||||
{
|
||||
private $cleanupJobPeriod = '10 days';
|
||||
|
||||
private $cleanupActionHistoryPeriod = '15 days';
|
||||
|
||||
private $cleanupAuthTokenPeriod = '1 month';
|
||||
|
||||
private $cleanupAuthLogPeriod = '2 months';
|
||||
|
||||
private $cleanupNotificationsPeriod = '2 months';
|
||||
|
||||
private $cleanupAttachmentsPeriod = '15 days';
|
||||
|
||||
private $cleanupAttachmentsFromPeriod = '3 months';
|
||||
|
||||
private $cleanupBackupPeriod = '2 month';
|
||||
|
||||
private $cleanupDeletedRecordsPeriod = '3 months';
|
||||
|
||||
private $config;
|
||||
|
||||
private $entityManager;
|
||||
|
||||
private $metadata;
|
||||
|
||||
private $fileManager;
|
||||
|
||||
private $injectableFactory;
|
||||
|
||||
private $selectBuilderFactory;
|
||||
|
||||
private $recordServiceContainer;
|
||||
|
||||
private $log;
|
||||
|
||||
public function __construct(
|
||||
Config $config,
|
||||
EntityManager $entityManager,
|
||||
Metadata $metadata,
|
||||
FileManager $fileManager,
|
||||
InjectableFactory $injectableFactory,
|
||||
SelectBuilderFactory $selectBuilderFactory,
|
||||
ServiceContainer $recordServiceContainer,
|
||||
Log $log
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
$this->injectableFactory = $injectableFactory;
|
||||
$this->selectBuilderFactory = $selectBuilderFactory;
|
||||
$this->recordServiceContainer = $recordServiceContainer;
|
||||
$this->log = $log;
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->cleanupJobs();
|
||||
$this->cleanupScheduledJobLog();
|
||||
$this->cleanupAttachments();
|
||||
$this->cleanupEmails();
|
||||
$this->cleanupNotifications();
|
||||
$this->cleanupActionHistory();
|
||||
$this->cleanupAuthToken();
|
||||
$this->cleanupAuthLog();
|
||||
$this->cleanupUpgradeBackups();
|
||||
$this->cleanupUniqueIds();
|
||||
$this->cleanupDeletedRecords();
|
||||
|
||||
$items = $this->metadata->get(['app', 'cleanup']) ?? [];
|
||||
|
||||
usort($items, function ($a, $b) {
|
||||
$o1 = $a['order'] ?? 0;
|
||||
$o2 = $b['order'] ?? 0;
|
||||
|
||||
return $o1 <=> $o2;
|
||||
});
|
||||
|
||||
$injectableFactory = $this->injectableFactory;
|
||||
|
||||
foreach ($items as $name => $item) {
|
||||
try {
|
||||
$className = $item['className'];
|
||||
|
||||
$injectableFactory->create($className)->process();
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->log->error("Cleanup: {$name}: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupJobs(): void
|
||||
{
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from('Job')
|
||||
->where([
|
||||
'DATE:modifiedAt<' => $this->getCleanupJobFromDate(),
|
||||
'status!=' => 'Pending',
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from('Job')
|
||||
->where([
|
||||
'DATE:modifiedAt<' => $this->getCleanupJobFromDate(),
|
||||
'status=' => 'Pending',
|
||||
'deleted' => true,
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
|
||||
private function cleanupUniqueIds(): void
|
||||
{
|
||||
$delete = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('UniqueId')
|
||||
->where([
|
||||
'terminateAt!=' => null,
|
||||
'terminateAt<' => date('Y-m-d H:i:s')
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
|
||||
private function cleanupScheduledJobLog(): void
|
||||
{
|
||||
$scheduledJobList = $this->entityManager->getRepository('ScheduledJob')
|
||||
->select(['id'])
|
||||
->find();
|
||||
|
||||
foreach ($scheduledJobList as $scheduledJob) {
|
||||
$scheduledJobId = $scheduledJob->get('id');
|
||||
|
||||
$ignoreLogRecordList = $this->entityManager->getRepository('ScheduledJobLogRecord')
|
||||
->select(['id'])
|
||||
->where([
|
||||
'scheduledJobId' => $scheduledJobId,
|
||||
])
|
||||
->order('createdAt', 'DESC')
|
||||
->limit(0, 10)
|
||||
->find();
|
||||
|
||||
if (!count($ignoreLogRecordList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ignoreIdList = [];
|
||||
foreach ($ignoreLogRecordList as $logRecord) {
|
||||
$ignoreIdList[] = $logRecord->get('id');
|
||||
}
|
||||
|
||||
$delete = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('ScheduledJobLogRecord')
|
||||
->where([
|
||||
'scheduledJobId' => $scheduledJobId,
|
||||
'DATE:createdAt<' => $this->getCleanupJobFromDate(),
|
||||
'id!=' => $ignoreIdList,
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupActionHistory(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupActionHistoryPeriod', $this->cleanupActionHistoryPeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
|
||||
$datetime->modify($period);
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from('ActionHistoryRecord')
|
||||
->where([
|
||||
'DATE:createdAt<' => $datetime->format('Y-m-d'),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
|
||||
private function cleanupAuthToken(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupAuthTokenPeriod', $this->cleanupAuthTokenPeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
$delete = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('AuthToken')
|
||||
->where([
|
||||
'DATE:modifiedAt<' => $datetime->format('Y-m-d'),
|
||||
'isActive' => false,
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
|
||||
private function cleanupAuthLog(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupAuthLogPeriod', $this->cleanupAuthLogPeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
|
||||
$datetime->modify($period);
|
||||
|
||||
$delete = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->delete()
|
||||
->from('AuthLogRecord')
|
||||
->where([
|
||||
'DATE:createdAt<' => $datetime->format('Y-m-d'),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
|
||||
private function getCleanupJobFromDate(): string
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupJobPeriod', $this->cleanupJobPeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
return $datetime->format('Y-m-d');
|
||||
}
|
||||
|
||||
private function cleanupAttachments(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupAttachmentsPeriod', $this->cleanupAttachmentsPeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
|
||||
$datetime->modify($period);
|
||||
|
||||
$collection = $this->entityManager
|
||||
->getRepository('Attachment')
|
||||
->where([
|
||||
'OR' => [
|
||||
[
|
||||
'role' => ['Export File', 'Mail Merge', 'Mass Pdf']
|
||||
]
|
||||
],
|
||||
'createdAt<' => $datetime->format('Y-m-d H:i:s'),
|
||||
])
|
||||
->limit(0, 5000)
|
||||
->find();
|
||||
|
||||
foreach ($collection as $entity) {
|
||||
$this->entityManager->removeEntity($entity);
|
||||
}
|
||||
|
||||
if ($this->config->get('cleanupOrphanAttachments')) {
|
||||
$orphanQueryBuilder = $this->selectBuilderFactory
|
||||
->create()
|
||||
->from('Attachment')
|
||||
->withPrimaryFilter('orphan')
|
||||
->buildQueryBuilder();
|
||||
|
||||
$orphanQueryBuilder->where([
|
||||
'createdAt<' => $datetime->format('Y-m-d H:i:s'),
|
||||
'createdAt>' => '2018-01-01 00:00:00',
|
||||
]);
|
||||
|
||||
$collection = $this->entityManager
|
||||
->getRepository('Attachment')
|
||||
->clone($orphanQueryBuilder->build())
|
||||
->limit(0, 5000)
|
||||
->find();
|
||||
|
||||
foreach ($collection as $entity) {
|
||||
$this->entityManager->removeEntity($entity);
|
||||
}
|
||||
}
|
||||
|
||||
$fromPeriod = '-' . $this->config->get('cleanupAttachmentsFromPeriod', $this->cleanupAttachmentsFromPeriod);
|
||||
|
||||
$datetimeFrom = new DateTime();
|
||||
|
||||
$datetimeFrom->modify($fromPeriod);
|
||||
|
||||
$scopeList = array_keys($this->metadata->get(['scopes']));
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
if (!$this->metadata->get(['scopes', $scope, 'entity'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->metadata->get(['scopes', $scope, 'object']) && $scope !== 'Note') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->metadata->get(['entityDefs', $scope, 'fields', 'modifiedAt'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hasAttachmentField = false;
|
||||
|
||||
if ($scope === 'Note') {
|
||||
$hasAttachmentField = true;
|
||||
}
|
||||
|
||||
if (!$hasAttachmentField) {
|
||||
foreach ($this->metadata->get(['entityDefs', $scope, 'fields']) as $field => $defs) {
|
||||
if (empty($defs['type'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($defs['type'], ['file', 'image', 'attachmentMultiple'])) {
|
||||
$hasAttachmentField = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasAttachmentField) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->entityManager->hasRepository($scope)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$repository = $this->entityManager->getRepository($scope);
|
||||
|
||||
if (!method_exists($repository, 'find')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!method_exists($repository, 'clone')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select()
|
||||
->from($scope)
|
||||
->withDeleted()
|
||||
->where([
|
||||
'deleted' => 1,
|
||||
'modifiedAt<' => $datetime->format('Y-m-d H:i:s'),
|
||||
'modifiedAt>' => $datetimeFrom->format('Y-m-d H:i:s'),
|
||||
])
|
||||
->build();
|
||||
|
||||
$deletedEntityList = $repository
|
||||
->clone($query)
|
||||
->find();
|
||||
|
||||
foreach ($deletedEntityList as $deletedEntity) {
|
||||
$attachmentToRemoveList = $this->entityManager
|
||||
->getRepository('Attachment')
|
||||
->where([
|
||||
'OR' => [
|
||||
[
|
||||
'relatedType' => $scope,
|
||||
'relatedId' => $deletedEntity->id,
|
||||
],
|
||||
[
|
||||
'parentType' => $scope,
|
||||
'parentId' => $deletedEntity->id,
|
||||
]
|
||||
]
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($attachmentToRemoveList as $attachmentToRemove) {
|
||||
$this->entityManager->removeEntity($attachmentToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from('Attachment')
|
||||
->where([
|
||||
'deleted' => true,
|
||||
'createdAt<' => $datetime->format('Y-m-d H:i:s'),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
|
||||
private function cleanupEmails(): void
|
||||
{
|
||||
$dateBefore = date('Y-m-d H:i:s', time() - 3600 * 24 * 20);
|
||||
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select()
|
||||
->from('Email')
|
||||
->withDeleted()
|
||||
->build();
|
||||
|
||||
$emailList = $this->entityManager
|
||||
->getRepository('Email')
|
||||
->clone($query)
|
||||
->select(['id'])
|
||||
->where([
|
||||
'createdAt<' => $dateBefore,
|
||||
'deleted' => true,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($emailList as $email) {
|
||||
$id = $email->get('id');
|
||||
|
||||
$attachments = $this->entityManager
|
||||
->getRepository('Attachment')
|
||||
->where([
|
||||
'parentId' => $id,
|
||||
'parentType' => 'Email'
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$this->entityManager->removeEntity($attachment);
|
||||
}
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from('Email')
|
||||
->where([
|
||||
'deleted' => true,
|
||||
'id' => $id,
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from('EmailUser')
|
||||
->where([
|
||||
'emailId' => $id,
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupNotifications(): void
|
||||
{
|
||||
$period = '-' . $this->config->get('cleanupNotificationsPeriod', $this->cleanupNotificationsPeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
$datetime->modify($period);
|
||||
|
||||
$notificationList = $this->entityManager->getRepository('Notification')
|
||||
->where([
|
||||
'DATE:createdAt<' => $datetime->format('Y-m-d'),
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($notificationList as $notification) {
|
||||
$this->entityManager->getRepository('Notification')->deleteFromDb($notification->get('id'));
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupUpgradeBackups(): void
|
||||
{
|
||||
$path = 'data/.backup/upgrades';
|
||||
|
||||
$datetime = new DateTime('-' . $this->cleanupBackupPeriod);
|
||||
|
||||
if (file_exists($path)) {
|
||||
$fileManager = $this->fileManager;
|
||||
$fileList = $fileManager->getFileList($path, false, '', false);
|
||||
|
||||
foreach ($fileList as $dirName) {
|
||||
$dirPath = $path . '/' . $dirName;
|
||||
|
||||
$info = new SplFileInfo($dirPath);
|
||||
|
||||
if ($datetime->getTimestamp() > $info->getMTime()) {
|
||||
$fileManager->removeInDir($dirPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupDeletedEntity(Entity $entity): void
|
||||
{
|
||||
$scope = $entity->getEntityType();
|
||||
|
||||
if (!$entity->get('deleted')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$repository = $this->entityManager->getRepository($scope);
|
||||
|
||||
$repository->deleteFromDb($entity->id);
|
||||
|
||||
$query = $this->entityManager->getQueryComposer();
|
||||
|
||||
foreach ($entity->getRelationList() as $relation) {
|
||||
if ($entity->getRelationType($relation) !== Entity::MANY_MANY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$relationName = $entity->getRelationParam($relation, 'relationName');
|
||||
|
||||
if (!$relationName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$midKey = $entity->getRelationParam($relation, 'midKeys')[0];
|
||||
|
||||
if (!$midKey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$where = [
|
||||
$midKey => $entity->id,
|
||||
];
|
||||
|
||||
$conditions = $entity->getRelationParam($relation, 'conditions') ?? [];
|
||||
|
||||
foreach ($conditions as $key => $value) {
|
||||
$where[$key] = $value;
|
||||
}
|
||||
|
||||
if (empty($where)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$relationEntityType = ucfirst($relationName);
|
||||
|
||||
if (!$this->entityManager->hasRepository($relationEntityType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()->delete()
|
||||
->from($relationEntityType)
|
||||
->where($where)
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->log->error("Cleanup: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select()
|
||||
->from('Note')
|
||||
->withDeleted()
|
||||
->build();
|
||||
|
||||
$noteList = $this->entityManager
|
||||
->getRepository('Note')
|
||||
->clone($query)
|
||||
->where([
|
||||
'OR' => [
|
||||
[
|
||||
'relatedType' => $scope,
|
||||
'relatedId' => $entity->id,
|
||||
],
|
||||
[
|
||||
'parentType' => $scope,
|
||||
'parentId' => $entity->id,
|
||||
]
|
||||
]
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($noteList as $note) {
|
||||
$this->entityManager->removeEntity($note);
|
||||
|
||||
$note->set('deleted', true);
|
||||
|
||||
$this->cleanupDeletedEntity($note);
|
||||
}
|
||||
|
||||
if ($scope === 'Note') {
|
||||
$attachmentList = $this->entityManager
|
||||
->getRepository('Attachment')
|
||||
->where([
|
||||
'parentId' => $entity->id,
|
||||
'parentType' => 'Note',
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($attachmentList as $attachment) {
|
||||
$this->entityManager->removeEntity($attachment);
|
||||
$this->entityManager->getRepository('Attachment')->deleteFromDb($attachment->id);
|
||||
}
|
||||
}
|
||||
|
||||
$arrayValueList = $this->entityManager
|
||||
->getRepository('ArrayValue')
|
||||
->where([
|
||||
'entityType' => $entity->getEntityType(),
|
||||
'entityId' => $entity->id,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($arrayValueList as $arrayValue) {
|
||||
$this->entityManager->getRepository('ArrayValue')->deleteFromDb($arrayValue->id);
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanupDeletedRecords(): void
|
||||
{
|
||||
if (!$this->config->get('cleanupDeletedRecords')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$period = '-' . $this->config->get('cleanupDeletedRecordsPeriod', $this->cleanupDeletedRecordsPeriod);
|
||||
|
||||
$datetime = new DateTime($period);
|
||||
|
||||
$scopeList = array_keys($this->metadata->get(['scopes']));
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
if (!$this->metadata->get(['scopes', $scope, 'entity'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($scope === 'Attachment') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->entityManager->hasRepository($scope)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$repository = $this->entityManager->getRepository($scope);
|
||||
|
||||
if (!$repository) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!method_exists($repository, 'find')) continue;
|
||||
if (!method_exists($repository, 'clone')) continue;
|
||||
if (!method_exists($repository, 'where')) continue;
|
||||
if (!method_exists($repository, 'select')) continue;
|
||||
if (!method_exists($repository, 'deleteFromDb')) continue;
|
||||
|
||||
$hasCleanupMethod = false;
|
||||
|
||||
$service = $this->recordServiceContainer->get($scope);
|
||||
|
||||
if (method_exists($service, 'cleanup')) {
|
||||
$hasCleanupMethod = true;
|
||||
}
|
||||
|
||||
$whereClause = [
|
||||
'deleted' => 1,
|
||||
];
|
||||
|
||||
if ($this->metadata->get(['entityDefs', $scope, 'fields', 'modifiedAt'])) {
|
||||
$whereClause['modifiedAt<'] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
else if ($this->metadata->get(['entityDefs', $scope, 'fields', 'createdAt'])) {
|
||||
$whereClause['createdAt<'] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select()
|
||||
->from($scope)
|
||||
->withDeleted()
|
||||
->build();
|
||||
|
||||
$deletedEntityList = $repository
|
||||
->clone($query)
|
||||
->select(['id', 'deleted'])
|
||||
->where($whereClause)
|
||||
->find();
|
||||
|
||||
foreach ($deletedEntityList as $entity) {
|
||||
if ($hasCleanupMethod) {
|
||||
try {
|
||||
$service->cleanup($entity->id);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->log->error("Cleanup job: Cleanup scope {$scope}: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->cleanupDeletedEntity($entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
@@ -27,12 +27,11 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Jobs;
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
class Dummy extends \Espo\Core\Jobs\Base
|
||||
use Espo\Core\Job\JobDataLess;
|
||||
|
||||
class Dummy implements JobDataLess
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
public function run(): void {}
|
||||
}
|
||||
50
application/Espo/Classes/Jobs/ProcessWebhookQueue.php
Normal file
50
application/Espo/Classes/Jobs/ProcessWebhookQueue.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Jobs;
|
||||
|
||||
use Espo\Core\{
|
||||
Job\JobDataLess,
|
||||
Webhook\Queue,
|
||||
};
|
||||
|
||||
class ProcessWebhookQueue implements JobDataLess
|
||||
{
|
||||
private $queue;
|
||||
|
||||
public function __construct(Queue $queue)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->queue->process();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user