mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-09 13:37:00 +00:00
Compare commits
1242 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
66fc4c2294 | ||
|
|
a21e4b836d | ||
|
|
163d51770d | ||
|
|
364a5c50f0 | ||
|
|
581f09eb9b | ||
|
|
e80269b61c | ||
|
|
2c4d5fb0f8 | ||
|
|
1fe222852a | ||
|
|
60ae87a3cb | ||
|
|
4aba2aab4c | ||
|
|
8c03b0a6cd | ||
|
|
e87fda3f3a | ||
|
|
4cabd6c2f1 | ||
|
|
ca3d10e7a2 | ||
|
|
e4cb9071d0 | ||
|
|
2b2777b3da | ||
|
|
83fd96a876 | ||
|
|
c1b1eaf847 | ||
|
|
f63cc22f44 | ||
|
|
3da1632e4b | ||
|
|
0bf4624839 | ||
|
|
0d38dfb385 | ||
|
|
46d9dd7bea | ||
|
|
4fa562a283 | ||
|
|
74c142a1ac | ||
|
|
4433325abb | ||
|
|
f2e5197568 | ||
|
|
5deefc5f35 | ||
|
|
506f7cf410 | ||
|
|
a5cec0370e | ||
|
|
2e92adff81 | ||
|
|
1e3a3b909b | ||
|
|
e4237abdbf | ||
|
|
20b6dbe5ac |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,6 +4,7 @@
|
||||
/data/preferences/*
|
||||
/data/.backup/*
|
||||
/data/config.php
|
||||
/data/tmp/*
|
||||
/build
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
@@ -13,6 +14,7 @@ npm-debug.log
|
||||
/tests/unit/testData/cache/*
|
||||
!/tests/unit/testData/cache/.data
|
||||
/tests/integration/config.php
|
||||
.phpunit.result.cache
|
||||
composer.phar
|
||||
vendor/
|
||||
/custom/Espo/Custom/*
|
||||
|
||||
@@ -20,5 +20,5 @@ DirectoryIndex index.php index.html
|
||||
|
||||
RewriteRule .* - [E=HTTP_ESPO_CGI_AUTH:%{HTTP:Authorization}]
|
||||
|
||||
RewriteRule reset/?$ reset.html [QSA,L]
|
||||
RewriteRule /?web\.config - [F]
|
||||
</IfModule>
|
||||
52
Gruntfile.js
52
Gruntfile.js
@@ -21,10 +21,11 @@
|
||||
|
||||
/**
|
||||
* * `grunt` - full build
|
||||
* * `grunt dev` - build only items needed for development
|
||||
* * `grunt offline` - skips *composer install*
|
||||
* * `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 tests` - build and run tests
|
||||
* * `grant test` - build for test running
|
||||
* * `grant run-tests` - build and run unit and integratino tests
|
||||
*/
|
||||
|
||||
module.exports = function (grunt) {
|
||||
@@ -48,6 +49,7 @@ module.exports = function (grunt) {
|
||||
'client/lib/bull.js',
|
||||
'client/lib/marked.min.js',
|
||||
'client/lib/autobahn.js',
|
||||
'client/lib/gridstack.all.js',
|
||||
|
||||
'client/src/namespace.js',
|
||||
'client/src/exceptions.js',
|
||||
@@ -210,6 +212,7 @@ module.exports = function (grunt) {
|
||||
'daemon.php',
|
||||
'rebuild.php',
|
||||
'clear_cache.php',
|
||||
'preload.php',
|
||||
'upgrade.php',
|
||||
'extension.php',
|
||||
'websocket.php',
|
||||
@@ -287,8 +290,8 @@ module.exports = function (grunt) {
|
||||
},
|
||||
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'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -300,19 +303,23 @@ module.exports = function (grunt) {
|
||||
});
|
||||
|
||||
grunt.registerTask("composer", function() {
|
||||
cp.execSync("composer install", {stdio: 'ignore'});
|
||||
cp.execSync("composer install --ignore-platform-reqs --no-dev", {stdio: 'ignore'});
|
||||
});
|
||||
|
||||
grunt.registerTask("composer-dev", function() {
|
||||
cp.execSync("composer install --ignore-platform-reqs", {stdio: 'ignore'});
|
||||
});
|
||||
|
||||
grunt.registerTask("upgrade", function() {
|
||||
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", function() {
|
||||
cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php ./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", function() {
|
||||
cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php ./tests/integration", {stdio: 'inherit'});
|
||||
});
|
||||
|
||||
grunt.registerTask("zip", function() {
|
||||
@@ -382,14 +389,29 @@ module.exports = function (grunt) {
|
||||
'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-dev',
|
||||
'unit-tests-run',
|
||||
]);
|
||||
|
||||
grunt.registerTask('run-integration-tests', [
|
||||
'test',
|
||||
'integration-tests-run',
|
||||
]);
|
||||
|
||||
grunt.registerTask('dev', [
|
||||
'composer',
|
||||
'composer-dev',
|
||||
'less',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test', [
|
||||
'composer-dev',
|
||||
'offline',
|
||||
]);
|
||||
};
|
||||
|
||||
72
README.md
72
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);
|
||||
* 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).
|
||||
|
||||
9
SECURITY.md
Normal file
9
SECURITY.md
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.
|
||||
@@ -9,4 +9,6 @@ RewriteEngine On
|
||||
RewriteRule .* - [E=HTTP_ESPO_CGI_AUTH:%{HTTP:Authorization}]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
|
||||
RewriteRule /?web\.config - [F]
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -29,5 +29,9 @@
|
||||
|
||||
require_once('../../bootstrap.php');
|
||||
|
||||
$app = new \Espo\Core\Application();
|
||||
$app->run();
|
||||
use Espo\Core\{
|
||||
Application,
|
||||
ApplicationRunners\Api,
|
||||
};
|
||||
|
||||
(new Application())->run(Api::class);
|
||||
|
||||
@@ -9,4 +9,6 @@ RewriteEngine On
|
||||
RewriteRule .* - [E=HTTP_ESPO_CGI_AUTH:%{HTTP:Authorization}]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
|
||||
RewriteRule /?web\.config - [F]
|
||||
@@ -29,11 +29,15 @@
|
||||
|
||||
require_once('../../../bootstrap.php');
|
||||
|
||||
use Espo\Core\{
|
||||
Portal\Application,
|
||||
Portal\ApplicationRunners\Api,
|
||||
};
|
||||
|
||||
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();
|
||||
(new Application($portalId))->run(Api::class);
|
||||
|
||||
@@ -29,14 +29,13 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class ActionHistoryRecord extends \Espo\Core\Acl\Base
|
||||
class ActionHistoryRecord extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
return $entity->get('userId') === $user->id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Attachment extends \Espo\Core\Acl\Base
|
||||
class Attachment extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
@@ -90,4 +90,3 @@ class Attachment extends \Espo\Core\Acl\Base
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Email extends \Espo\Core\Acl\Base
|
||||
class Email extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
protected $ownerUserIdAttribute = 'usersIds';
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class EmailAddress extends \Espo\Core\Acl\Base
|
||||
class EmailAddress extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkEditInEntity(EntityUser $user, Entity $entity, Entity $excludeEntity)
|
||||
{
|
||||
@@ -62,4 +62,3 @@ class EmailAddress extends \Espo\Core\Acl\Base
|
||||
return !$isFobidden;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class EmailFilter extends \Espo\Core\Acl\Base
|
||||
class EmailFilter extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
@@ -53,4 +53,3 @@ class EmailFilter extends \Espo\Core\Acl\Base
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,11 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Import extends \Espo\Core\Acl\Base
|
||||
class Import extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) return true;
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Note extends \Espo\Core\Acl\Base
|
||||
class Note extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
protected $deleteThresholdPeriod = '1 month';
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Notification extends \Espo\Core\Acl\Base
|
||||
class Notification extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
@@ -42,4 +42,3 @@ class Notification extends \Espo\Core\Acl\Base
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class PhoneNumber extends \Espo\Core\Acl\Base
|
||||
class PhoneNumber extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkEditInEntity(EntityUser $user, Entity $entity, Entity $excludeEntity)
|
||||
{
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class ScheduledJob extends \Espo\Core\Acl\Base
|
||||
class ScheduledJob extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkEntityRead(EntityUser $user, Entity $entity, $data)
|
||||
{
|
||||
@@ -58,4 +58,3 @@ class ScheduledJob extends \Espo\Core\Acl\Base
|
||||
return $this->checkEntity($user, $entity, $data, 'create');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,13 +29,15 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Team extends \Espo\Core\Acl\Base
|
||||
use Espo\Entities\User as UserEntity;
|
||||
|
||||
class Team extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkInTeam(\Espo\Entities\User $user, Entity $entity)
|
||||
public function checkInTeam(UserEntity $user, Entity $entity)
|
||||
{
|
||||
$userTeamIdList = $user->getLinkMultipleIdList('teams');
|
||||
return in_array($entity->id, $userTeamIdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
|
||||
class User extends \Espo\Core\Acl\Base
|
||||
class User extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkIsOwner(\Espo\Entities\User $user, Entity $entity)
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
return $user->id === $entity->id;
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Acl;
|
||||
|
||||
use \Espo\Entities\User as EntityUser;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User as EntityUser;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Webhook extends \Espo\Core\Acl\Base
|
||||
class Webhook extends \Espo\Core\Acl\Acl
|
||||
{
|
||||
public function checkIsOwner(EntityUser $user, Entity $entity)
|
||||
{
|
||||
|
||||
@@ -27,31 +27,44 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\AppParams;
|
||||
namespace Espo\Classes\AppParams;
|
||||
|
||||
class TemplateEntityTypeList extends \Espo\Core\Injectable
|
||||
use Espo\Core\{
|
||||
Acl,
|
||||
Select\SelectManagerFactory,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of entity types for which a PDF template exists.
|
||||
*/
|
||||
class TemplateEntityTypeList
|
||||
{
|
||||
protected function init()
|
||||
protected $acl;
|
||||
protected $selectManagerFactory;
|
||||
protected $entityManager;
|
||||
|
||||
public function __construct(Acl $acl, SelectManagerFactory $selectManagerFactory, EntityManager $entityManager)
|
||||
{
|
||||
$this->addDependency('acl');
|
||||
$this->addDependency('selectManagerFactory');
|
||||
$this->addDependency('entityManager');
|
||||
$this->acl = $acl;
|
||||
$this->selectManagerFactory = $selectManagerFactory;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function get()
|
||||
{
|
||||
if (!$this->getInjection('acl')->checkScope('Template')) {
|
||||
if (!$this->acl->checkScope('Template')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
|
||||
$selectManager = $this->getInjection('selectManagerFactory')->create('Template');
|
||||
$selectManager = $this->selectManagerFactory->create('Template');
|
||||
|
||||
$selectParams = $selectManager->getEmptySelectParams();
|
||||
$selectManager->applyAccess($selectParams);
|
||||
|
||||
$templateList = $this->getInjection('entityManager')->getRepository('Template')
|
||||
$templateList = $this->entityManager->getRepository('Template')
|
||||
->select(['entityType'])
|
||||
->groupBy(['entityType'])
|
||||
->find($selectParams);
|
||||
@@ -27,42 +27,44 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\Authentication;
|
||||
namespace Espo\Classes\Cleanup;
|
||||
|
||||
use \Espo\Core\Utils\Config;
|
||||
use \Espo\Core\ORM\EntityManager;
|
||||
use \Espo\Core\Utils\Auth;
|
||||
use Espo\Core\{
|
||||
Utils\Config,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
abstract class Base
|
||||
use DateTime;
|
||||
|
||||
class Reminders
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected $entityManager;
|
||||
|
||||
private $passwordHash;
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
protected $cleanupRemindersPeriod = '15 days';
|
||||
|
||||
protected function getEntityManager()
|
||||
public function process()
|
||||
{
|
||||
return $this->entityManager;
|
||||
}
|
||||
$period = '-' . $this->config->get('cleanupRemindersPeriod', $this->cleanupRemindersPeriod);
|
||||
|
||||
protected function getPasswordHash()
|
||||
{
|
||||
if (!isset($this->passwordHash)) {
|
||||
$this->passwordHash = new \Espo\Core\Utils\PasswordHash($this->config);
|
||||
}
|
||||
$dt = new DateTime();
|
||||
|
||||
return $this->passwordHash;
|
||||
$dt->modify($period);
|
||||
|
||||
$delete = $this->entityManager->getQueryBuilder()
|
||||
->delete()
|
||||
->from('Reminder')
|
||||
->where([
|
||||
'remindAt<' => $dt->format('Y-m-d'),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($delete);
|
||||
}
|
||||
}
|
||||
@@ -27,33 +27,63 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Cleanup;
|
||||
namespace Espo\Classes\Cleanup;
|
||||
|
||||
class WebhookQueue extends Base
|
||||
use Espo\Core\{
|
||||
Utils\Config,
|
||||
ORM\EntityManager,
|
||||
};
|
||||
|
||||
use DateTime;
|
||||
|
||||
class WebhookQueue
|
||||
{
|
||||
protected $cleanupWebhookQueuePeriod = '10 days';
|
||||
|
||||
protected $config;
|
||||
protected $entityManager;
|
||||
|
||||
public function __construct(Config $config, EntityManager $entityManager)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function process()
|
||||
{
|
||||
$pdo = $this->getEntityManager()->getPDO();
|
||||
$period = '-' . $this->config->get('cleanupWebhookQueuePeriod', $this->cleanupWebhookQueuePeriod);
|
||||
|
||||
$datetime = new DateTime();
|
||||
|
||||
$period = '-' . $this->getConfig()->get('cleanupWebhookQueuePeriod', $this->cleanupWebhookQueuePeriod);
|
||||
$datetime = new \DateTime();
|
||||
$datetime->modify($period);
|
||||
$from = $datetime->format('Y-m-d H:i:s');
|
||||
|
||||
$query = "
|
||||
DELETE FROM `webhook_queue_item`
|
||||
WHERE
|
||||
DATE(created_at) < ".$pdo->quote($from)." AND
|
||||
(status <> 'Pending' OR deleted = 1)
|
||||
";
|
||||
$pdo->query($query);
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->delete()
|
||||
->from('WebhookQueueItem')
|
||||
->where([
|
||||
'DATE:(createdAt)<' => $from,
|
||||
'OR' => [
|
||||
'status!=' => 'Pending',
|
||||
'deleted' => true,
|
||||
],
|
||||
])
|
||||
->build();
|
||||
|
||||
$query = "
|
||||
DELETE FROM `webhook_event_queue_item`
|
||||
WHERE DATE(created_at) < ".$pdo->quote($from)." AND (is_processed = 1 OR deleted = 1)
|
||||
";
|
||||
$pdo->query($query);
|
||||
$this->entityManager->getQueryExecutor()->execute($query);
|
||||
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->delete()
|
||||
->from('WebhookEventQueueItem')
|
||||
->where([
|
||||
'DATE:(createdAt)<' => $from,
|
||||
'OR' => [
|
||||
'isProcessed' => true,
|
||||
'deleted' => true,
|
||||
],
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query);
|
||||
}
|
||||
}
|
||||
138
application/Espo/Classes/ConsoleCommands/Import.php
Normal file
138
application/Espo/Classes/ConsoleCommands/Import.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?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\Classes\ConsoleCommands;
|
||||
|
||||
use Espo\Core\{
|
||||
ServiceFactory,
|
||||
Console\Commands\Command,
|
||||
};
|
||||
|
||||
use Throwable;
|
||||
|
||||
class Import implements Command
|
||||
{
|
||||
protected $serviceFactory;
|
||||
|
||||
public function __construct(ServiceFactory $serviceFactory)
|
||||
{
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
}
|
||||
|
||||
public function run(array $options, array $flagList)
|
||||
{
|
||||
$id = $options['id'] ?? null;
|
||||
$filePath = $options['file'] ?? null;
|
||||
$paramsId = $options['paramsId'] ?? null;
|
||||
|
||||
$service = $this->serviceFactory->create('Import');
|
||||
|
||||
$forceResume = in_array('resume', $flagList);
|
||||
$revert = in_array('revert', $flagList);
|
||||
|
||||
if (!$id && $filePath) {
|
||||
if (!$paramsId) {
|
||||
$this->out("You need to specify --params-id option.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file_exists($filePath)) {
|
||||
$this->out("File not found.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$contents = file_get_contents($filePath);
|
||||
|
||||
try {
|
||||
$result = $service->importFileWithParamsId($contents, $paramsId);
|
||||
|
||||
$resultId = $result->id;
|
||||
$countCreated = $result->countCreated;
|
||||
$countUpdated = $result->countUpdated;
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->out("Error occured: ".$e->getMessage()."\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->out("Finished. Import ID: {$resultId}. Created: {$countCreated}. Updated: {$countUpdated}.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($id && $revert) {
|
||||
$this->out("Reverting import...\n");
|
||||
|
||||
try {
|
||||
$service->revert($id);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->out("Error occured: " . $e->getMessage() . "\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->out("Finished.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
$this->out("Running import, this may take a while...\n");
|
||||
|
||||
try {
|
||||
$result = $service->importById($id, true, $forceResume);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->out("Error occured: " . $e->getMessage() . "\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$countCreated = $result->countCreated;
|
||||
$countUpdated = $result->countUpdated;
|
||||
|
||||
$this->out("Finished. Created: {$countCreated}. Updated: {$countUpdated}.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->out("Not enough params passed.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
protected function out($string)
|
||||
{
|
||||
fwrite(\STDOUT, $string);
|
||||
}
|
||||
}
|
||||
@@ -27,13 +27,15 @@
|
||||
* 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;
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
@@ -27,16 +27,18 @@
|
||||
* 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 ArrayType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : 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, $validationValue, $data) : bool
|
||||
{
|
||||
if (!$this->isNotEmpty($entity, $field)) return true;
|
||||
$list = $entity->get($field);
|
||||
@@ -44,14 +46,16 @@ class ArrayType extends BaseType
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkArray(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkArray(Entity $entity, string $field, $validationValue, $data) : 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, $field)
|
||||
{
|
||||
if (!$entity->has($field) || $entity->get($field) === null) return false;
|
||||
$list = $entity->get($field);
|
||||
@@ -27,33 +27,33 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FieldValidators;
|
||||
namespace Espo\Classes\FieldValidators;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
Utils\Metadata,
|
||||
Utils\FieldUtil,
|
||||
};
|
||||
|
||||
class BaseType
|
||||
{
|
||||
private $metadata;
|
||||
private $fieldManagerUtil;
|
||||
protected $metadata;
|
||||
protected $fieldUtil;
|
||||
|
||||
public function __construct(\Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\FieldManagerUtil $fieldManagerUtil)
|
||||
public function __construct(Metadata $metadata, FieldUtil $fieldUtil)
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
$this->fieldManagerUtil = $fieldManagerUtil;
|
||||
$this->fieldUtil = $fieldUtil;
|
||||
}
|
||||
|
||||
protected function getActualAttributeList(Entity $entity, string $field) : array
|
||||
{
|
||||
return $this->getFieldManagerUtil()->getActualAttributeList($entity->getEntityType(), $field);
|
||||
return $this->fieldUtil->getActualAttributeList($entity->getEntityType(), $field);
|
||||
}
|
||||
|
||||
protected function getMetadata() : \Espo\Core\Utils\Metadata
|
||||
protected function getMetadata() : Metadata
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function getFieldManagerUtil() : \Espo\Core\Utils\FieldManagerUtil
|
||||
{
|
||||
return $this->fieldManagerUtil;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
@@ -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, $field)
|
||||
{
|
||||
return
|
||||
$entity->has($field) && $entity->get($field) !== null &&
|
||||
@@ -27,16 +27,18 @@
|
||||
* 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 DateType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -27,16 +27,18 @@
|
||||
* 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, $validationValue, $data) : bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
if ($entity->has($field) && $entity->get($field) !== null) return true;
|
||||
if ($entity->has($field . 'Date') && $entity->get($field . 'Date') !== null) return true;
|
||||
@@ -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
|
||||
{
|
||||
@@ -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 EmailType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) return true;
|
||||
|
||||
@@ -45,7 +47,7 @@ class EmailType extends BaseType
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEmailAddress(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkEmailAddress(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) {
|
||||
$address = $entity->get($field);
|
||||
@@ -68,7 +70,7 @@ class EmailType extends BaseType
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -27,16 +27,18 @@
|
||||
* 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 EnumType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
return $this->isNotEmpty($entity, $field);
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -27,30 +27,32 @@
|
||||
* 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 IntType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : 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, $data) : bool
|
||||
{
|
||||
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, $data) : bool
|
||||
{
|
||||
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, $field)
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -27,18 +27,20 @@
|
||||
* 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 JsonArrayType extends BaseType
|
||||
{
|
||||
public function checkArray(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkArray(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
if (!$entity->has($field) || $entity->get($field) === null) return true;
|
||||
|
||||
return is_array($entity->get($field));
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
if (!$entity->has($field) || $entity->get($field) === null) return false;
|
||||
$list = $entity->get($field);
|
||||
@@ -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 LinkMultipleType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
return count($entity->getLinkMultipleIdList($field)) > 0;
|
||||
}
|
||||
@@ -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 LinkParentType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
$idAttribute = $field . 'Id';
|
||||
$typeAttribute = $field . 'Type';
|
||||
@@ -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 LinkType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
$idAttribute = $field . 'Id';
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -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 PersonNameType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
$isEmpty = true;
|
||||
foreach ($this->getActualAttributeList($entity, $field) as $attribute) {
|
||||
@@ -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 PhoneType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) return true;
|
||||
|
||||
@@ -45,7 +47,7 @@ class PhoneType extends BaseType
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null;
|
||||
}
|
||||
@@ -27,16 +27,18 @@
|
||||
* 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 VarcharType extends BaseType
|
||||
{
|
||||
public function checkRequired(\Espo\ORM\Entity $entity, string $field, $validationValue, $data) : bool
|
||||
public function checkRequired(Entity $entity, string $field, $validationValue, $data) : 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, $validationValue, $data) : bool
|
||||
{
|
||||
if ($this->isNotEmpty($entity, $field)) {
|
||||
$value = $entity->get($field);
|
||||
@@ -47,7 +49,7 @@ class VarcharType extends BaseType
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isNotEmpty(\Espo\ORM\Entity $entity, $field)
|
||||
protected function isNotEmpty(Entity $entity, $field)
|
||||
{
|
||||
return $entity->has($field) && $entity->get($field) !== '' && $entity->get($field) !== null;
|
||||
}
|
||||
194
application/Espo/Classes/TemplateHelpers/GoogleMaps.php
Normal file
194
application/Espo/Classes/TemplateHelpers/GoogleMaps.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?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\Classes\TemplateHelpers;
|
||||
|
||||
class GoogleMaps
|
||||
{
|
||||
public static function image()
|
||||
{
|
||||
$args = func_get_args();
|
||||
$context = $args[count($args) - 1];
|
||||
$hash = $context['hash'];
|
||||
$data = $context['data']['root'];
|
||||
|
||||
$em = $data['__entityManager'];
|
||||
$metadata = $data['__metadata'];
|
||||
$config = $data['__config'];
|
||||
|
||||
$entityType = $data['__entityType'];
|
||||
|
||||
$field = $hash['field'] ?? null;
|
||||
|
||||
$size = $hash['size'] ?? '400x400';
|
||||
$zoom = $hash['zoom'] ?? null;
|
||||
$language = $hash['language'] ?? $config->get('language');
|
||||
|
||||
if (strpos($size, 'x') === false) {
|
||||
$size = $size .'x' . $size;
|
||||
}
|
||||
|
||||
if ($field && $metadata->get(['entityDefs', $entityType, 'fields', $field, 'type']) !== 'address') {
|
||||
$GLOBALS['log']->warning("Template helper _googleMapsImage: Specified field is not of address type.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
!$field &&
|
||||
!array_key_exists('street', $hash) &&
|
||||
!array_key_exists('city', $hash) &&
|
||||
!array_key_exists('country', $hash) &&
|
||||
!array_key_exists('state', $hash) &&
|
||||
!array_key_exists('postalCode', $hash)
|
||||
) {
|
||||
$field = ($entityType === 'Account') ? 'billingAddress' : 'address';
|
||||
}
|
||||
|
||||
if ($field) {
|
||||
$street = $data[$field . 'Street'] ?? null;
|
||||
$city = $data[$field . 'City'] ?? null;
|
||||
$country = $data[$field . 'Country'] ?? null;
|
||||
$state = $data[$field . 'State'] ?? null;
|
||||
$postalCode = $data[$field . 'postalCode'] ?? null;
|
||||
} else {
|
||||
$street = $hash['street'] ?? null;
|
||||
$city = $hash['city'] ?? null;
|
||||
$country = $hash['country'] ?? null;
|
||||
$state = $hash['state'] ?? null;
|
||||
$postalCode = $hash['postalCode'] ?? null;
|
||||
}
|
||||
|
||||
$address = '';
|
||||
if ($street) {
|
||||
$address .= $street;
|
||||
}
|
||||
if ($city) {
|
||||
if ($address != '') {
|
||||
$address .= ', ';
|
||||
}
|
||||
$address .= $city;
|
||||
}
|
||||
if ($state) {
|
||||
if ($address != '') {
|
||||
$address .= ', ';
|
||||
}
|
||||
$address .= $state;
|
||||
}
|
||||
if ($postalCode) {
|
||||
if ($state || $city) {
|
||||
$address .= ' ';
|
||||
} else {
|
||||
if ($address) {
|
||||
$address .= ', ';
|
||||
}
|
||||
}
|
||||
$address .= $postalCode;
|
||||
}
|
||||
if ($country) {
|
||||
if ($address != '') {
|
||||
$address .= ', ';
|
||||
}
|
||||
$address .= $country;
|
||||
}
|
||||
|
||||
$address = urlencode($address);
|
||||
|
||||
$apiKey = $config->get('googleMapsApiKey');
|
||||
|
||||
if (!$apiKey) {
|
||||
$GLOBALS['log']->error("Template helper _googleMapsImage: No Google Maps API key.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$address) {
|
||||
$GLOBALS['log']->debug("Template helper _googleMapsImage: No address to display.");
|
||||
return null;
|
||||
}
|
||||
|
||||
$format = 'jpg;';
|
||||
|
||||
$url = "https://maps.googleapis.com/maps/api/staticmap?" .
|
||||
'center=' . $address .
|
||||
'format=' . $format .
|
||||
'&size=' . $size .
|
||||
'&key=' . $apiKey;
|
||||
|
||||
if ($zoom) {
|
||||
$url .= '&zoom=' . $zoom;
|
||||
}
|
||||
if ($language) {
|
||||
$url .= '&language=' . $language;
|
||||
}
|
||||
|
||||
$GLOBALS['log']->debug("Template helper _googleMapsImage: URL: {$url}.");
|
||||
|
||||
$image = \Espo\Core\TemplateHelpers\GoogleMaps::getImage($url);
|
||||
|
||||
if (!$image) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$filePath = tempnam(sys_get_temp_dir(), 'google_maps_image');
|
||||
file_put_contents($filePath, $image);
|
||||
|
||||
list($width, $height) = explode('x', $size);
|
||||
|
||||
$tag = "<img src=\"{$filePath}\" width=\"{$width}\" height=\"{$height}\">";
|
||||
|
||||
return new LightnCandy\SafeString($tag);
|
||||
}
|
||||
|
||||
public static function getImage(string $url)
|
||||
{
|
||||
$headers = [];
|
||||
$headers[] = 'Accept: image/jpeg, image/pjpeg';
|
||||
$headers[] = 'Connection: Keep-Alive';
|
||||
|
||||
$agent = 'Mozilla/5.0';
|
||||
|
||||
$c = curl_init();
|
||||
|
||||
curl_setopt($c, \CURLOPT_URL, $url);
|
||||
curl_setopt($c, \CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($c, \CURLOPT_HEADER, 0);
|
||||
curl_setopt($c, \CURLOPT_USERAGENT, $agent);
|
||||
curl_setopt($c, \CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($c, \CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($c, \CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($c, \CURLOPT_BINARYTRANSFER, 1);
|
||||
|
||||
|
||||
$raw = curl_exec($c);
|
||||
curl_close($c);
|
||||
|
||||
return $raw;
|
||||
}
|
||||
}
|
||||
@@ -63,11 +63,6 @@ class ActionHistoryRecord extends \Espo\Core\Controllers\Record
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function beforeMassDelete()
|
||||
{
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
public function beforeMassConvertCurrency()
|
||||
{
|
||||
throw new Forbidden();
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
use Espo\Core\UpgradeManager;
|
||||
use Espo\Core\Utils\AdminNotificationManager;
|
||||
use Espo\Core\Utils\SystemRequirements;
|
||||
|
||||
class Admin extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
@@ -48,15 +50,17 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$result = $this->getContainer()->get('dataManager')->rebuild();
|
||||
|
||||
return $result;
|
||||
$this->getContainer()->get('dataManager')->rebuild();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postActionClearCache($params)
|
||||
{
|
||||
$result = $this->getContainer()->get('dataManager')->clearCache();
|
||||
return $result;
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionJobs()
|
||||
@@ -73,15 +77,16 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
|
||||
|
||||
$upgradeManager = new UpgradeManager($this->getContainer());
|
||||
|
||||
$upgradeId = $upgradeManager->upload($data);
|
||||
$manifest = $upgradeManager->getManifest();
|
||||
|
||||
return array(
|
||||
return [
|
||||
'id' => $upgradeId,
|
||||
'version' => $manifest['version'],
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
public function postActionRunUpgrade($params, $data)
|
||||
@@ -92,7 +97,7 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
}
|
||||
}
|
||||
|
||||
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
|
||||
$upgradeManager = new UpgradeManager($this->getContainer());
|
||||
$upgradeManager->install(get_object_vars($data));
|
||||
|
||||
return true;
|
||||
@@ -105,13 +110,15 @@ class Admin extends \Espo\Core\Controllers\Base
|
||||
|
||||
public function actionAdminNotificationList($params)
|
||||
{
|
||||
$adminNotificationManager = new \Espo\Core\Utils\AdminNotificationManager($this->getContainer());
|
||||
$adminNotificationManager = new AdminNotificationManager($this->getContainer());
|
||||
|
||||
return $adminNotificationManager->getNotificationList();
|
||||
}
|
||||
|
||||
public function actionSystemRequirementList($params)
|
||||
{
|
||||
$systemRequirementManager = new \Espo\Core\Utils\SystemRequirements($this->getContainer());
|
||||
$systemRequirementManager = new SystemRequirements($this->getContainer());
|
||||
|
||||
return $systemRequirementManager->getAllRequiredList();
|
||||
}
|
||||
}
|
||||
|
||||
38
application/Espo/Controllers/ApiIndex.php
Normal file
38
application/Espo/Controllers/ApiIndex.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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\Controllers;
|
||||
|
||||
class ApiIndex {
|
||||
|
||||
public function getActionIndex()
|
||||
{
|
||||
return "EspoCRM REST API";
|
||||
}
|
||||
}
|
||||
@@ -29,22 +29,33 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class App extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\Authentication\Authentication;
|
||||
use Espo\Core\Di;
|
||||
use Espo\Core\Api\Request;
|
||||
|
||||
use StdClass;
|
||||
|
||||
class App implements
|
||||
|
||||
Di\ServiceFactoryAware,
|
||||
Di\InjectableFactoryAware
|
||||
{
|
||||
use Di\ServiceFactorySetter;
|
||||
use Di\InjectableFactorySetter;
|
||||
|
||||
public function actionUser()
|
||||
{
|
||||
return $this->getServiceFactory()->create('App')->getUserData();
|
||||
return $this->serviceFactory->create('App')->getUserData();
|
||||
}
|
||||
|
||||
public function postActionDestroyAuthToken($params, $data)
|
||||
public function postActionDestroyAuthToken(array $params, StdClass $data, Request $request)
|
||||
{
|
||||
if (empty($data->token)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$auth = new \Espo\Core\Utils\Auth($this->getContainer());
|
||||
return $auth->destroyAuthToken($data->token);
|
||||
$auth = $this->injectableFactory->create(Authentication::class);
|
||||
return $auth->destroyAuthToken($data->token, $request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Attachment extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -57,4 +57,21 @@ class Attachment extends \Espo\Core\Controllers\Record
|
||||
|
||||
return $this->getRecordService()->getCopiedAttachment($data)->getValueMap();
|
||||
}
|
||||
|
||||
public function getActionFile($params, $data, $request, $response)
|
||||
{
|
||||
$id = $params['id'] ?? null;
|
||||
|
||||
if (!$id) throw new BadRequest();
|
||||
|
||||
$fileData = $this->getRecordService()->getFileData($id);
|
||||
|
||||
$response->setHeader('Content-Type', $fileData->type);
|
||||
$response->setHeader('Content-Disposition', 'Content-Disposition: attachment; filename="'.$fileData->name.'"');
|
||||
if ($fileData->size) {
|
||||
$response->setHeader('Content-Length', $fileData->size);
|
||||
}
|
||||
|
||||
return $fileData->contents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class AuthLogRecord extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class AuthToken extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,31 +29,34 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\{
|
||||
Forbidden,
|
||||
BadRequest,
|
||||
};
|
||||
|
||||
class CurrencyRate extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\{
|
||||
ServiceFactory,
|
||||
Api\Request,
|
||||
};
|
||||
|
||||
class CurrencyRate
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
protected $serviceFactory;
|
||||
|
||||
public function __construct(ServiceFactory $serviceFactory)
|
||||
{
|
||||
if (!$this->getAcl()->check('Currency')) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
}
|
||||
|
||||
public function getActionIndex()
|
||||
public function getActionIndex(Request $request)
|
||||
{
|
||||
if ($this->getAcl()->getLevel('Currency', 'read') !== 'yes') throw new Forbidden();
|
||||
|
||||
return $this->getService('CurrencyRate')->get();
|
||||
return $this->serviceFactory->create('CurrencyRate')->get();
|
||||
}
|
||||
|
||||
public function putActionUpdate($params, $data)
|
||||
public function putActionUpdate(Request $request)
|
||||
{
|
||||
if ($this->getAcl()->getLevel('Currency', 'edit') !== 'yes') throw new Forbidden();
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (empty($data) || !is_object($data)) throw new BadRequest();
|
||||
|
||||
return $this->getService('CurrencyRate')->set($data);
|
||||
return $this->serviceFactory->create('CurrencyRate')->set($data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class DashboardTemplate extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,27 +29,33 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class DataPrivacy extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\ServiceFactory;
|
||||
use Espo\Core\Acl;
|
||||
|
||||
class DataPrivacy
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
protected $serviceFactory;
|
||||
protected $acl;
|
||||
|
||||
public function __construct(ServiceFactory $serviceFactory, Acl $acl)
|
||||
{
|
||||
if ($this->getAcl()->get('dataPrivacyPermission') === 'no') {
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
$this->acl = $acl;
|
||||
|
||||
if ($this->acl->get('dataPrivacyPermission') === 'no') {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function postActionErase($params, $data)
|
||||
public function postActionErase($params, \StdClass $data)
|
||||
{
|
||||
if (empty($data->entityType) || empty($data->id) || empty($data->fieldList) || !is_array($data->fieldList)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
return $this->getServiceFactory()->create('DataPrivacy')->erase($data->entityType, $data->id, $data->fieldList);
|
||||
return $this->serviceFactory->create('DataPrivacy')->erase($data->entityType, $data->id, $data->fieldList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,10 +29,9 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
|
||||
class Email extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -230,4 +229,15 @@ class Email extends \Espo\Core\Controllers\Record
|
||||
}
|
||||
return $this->getRecordService()->moveToFolderByIdList($idList, $data->folderId);
|
||||
}
|
||||
|
||||
public function getActionGetInsertFieldData($params, $data, $request)
|
||||
{
|
||||
if (!$this->getAcl()->checkScope('Email', 'create')) throw new Forbidden();
|
||||
|
||||
return $this->getServiceFactory()->create('EmailTemplate')->getInsertFieldData([
|
||||
'parentId' => $request->get('parentId'),
|
||||
'parentType' => $request->get('parentType'),
|
||||
'to' => $request->get('to'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class EmailAccount extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -39,7 +39,7 @@ class EmailAccount extends \Espo\Core\Controllers\Record
|
||||
return $this->getRecordService()->getFolders([
|
||||
'host' => $data->host ?? null,
|
||||
'port' => $data->port ?? null,
|
||||
'ssl' => $data->ssl ?? false,
|
||||
'security' => $data->security ?? null,
|
||||
'username' => $data->username ?? null,
|
||||
'password' => $data->password ?? null,
|
||||
'id' => $data->id ?? null,
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class EmailAddress extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -33,4 +33,3 @@ class EmailFilter extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class EmailFolder extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class EmailTemplate extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -49,6 +49,4 @@ class EmailTemplate extends \Espo\Core\Controllers\Record
|
||||
'relatedId' => $request->get('relatedId')
|
||||
), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,26 +29,49 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\{
|
||||
Entities\User,
|
||||
Tools\EntityManager\EntityManager as EntityManagerTool,
|
||||
};
|
||||
|
||||
class EntityManager extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
Exceptions\Forbidden,
|
||||
Exceptions\BadRequest,
|
||||
Api\Request,
|
||||
DataManager,
|
||||
Utils\Config,
|
||||
};
|
||||
|
||||
class EntityManager
|
||||
{
|
||||
protected $user;
|
||||
protected $dataManager;
|
||||
protected $config;
|
||||
protected $entityManagerTool;
|
||||
|
||||
public function __construct(User $user, DataManager $dataManager, Config $config, EntityManagerTool $entityManagerTool)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->dataManager = $dataManager;
|
||||
$this->config = $config;
|
||||
$this->entityManagerTool = $entityManagerTool;
|
||||
|
||||
$this->checkControllerAccess();
|
||||
}
|
||||
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
if (!$this->user->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function actionCreateEntity($params, $data, $request)
|
||||
public function postActionCreateEntity(Request $request)
|
||||
{
|
||||
$data = get_object_vars($data);
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data = get_object_vars($data);
|
||||
|
||||
if (empty($data['name']) || empty($data['type'])) {
|
||||
throw new BadRequest();
|
||||
@@ -101,18 +124,18 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
$params['kanbanStatusIgnoreList'] = $data['kanbanStatusIgnoreList'];
|
||||
}
|
||||
|
||||
$result = $this->getContainer()->get('entityManagerUtil')->create($name, $type, $params);
|
||||
$result = $this->entityManagerTool->create($name, $type, $params);
|
||||
|
||||
if ($result) {
|
||||
$tabList = $this->getConfig()->get('tabList', []);
|
||||
$tabList = $this->config->get('tabList', []);
|
||||
|
||||
if (!in_array($name, $tabList)) {
|
||||
$tabList[] = $name;
|
||||
$this->getConfig()->set('tabList', $tabList);
|
||||
$this->getConfig()->save();
|
||||
$this->config->set('tabList', $tabList);
|
||||
$this->config->save();
|
||||
}
|
||||
|
||||
$this->getContainer()->get('dataManager')->rebuild();
|
||||
$this->dataManager->rebuild();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -120,23 +143,23 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionUpdateEntity($params, $data, $request)
|
||||
public function postActionUpdateEntity(Request $request)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$data = get_object_vars($data);
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data['name'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$name = $data['name'];
|
||||
$name = filter_var($name, \FILTER_SANITIZE_STRING);
|
||||
|
||||
$result = $this->getContainer()->get('entityManagerUtil')->update($name, $data);
|
||||
$result = $this->entityManagerTool->update($name, $data);
|
||||
|
||||
if ($result) {
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -144,32 +167,31 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionRemoveEntity($params, $data, $request)
|
||||
public function postActionRemoveEntity(Request $request)
|
||||
{
|
||||
$data = get_object_vars($data);
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data = get_object_vars($data);
|
||||
|
||||
if (empty($data['name'])) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$name = $data['name'];
|
||||
$name = filter_var($name, \FILTER_SANITIZE_STRING);
|
||||
|
||||
$result = $this->getContainer()->get('entityManagerUtil')->delete($name);
|
||||
$result = $this->entityManagerTool->delete($name);
|
||||
|
||||
if ($result) {
|
||||
$tabList = $this->getConfig()->get('tabList', []);
|
||||
$tabList = $this->config->get('tabList', []);
|
||||
if (($key = array_search($name, $tabList)) !== false) {
|
||||
unset($tabList[$key]);
|
||||
$tabList = array_values($tabList);
|
||||
}
|
||||
$this->getConfig()->set('tabList', $tabList);
|
||||
$this->getConfig()->save();
|
||||
$this->config->set('tabList', $tabList);
|
||||
$this->config->save();
|
||||
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -177,13 +199,11 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionCreateLink($params, $data, $request)
|
||||
public function postActionCreateLink(Request $request)
|
||||
{
|
||||
$data = get_object_vars($data);
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data = get_object_vars($data);
|
||||
|
||||
$paramList = [
|
||||
'entity',
|
||||
@@ -234,10 +254,10 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
$params['foreignLinkEntityTypeList'] = $data['foreignLinkEntityTypeList'];
|
||||
}
|
||||
|
||||
$result = $this->getContainer()->get('entityManagerUtil')->createLink($params);
|
||||
$result = $this->entityManagerTool->createLink($params);
|
||||
|
||||
if ($result) {
|
||||
$this->getContainer()->get('dataManager')->rebuild();
|
||||
$this->dataManager->rebuild();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -245,13 +265,11 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionUpdateLink($params, $data, $request)
|
||||
public function postActionUpdateLink(Request $request)
|
||||
{
|
||||
$data = get_object_vars($data);
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data = get_object_vars($data);
|
||||
|
||||
$paramList = [
|
||||
'entity',
|
||||
@@ -295,10 +313,10 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
$params['foreignLinkEntityTypeList'] = $data['foreignLinkEntityTypeList'];
|
||||
}
|
||||
|
||||
$result = $this->getContainer()->get('entityManagerUtil')->updateLink($params);
|
||||
$result = $this->entityManagerTool->updateLink($params);
|
||||
|
||||
if ($result) {
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -306,27 +324,27 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionRemoveLink($params, $data, $request)
|
||||
public function postActionRemoveLink(Request $request)
|
||||
{
|
||||
$data = get_object_vars($data);
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$data = get_object_vars($data);
|
||||
|
||||
$paramList = [
|
||||
'entity',
|
||||
'link',
|
||||
];
|
||||
$d = array();
|
||||
|
||||
$d = [];
|
||||
|
||||
foreach ($paramList as $item) {
|
||||
$d[$item] = filter_var($data[$item], \FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
$result = $this->getContainer()->get('entityManagerUtil')->deleteLink($d);
|
||||
$result = $this->entityManagerTool->deleteLink($d);
|
||||
|
||||
if ($result) {
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -334,32 +352,37 @@ class EntityManager extends \Espo\Core\Controllers\Base
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postActionFormula($params, $data, $request)
|
||||
public function postActionFormula(Request $request)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (empty($data->scope)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
if (!property_exists($data, 'data')) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$formulaData = get_object_vars($data->data);
|
||||
|
||||
$this->getContainer()->get('entityManagerUtil')->setFormulaData($data->scope, $formulaData);
|
||||
$this->entityManagerTool->setFormulaData($data->scope, $formulaData);
|
||||
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postActionResetToDefault($params, $data, $request)
|
||||
public function postActionResetToDefault(Request $request)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (empty($data->scope)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$this->getContainer()->get('entityManagerUtil')->resetToDefaults($data->scope);
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->entityManagerTool->resetToDefaults($data->scope);
|
||||
$this->dataManager->clearCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Extension extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class ExternalAccount extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -93,12 +93,7 @@ class ExternalAccount extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
list($integration, $userId) = explode('__', $params['id']);
|
||||
|
||||
if ($this->getUser()->id != $userId && !$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$entity = $this->getEntityManager()->getEntity('ExternalAccount', $params['id']);
|
||||
return $entity->toArray();
|
||||
return $this->getRecordService()->read($params['id'])->getValueMap();
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data, $request)
|
||||
|
||||
@@ -29,27 +29,52 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\{
|
||||
Entities\User,
|
||||
Tools\FieldManager\FieldManager as FieldManagerTool,
|
||||
};
|
||||
|
||||
class FieldManager extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
Exceptions\Forbidden,
|
||||
Exceptions\NotFound,
|
||||
Exceptions\BadRequest,
|
||||
Api\Request,
|
||||
DataManager,
|
||||
};
|
||||
|
||||
class FieldManager
|
||||
{
|
||||
protected $user;
|
||||
protected $dataManager;
|
||||
protected $fieldManagerTool;
|
||||
|
||||
public function __construct(User $user, DataManager $dataManager, FieldManagerTool $fieldManagerTool)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->dataManager = $dataManager;
|
||||
$this->fieldManagerTool = $fieldManagerTool;
|
||||
|
||||
$this->checkControllerAccess();
|
||||
}
|
||||
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
if (!$this->user->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function actionRead($params, $data)
|
||||
public function getActionRead(Request $request)
|
||||
{
|
||||
if (empty($params['scope']) || empty($params['name'])) {
|
||||
$scope = $request->getRouteParam('scope');
|
||||
$name = $request->getRouteParam('name');
|
||||
|
||||
if (!$scope || !$name) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$data = $this->getContainer()->get('fieldManager')->read($params['scope'], $params['name']);
|
||||
$data = $this->fieldManagerTool->read($scope, $name);
|
||||
|
||||
if (!isset($data)) {
|
||||
throw new BadRequest();
|
||||
@@ -58,72 +83,91 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function postActionCreate($params, $data)
|
||||
public function postActionCreate(Request $request)
|
||||
{
|
||||
if (empty($params['scope']) || empty($data->name)) {
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$scope = $request->getRouteParam('scope');
|
||||
$name = $data->name ?? null;
|
||||
|
||||
if (!$scope || !$name) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$fieldManager = $this->getContainer()->get('fieldManager');
|
||||
$fieldManager->create($params['scope'], $data->name, get_object_vars($data));
|
||||
$fieldManagerTool = $this->fieldManagerTool;
|
||||
|
||||
$fieldManagerTool->create($scope, $name, get_object_vars($data));
|
||||
|
||||
try {
|
||||
$this->getContainer()->get('dataManager')->rebuild($params['scope']);
|
||||
} catch (Error $e) {
|
||||
$fieldManager->delete($params['scope'], $data->name);
|
||||
$this->dataManager->rebuild([$scope]);
|
||||
}
|
||||
catch (Error $e) {
|
||||
$fieldManagerTool->delete($scope, $data->name);
|
||||
|
||||
throw new Error($e->getMessage());
|
||||
}
|
||||
|
||||
return $fieldManager->read($params['scope'], $data->name);
|
||||
return $fieldManagerTool->read($scope, $data->name);
|
||||
}
|
||||
|
||||
public function patchActionUpdate($params, $data)
|
||||
public function patchActionUpdate(Request $request)
|
||||
{
|
||||
return $this->putActionUpdate($params, $data);
|
||||
return $this->putActionUpdate($request);
|
||||
}
|
||||
|
||||
public function putActionUpdate($params, $data)
|
||||
public function putActionUpdate(Request $request)
|
||||
{
|
||||
if (empty($params['scope']) || empty($params['name'])) {
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$scope = $request->getRouteParam('scope');
|
||||
$name = $request->getRouteParam('name');
|
||||
|
||||
if (!$scope || !$name) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$fieldManager = $this->getContainer()->get('fieldManager');
|
||||
$fieldManager->update($params['scope'], $params['name'], get_object_vars($data));
|
||||
$fieldManagerTool = $this->fieldManagerTool;
|
||||
|
||||
if ($fieldManager->isChanged()) {
|
||||
$this->getContainer()->get('dataManager')->rebuild($params['scope']);
|
||||
$fieldManagerTool->update($scope, $name, get_object_vars($data));
|
||||
|
||||
if ($fieldManagerTool->isChanged()) {
|
||||
$this->dataManager->rebuild([$scope]);
|
||||
} else {
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
}
|
||||
|
||||
return $fieldManager->read($params['scope'], $params['name']);
|
||||
return $fieldManagerTool->read($scope, $name);
|
||||
}
|
||||
|
||||
public function deleteActionDelete($params, $data)
|
||||
public function deleteActionDelete(Request $request)
|
||||
{
|
||||
if (empty($params['scope']) || empty($params['name'])) {
|
||||
$scope = $request->getRouteParam('scope');
|
||||
$name = $request->getRouteParam('name');
|
||||
|
||||
if (!$scope || !$name) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$result = $this->getContainer()->get('fieldManager')->delete($params['scope'], $params['name']);
|
||||
$result = $this->fieldManagerTool->delete($scope, $name);
|
||||
|
||||
$this->getContainer()->get('dataManager')->rebuildMetadata();
|
||||
$this->dataManager->rebuildMetadata();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function postActionResetToDefault($params, $data)
|
||||
public function postActionResetToDefault(Request $request)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (empty($data->scope) || empty($data->name)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$this->getContainer()->get('fieldManager')->resetToDefault($data->scope, $data->name);
|
||||
$this->fieldManagerTool->resetToDefault($data->scope, $data->name);
|
||||
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
|
||||
$this->getContainer()->get('dataManager')->rebuildMetadata();
|
||||
$this->dataManager->rebuildMetadata();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,17 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error,
|
||||
\Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\ServiceFactory;
|
||||
|
||||
class GlobalSearch extends \Espo\Core\Controllers\Base
|
||||
class GlobalSearch
|
||||
{
|
||||
protected $serviceFactory;
|
||||
|
||||
public function __construct(ServiceFactory $serviceFactory)
|
||||
{
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
}
|
||||
|
||||
public function actionSearch($params, $data, $request)
|
||||
{
|
||||
$query = $request->get('q');
|
||||
@@ -41,7 +47,6 @@ class GlobalSearch extends \Espo\Core\Controllers\Base
|
||||
$offset = intval($request->get('offset'));
|
||||
$maxSize = intval($request->get('maxSize'));
|
||||
|
||||
return $this->getService('GlobalSearch')->find($query, $offset, $maxSize);
|
||||
return $this->serviceFactory->create('GlobalSearch')->find($query, $offset, $maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,17 +29,21 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
class I18n extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\ServiceFactory;
|
||||
|
||||
class I18n
|
||||
{
|
||||
protected $serviceFactory;
|
||||
|
||||
public function __construct(ServiceFactory $serviceFactory)
|
||||
{
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
}
|
||||
|
||||
public function actionRead($params, $data, $request)
|
||||
{
|
||||
$default = $request->get('default') === 'true';
|
||||
|
||||
return $this->getServiceFactory()->create('Language')->getDataForFrontend($default);
|
||||
|
||||
/*if ($request->get('default')) {
|
||||
return $this->getContainer()->get('defaultLanguage')->getAll();
|
||||
}
|
||||
return $this->getContainer()->get('language')->getAll();*/
|
||||
return $this->serviceFactory->create('Language')->getDataForFrontend($default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Utils as Utils;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Import extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -78,24 +78,13 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
return $this->getContainer()->get('entityManager');
|
||||
}
|
||||
|
||||
public function actionUploadFile($params, $data, $request)
|
||||
public function postActionUploadFile($params, $data)
|
||||
{
|
||||
$contents = $data;
|
||||
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$attachmentId = $this->getService('Import')->uploadFile($contents);
|
||||
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment');
|
||||
$attachment->set('type', 'text/csv');
|
||||
$attachment->set('role', 'Import File');
|
||||
$attachment->set('name', 'import-file.csv');
|
||||
$attachment->set('contents', $contents);
|
||||
$this->getEntityManager()->saveEntity($attachment);
|
||||
|
||||
return [
|
||||
'attachmentId' => $attachment->id
|
||||
];
|
||||
return ['attachmentId' => $attachmentId];
|
||||
}
|
||||
|
||||
public function actionRevert($params, $data, $request)
|
||||
@@ -106,7 +95,9 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
return $this->getService('Import')->revert($data->id);
|
||||
$this->getService('Import')->revert($data->id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionRemoveDuplicates($params, $data, $request)
|
||||
@@ -117,7 +108,9 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
if (!$request->isPost()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
return $this->getService('Import')->removeDuplicates($data->id);
|
||||
$this->getService('Import')->removeDuplicates($data->id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionCreate($params, $data, $request)
|
||||
@@ -190,6 +183,8 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
'skipDuplicateChecking' => !empty($data->skipDuplicateChecking),
|
||||
'idleMode' => !empty($data->idleMode),
|
||||
'silentMode' => !empty($data->silentMode),
|
||||
'manualMode' => !empty($data->manualMode),
|
||||
'defaultFieldList' => $data->defaultFieldList ?? [],
|
||||
];
|
||||
|
||||
if (property_exists($data, 'updateBy')) {
|
||||
@@ -210,7 +205,9 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
if (empty($data->id) || empty($data->entityType) || empty($data->entityId)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$this->getService('Import')->unmarkAsDuplicate($data->id, $data->entityType, $data->entityId);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class InboundEmail extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -46,7 +45,7 @@ class InboundEmail extends \Espo\Core\Controllers\Record
|
||||
return $this->getRecordService()->getFolders([
|
||||
'host' => $data->host ?? null,
|
||||
'port' => $data->port ?? null,
|
||||
'ssl' => $data->ssl ?? false,
|
||||
'security' => $data->security ?? null,
|
||||
'username' => $data->username ?? null,
|
||||
'password' => $data->password ?? null,
|
||||
'id' => $data->id ?? null,
|
||||
|
||||
@@ -29,9 +29,8 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Integration extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -82,4 +81,3 @@ class Integration extends \Espo\Core\Controllers\Record
|
||||
return $entity->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Job extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,49 +29,69 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Utils as Utils;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\{
|
||||
Exceptions\Forbidden,
|
||||
Exceptions\BadRequest,
|
||||
Api\Request,
|
||||
DataManager,
|
||||
};
|
||||
|
||||
class LabelManager extends \Espo\Core\Controllers\Base
|
||||
use Espo\{
|
||||
Tools\LabelManager\LabelManager as LabelManagerTool,
|
||||
Entities\User,
|
||||
};
|
||||
|
||||
class LabelManager
|
||||
{
|
||||
protected $user;
|
||||
protected $dataManager;
|
||||
protected $labelManagerTool;
|
||||
|
||||
public function __construct(User $user, DataManager $dataManager, LabelManagerTool $labelManagerTool)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->dataManager = $dataManager;
|
||||
$this->labelManagerTool = $labelManagerTool;
|
||||
|
||||
$this->checkControllerAccess();
|
||||
}
|
||||
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
if (!$this->user->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function postActionGetScopeList($params)
|
||||
public function postActionGetScopeList()
|
||||
{
|
||||
$labelManager = $this->getContainer()->get('injectableFactory')->createByClassName('\\Espo\\Core\\Utils\\LabelManager');
|
||||
|
||||
return $labelManager->getScopeList();
|
||||
return $this->labelManagerTool->getScopeList();
|
||||
}
|
||||
|
||||
public function postActionGetScopeData($params, $data, $request)
|
||||
public function postActionGetScopeData(Request $request)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (empty($data->scope) || empty($data->language)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
$labelManager = $this->getContainer()->get('injectableFactory')->createByClassName('\\Espo\\Core\\Utils\\LabelManager');
|
||||
return $labelManager->getScopeData($data->language, $data->scope);
|
||||
|
||||
return $this->labelManagerTool->getScopeData($data->language, $data->scope);
|
||||
}
|
||||
|
||||
public function postActionSaveLabels($params, $data)
|
||||
public function postActionSaveLabels(Request $request)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
if (empty($data->scope) || empty($data->language) || !isset($data->labels)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$labels = get_object_vars($data->labels);
|
||||
|
||||
$labelManager = $this->getContainer()->get('injectableFactory')->createByClassName('\\Espo\\Core\\Utils\\LabelManager');
|
||||
$returnData = $labelManager->saveLabels($data->language, $data->scope, $labels);
|
||||
$returnData = $this->labelManagerTool->saveLabels($data->language, $data->scope, $labels);
|
||||
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
$this->dataManager->clearCache();
|
||||
|
||||
return $returnData;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class LastViewed extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
|
||||
@@ -30,62 +30,51 @@
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Utils as Utils;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class Layout extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
public function actionRead($params, $data)
|
||||
public function getActionRead($params, $data)
|
||||
{
|
||||
return $this->getServiceFactory()->create('Layout')->getForFrontend($params['scope'], $params['name']);
|
||||
$scope = $params['scope'] ?? null;
|
||||
$name = $params['name'] ?? null;
|
||||
|
||||
return $this->getServiceFactory()->create('Layout')->getForFrontend($scope, $name);
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data, $request)
|
||||
public function putActionUpdate($params, $data, $request)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$data = get_object_vars($data);
|
||||
}
|
||||
$data = json_decode($request->getBodyContents());
|
||||
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if (is_object($data)) $data = get_object_vars($data);
|
||||
|
||||
if (!$request->isPut() && !$request->isPatch()) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
|
||||
$layoutManager = $this->getContainer()->get('layout');
|
||||
$layoutManager->set($data, $params['scope'], $params['name']);
|
||||
$result = $layoutManager->save();
|
||||
$scope = $params['scope'] ?? null;
|
||||
$name = $params['name'] ?? null;
|
||||
$setId = $params['setId'] ?? null;
|
||||
|
||||
if ($result === false) {
|
||||
throw new Error("Error while saving layout.");
|
||||
}
|
||||
|
||||
$this->getContainer()->get('dataManager')->updateCacheTimestamp();
|
||||
|
||||
return $layoutManager->get($params['scope'], $params['name']);
|
||||
}
|
||||
|
||||
public function actionPatch($params, $data, $request)
|
||||
{
|
||||
return $this->actionUpdate($params, $data, $request);
|
||||
return $this->getServiceFactory()->create('Layout')->update($scope, $name, $setId, $data);
|
||||
}
|
||||
|
||||
public function postActionResetToDefault($params, $data, $request)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
|
||||
if (empty($data->scope) || empty($data->name)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
if (empty($data->scope) || empty($data->name)) throw new BadRequest();
|
||||
|
||||
$this->getContainer()->get('dataManager')->updateCacheTimestamp();
|
||||
return $this->getServiceFactory()->create('Layout')->resetToDefault($data->scope, $data->name, $data->setId ?? null);
|
||||
}
|
||||
|
||||
return $this->getContainer()->get('layout')->resetToDefault($data->scope, $data->name);
|
||||
public function getActionGetOriginal($params, $data, $request)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
|
||||
return $this->getServiceFactory()->create('Layout')->getOriginal(
|
||||
$request->get('scope'), $request->get('name'), $request->get('setId')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
42
application/Espo/Controllers/LayoutSet.php
Normal file
42
application/Espo/Controllers/LayoutSet.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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\Controllers;
|
||||
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class LayoutSet extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,26 +29,36 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
|
||||
class LeadCapture extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
public function postActionLeadCapture($params, $data, $request, $response)
|
||||
{
|
||||
if (empty($params['apiKey'])) throw new BadRequest('No API key provided.');
|
||||
if (empty($data)) throw new BadRequest('No payload provided.');
|
||||
if (empty($params['apiKey'])) {
|
||||
throw new BadRequest('No API key provided.');
|
||||
}
|
||||
|
||||
if (empty($data)) {
|
||||
throw new BadRequest('No payload provided.');
|
||||
}
|
||||
|
||||
$allowOrigin = $this->getConfig()->get('leadCaptureAllowOrigin', '*');
|
||||
$response->headers->set('Access-Control-Allow-Origin', $allowOrigin);
|
||||
|
||||
return $this->getRecordService()->leadCapture($params['apiKey'], $data);
|
||||
$response->setHeader('Access-Control-Allow-Origin', $allowOrigin);
|
||||
|
||||
$this->getRecordService()->leadCapture($params['apiKey'], $data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function optionsActionLeadCapture($params, $data, $request, $response)
|
||||
{
|
||||
if (empty($params['apiKey'])) throw new BadRequest('No API key provided.');
|
||||
if (empty($params['apiKey'])) {
|
||||
throw new BadRequest('No API key provided.');
|
||||
}
|
||||
|
||||
if (!$this->getRecordService()->isApiKeyValid($params['apiKey'])) {
|
||||
throw new NotFound();
|
||||
@@ -56,23 +66,27 @@ class LeadCapture extends \Espo\Core\Controllers\Record
|
||||
|
||||
$allowOrigin = $this->getConfig()->get('leadCaptureAllowOrigin', '*');
|
||||
|
||||
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept');
|
||||
$response->headers->set('Access-Control-Allow-Origin', $allowOrigin);
|
||||
$response->headers->set('Access-Control-Allow-Methods', 'POST');
|
||||
$response->setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept');
|
||||
$response->setHeader('Access-Control-Allow-Origin', $allowOrigin);
|
||||
$response->setHeader('Access-Control-Allow-Methods', 'POST');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postActionGenerateNewApiKey($params, $data, $request)
|
||||
{
|
||||
if (empty($data->id)) throw new BadRequest();
|
||||
if (empty($data->id)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
return $this->getRecordService()->generateNewApiKeyForEntity($data->id)->getValueMap();
|
||||
}
|
||||
|
||||
public function getActionSmtpAccountDataList()
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) throw new Forbidden();
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
return $this->getServiceFactory()->create('LeadCapture')->getSmtpAccountDataList();
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class LeadCaptureLogRecord extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
|
||||
@@ -29,11 +29,10 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Metadata extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
|
||||
public function actionRead($params, $data)
|
||||
{
|
||||
return $this->getServiceFactory()->create('Metadata')->getDataForFrontend();
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class Notification extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -47,18 +47,18 @@ class Notification extends \Espo\Core\Controllers\Record
|
||||
$maxSize = self::MAX_SIZE_LIMIT;
|
||||
}
|
||||
|
||||
$params = array(
|
||||
$params = [
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize,
|
||||
'after' => $after
|
||||
);
|
||||
'after' => $after,
|
||||
];
|
||||
|
||||
$result = $this->getService('Notification')->getList($userId, $params);
|
||||
$recordCollection = $this->getService('Notification')->getList($userId, $params);
|
||||
|
||||
return array(
|
||||
'total' => $result['total'],
|
||||
'list' => $result['collection']->toArray()
|
||||
);
|
||||
return (object) [
|
||||
'total' => $recordCollection->getTotal(),
|
||||
'list' => $recordCollection->getValueMapList(),
|
||||
];
|
||||
}
|
||||
|
||||
public function actionNotReadCount()
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class Pdf extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class PhoneNumber extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Portal extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
|
||||
class Preferences extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
|
||||
@@ -32,6 +32,11 @@ namespace Espo\Controllers;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
use Espo\Core\{
|
||||
Authentication\LDAP\Utils as LDAPUtils,
|
||||
Authentication\LDAP\Client as LDAPClient,
|
||||
};
|
||||
|
||||
class Settings extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
protected function getConfigData()
|
||||
@@ -86,11 +91,14 @@ class Settings extends \Espo\Core\Controllers\Base
|
||||
|
||||
$data = get_object_vars($data);
|
||||
|
||||
$ldapUtils = new \Espo\Core\Utils\Authentication\LDAP\Utils();
|
||||
$ldapUtils = new LDAPUtils();
|
||||
|
||||
$options = $ldapUtils->normalizeOptions($data);
|
||||
|
||||
$ldapClient = new \Espo\Core\Utils\Authentication\LDAP\Client($options);
|
||||
$ldapClient->bind(); //an exception if no connection
|
||||
$ldapClient = new LDAPClient($options);
|
||||
|
||||
//an exception if no connection
|
||||
$ldapClient->bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,14 +29,26 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
class Stream extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\ServiceFactory;
|
||||
use Espo\Core\Utils\Config;
|
||||
|
||||
class Stream
|
||||
{
|
||||
const MAX_SIZE_LIMIT = 200;
|
||||
|
||||
public static $defaultAction = 'list';
|
||||
|
||||
protected $serviceFactory;
|
||||
protected $config;
|
||||
|
||||
public function __construct(ServiceFactory $serviceFactory, Config $config)
|
||||
{
|
||||
$this->serviceFactory = $serviceFactory;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function actionList($params, $data, $request)
|
||||
{
|
||||
$scope = $params['scope'];
|
||||
@@ -48,9 +60,7 @@ class Stream extends \Espo\Core\Controllers\Base
|
||||
$filter = $request->get('filter');
|
||||
$skipOwn = $request->get('skipOwn') === 'true';
|
||||
|
||||
$service = $this->getService('Stream');
|
||||
|
||||
$maxSizeLimit = $this->getConfig()->get('recordListMaxSizeLimit', self::MAX_SIZE_LIMIT);
|
||||
$maxSizeLimit = $this->config->get('recordListMaxSizeLimit', self::MAX_SIZE_LIMIT);
|
||||
if (empty($maxSize)) {
|
||||
$maxSize = $maxSizeLimit;
|
||||
}
|
||||
@@ -58,7 +68,7 @@ class Stream extends \Espo\Core\Controllers\Base
|
||||
throw new Forbidden("Max size should should not exceed " . $maxSizeLimit . ". Use offset and limit.");
|
||||
}
|
||||
|
||||
$result = $service->find($scope, $id, [
|
||||
$result = $this->serviceFactory->create('Stream')->find($scope, $id, [
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize,
|
||||
'after' => $after,
|
||||
@@ -83,9 +93,7 @@ class Stream extends \Espo\Core\Controllers\Base
|
||||
|
||||
$where = $request->get('where');
|
||||
|
||||
$service = $this->getService('Stream');
|
||||
|
||||
$maxSizeLimit = $this->getConfig()->get('recordListMaxSizeLimit', self::MAX_SIZE_LIMIT);
|
||||
$maxSizeLimit = $this->config->get('recordListMaxSizeLimit', self::MAX_SIZE_LIMIT);
|
||||
if (empty($maxSize)) {
|
||||
$maxSize = $maxSizeLimit;
|
||||
}
|
||||
@@ -93,7 +101,7 @@ class Stream extends \Espo\Core\Controllers\Base
|
||||
throw new Forbidden("Max size should should not exceed " . $maxSizeLimit . ". Use offset and limit.");
|
||||
}
|
||||
|
||||
$result = $service->find($scope, $id, [
|
||||
$result = $this->serviceFactory->create('Stream')->find($scope, $id, [
|
||||
'offset' => $offset,
|
||||
'maxSize' => $maxSize,
|
||||
'after' => $after,
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class Template extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
|
||||
@@ -29,17 +29,26 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Utils as Utils;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class TemplateManager extends \Espo\Core\Controllers\Base
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Core\Utils\TemplateFileManager;
|
||||
use Espo\Core\ApplicationState;
|
||||
|
||||
class TemplateManager
|
||||
{
|
||||
protected function checkControllerAccess()
|
||||
protected $metadata;
|
||||
protected $templateFileManager;
|
||||
protected $applicationState;
|
||||
|
||||
public function __construct(Metadata $metadata, TemplateFileManager $templateFileManager, ApplicationState $applicationState)
|
||||
{
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
$this->metadata = $metadata;
|
||||
$this->templateFileManager = $templateFileManager;
|
||||
$this->applicationState = $applicationState;
|
||||
|
||||
if (!$this->applicationState->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
@@ -50,10 +59,10 @@ class TemplateManager extends \Espo\Core\Controllers\Base
|
||||
if (empty($name)) throw new BadRequest();
|
||||
$scope = $request->get('scope');
|
||||
$module = null;
|
||||
$module = $this->getMetadata()->get(['app', 'templates', $name, 'module']);
|
||||
$hasSubject = !$this->getMetadata()->get(['app', 'templates', $name, 'noSubject']);
|
||||
$module = $this->metadata->get(['app', 'templates', $name, 'module']);
|
||||
$hasSubject = !$this->metadata->get(['app', 'templates', $name, 'noSubject']);
|
||||
|
||||
$templateFileManager = $this->getContainer()->get('templateFileManager');
|
||||
$templateFileManager = $this->templateFileManager;
|
||||
|
||||
$returnData = (object) [];
|
||||
$returnData->body = $templateFileManager->getTemplate($name, 'body', $scope, $module);
|
||||
@@ -75,7 +84,7 @@ class TemplateManager extends \Espo\Core\Controllers\Base
|
||||
$scope = $data->scope;
|
||||
}
|
||||
|
||||
$templateFileManager = $this->getContainer()->get('templateFileManager');
|
||||
$templateFileManager = $this->templateFileManager;
|
||||
|
||||
if (isset($data->subject)) {
|
||||
$templateFileManager->saveTemplate($data->name, 'subject', $data->subject, $scope);
|
||||
@@ -99,10 +108,10 @@ class TemplateManager extends \Espo\Core\Controllers\Base
|
||||
}
|
||||
|
||||
$module = null;
|
||||
$module = $this->getMetadata()->get(['app', 'templates', $data->name, 'module']);
|
||||
$hasSubject = !$this->getMetadata()->get(['app', 'templates', $data->name, 'noSubject']);
|
||||
$module = $this->metadata->get(['app', 'templates', $data->name, 'module']);
|
||||
$hasSubject = !$this->metadata->get(['app', 'templates', $data->name, 'noSubject']);
|
||||
|
||||
$templateFileManager = $this->getContainer()->get('templateFileManager');
|
||||
$templateFileManager = $this->templateFileManager;
|
||||
|
||||
if ($hasSubject) {
|
||||
$templateFileManager->resetTemplate($data->name, 'subject', $scope);
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class User extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
@@ -69,29 +69,7 @@ class User extends \Espo\Core\Controllers\Record
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
if ($this->getConfig()->get('passwordRecoveryDisabled')) {
|
||||
throw new Forbidden("Password recovery disabled");
|
||||
}
|
||||
|
||||
$request = $this->getEntityManager()->getRepository('PasswordChangeRequest')->where([
|
||||
'requestId' => $data->requestId
|
||||
])->findOne();
|
||||
|
||||
if (!$request) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$userId = $request->get('userId');
|
||||
if (!$userId) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if ($this->getService('User')->changePassword($userId, $data->password)) {
|
||||
$this->getEntityManager()->removeEntity($request);
|
||||
return [
|
||||
'url' => $request->get('url')
|
||||
];
|
||||
}
|
||||
return $this->getService('User')->changePasswordByRequest($data->requestId, $data->password);
|
||||
}
|
||||
|
||||
public function postActionPasswordChangeRequest($params, $data, $request)
|
||||
|
||||
@@ -29,10 +29,8 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use \Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class UserSecurity extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Webhook extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
@@ -29,9 +29,12 @@
|
||||
|
||||
namespace Espo\Core;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
/**
|
||||
* A wrapper for AclManager. To check access for a current user.
|
||||
*/
|
||||
class Acl
|
||||
{
|
||||
private $user;
|
||||
@@ -54,102 +57,154 @@ class Acl
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getMap()
|
||||
public function getMap() : \StdClass
|
||||
{
|
||||
return $this->getAclManager()->getMap($this->getUser());
|
||||
}
|
||||
|
||||
public function getLevel($scope, $action)
|
||||
/**
|
||||
* Get an access level for a specific scope and action.
|
||||
*/
|
||||
public function getLevel(string $scope, string $action) : string
|
||||
{
|
||||
return $this->getAclManager()->getLevel($this->getUser(), $scope, $action);
|
||||
}
|
||||
|
||||
public function get($permission)
|
||||
/**
|
||||
* Get a permission. E.g. 'assignment' permission.
|
||||
*/
|
||||
public function get(string $permission) : ?string
|
||||
{
|
||||
return $this->getAclManager()->get($this->getUser(), $permission);
|
||||
}
|
||||
|
||||
public function checkReadNo($scope)
|
||||
/**
|
||||
* Whether there's no 'read' access for a specific scope.
|
||||
*/
|
||||
public function checkReadNo(string $scope) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkReadNo($this->getUser(), $scope);
|
||||
}
|
||||
|
||||
public function checkReadOnlyTeam($scope)
|
||||
/**
|
||||
* Whether 'read' access is set to 'team' for a specific scope.
|
||||
*/
|
||||
public function checkReadOnlyTeam(string $scope) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkReadOnlyTeam($this->getUser(), $scope);
|
||||
}
|
||||
|
||||
public function checkReadOnlyOwn($scope)
|
||||
/**
|
||||
* Whether 'read' access is set to 'own' for a specific scope.
|
||||
*/
|
||||
public function checkReadOnlyOwn(string $scope) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkReadOnlyOwn($this->getUser(), $scope);
|
||||
}
|
||||
|
||||
public function check($subject, $action = null)
|
||||
/**
|
||||
* Check a scope or entity. If $action is omitted, it will check whether a scope level is set to 'enabled'.
|
||||
*/
|
||||
public function check($subject, ?string $action = null) : bool
|
||||
{
|
||||
return $this->getAclManager()->check($this->getUser(), $subject, $action);
|
||||
}
|
||||
|
||||
public function checkScope($scope, $action = null)
|
||||
/**
|
||||
* Check access to scope. If $action is omitted, it will check whether a scope level is set to 'enabled'.
|
||||
*/
|
||||
public function checkScope(string $scope, ?string $action = null) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkScope($this->getUser(), $scope, $action);
|
||||
}
|
||||
|
||||
public function checkEntity(Entity $entity, $action = 'read')
|
||||
/**
|
||||
* Check access to a specific entity (record).
|
||||
*/
|
||||
public function checkEntity(Entity $entity, string $action = 'read') : bool
|
||||
{
|
||||
return $this->getAclManager()->checkEntity($this->getUser(), $entity, $action);
|
||||
}
|
||||
|
||||
public function checkUser($permission, User $entity)
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function checkUser(string $permission, User $entity) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkUser($this->getUser(), $permission, $entity);
|
||||
}
|
||||
|
||||
public function checkIsOwner(Entity $entity)
|
||||
/**
|
||||
* Whether a user is owned of an entity (record). Usually 'assignedUser' field is used for checking.
|
||||
*/
|
||||
public function checkIsOwner(Entity $entity) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkIsOwner($this->getUser(), $entity);
|
||||
}
|
||||
|
||||
public function checkInTeam(Entity $entity)
|
||||
/**
|
||||
* Whether a user team list overlaps with teams set in an entity.
|
||||
*/
|
||||
public function checkInTeam(Entity $entity) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkInTeam($this->getUser(), $entity);
|
||||
}
|
||||
|
||||
public function getScopeForbiddenAttributeList($scope, $action = 'read', $thresholdLevel = 'no')
|
||||
/**
|
||||
* Get attributes forbidden for a user.
|
||||
*/
|
||||
public function getScopeForbiddenAttributeList(string $scope, string $action = 'read', string $thresholdLevel = 'no') : array
|
||||
{
|
||||
return $this->getAclManager()->getScopeForbiddenAttributeList($this->getUser(), $scope, $action, $thresholdLevel);
|
||||
}
|
||||
|
||||
public function getScopeForbiddenFieldList($scope, $action = 'read', $thresholdLevel = 'no')
|
||||
/**
|
||||
* Get fields forbidden for a user.
|
||||
*/
|
||||
public function getScopeForbiddenFieldList(string $scope, string $action = 'read', string $thresholdLevel = 'no') : array
|
||||
{
|
||||
return $this->getAclManager()->getScopeForbiddenFieldList($this->getUser(), $scope, $action, $thresholdLevel);
|
||||
}
|
||||
|
||||
public function getScopeForbiddenLinkList($scope, $action = 'read', $thresholdLevel = 'no')
|
||||
/**
|
||||
* Get links forbidden for a user.
|
||||
*/
|
||||
public function getScopeForbiddenLinkList(string $scope, string $action = 'read', string $thresholdLevel = 'no') : array
|
||||
{
|
||||
return $this->getAclManager()->getScopeForbiddenLinkList($this->getUser(), $scope, $action, $thresholdLevel);
|
||||
}
|
||||
|
||||
public function checkUserPermission($target, $permissionType = 'userPermission')
|
||||
/**
|
||||
* Whether a user has an access to another user over a specific permission.
|
||||
*
|
||||
* @param $target User|string User entity or user ID.
|
||||
*/
|
||||
public function checkUserPermission($target, string $permissionType = 'user') : bool
|
||||
{
|
||||
return $this->getAclManager()->checkUserPermission($this->getUser(), $target, $permissionType);
|
||||
}
|
||||
|
||||
public function checkAssignmentPermission($target)
|
||||
/**
|
||||
* Whether a user can assign to another user.
|
||||
*
|
||||
* @param $target User|string User entity or user ID.
|
||||
*/
|
||||
public function checkAssignmentPermission($target) : bool
|
||||
{
|
||||
return $this->getAclManager()->checkAssignmentPermission($this->getUser(), $target);
|
||||
}
|
||||
|
||||
public function getScopeRestrictedFieldList($scope, $type)
|
||||
public function getScopeRestrictedFieldList(string $scope, $type) : array
|
||||
{
|
||||
return $this->getAclManager()->getScopeRestrictedFieldList($scope, $type);
|
||||
}
|
||||
|
||||
public function getScopeRestrictedAttributeList($scope, $type)
|
||||
public function getScopeRestrictedAttributeList(string $scope, $type) : array
|
||||
{
|
||||
return $this->getAclManager()->getScopeRestrictedAttributeList($scope, $type);
|
||||
}
|
||||
|
||||
public function getScopeRestrictedLinkList($scope, $type)
|
||||
public function getScopeRestrictedLinkList(string $scope, $type) : array
|
||||
{
|
||||
return $this->getAclManager()->getScopeRestrictedLinkList($scope, $type);
|
||||
}
|
||||
|
||||
296
application/Espo/Core/Acl/Acl.php
Normal file
296
application/Espo/Core/Acl/Acl.php
Normal file
@@ -0,0 +1,296 @@
|
||||
<?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\Core\Acl;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\{
|
||||
ORM\EntityManager,
|
||||
AclManager,
|
||||
Utils\Config,
|
||||
};
|
||||
|
||||
/**
|
||||
* An implementation for access checking for entities. Can be overriden in `Acl` namespece.
|
||||
*/
|
||||
class Acl implements ScopeAcl, EntityAcl
|
||||
{
|
||||
protected $scope;
|
||||
|
||||
protected $ownerUserIdAttribute = null;
|
||||
|
||||
protected $allowDeleteCreatedThresholdPeriod = '24 hours';
|
||||
|
||||
protected $entityManager;
|
||||
protected $aclManager;
|
||||
protected $config;
|
||||
|
||||
public function __construct(string $scope, EntityManager $entityManager, AclManager $aclManager, Config $config)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
$this->entityManager = $entityManager;
|
||||
$this->aclManager = $aclManager;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->entityManager;
|
||||
}
|
||||
|
||||
protected function getAclManager()
|
||||
{
|
||||
return $this->aclManager;
|
||||
}
|
||||
|
||||
public function checkReadOnlyTeam(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_object($data) || !isset($data->read)) {
|
||||
return false;
|
||||
}
|
||||
return $data->read === 'team';
|
||||
}
|
||||
|
||||
public function checkReadNo(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_object($data) || !isset($data->read)) {
|
||||
return false;
|
||||
}
|
||||
return $data->read === 'no';
|
||||
}
|
||||
|
||||
public function checkReadOnlyOwn(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_object($data) || !isset($data->read)) {
|
||||
return false;
|
||||
}
|
||||
return $data->read === 'own';
|
||||
}
|
||||
|
||||
public function checkEntity(User $user, Entity $entity, $data, $action)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
return $this->checkScope($user, $data, $action, $entity);
|
||||
}
|
||||
|
||||
public function checkScope(User $user, $data, $action = null, Entity $entity = null, $entityAccessData = [])
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_null($data)) {
|
||||
return false;
|
||||
}
|
||||
if ($data === false) {
|
||||
return false;
|
||||
}
|
||||
if ($data === true) {
|
||||
return true;
|
||||
}
|
||||
if (is_string($data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$isOwner = null;
|
||||
if (isset($entityAccessData['isOwner'])) {
|
||||
$isOwner = $entityAccessData['isOwner'];
|
||||
}
|
||||
$inTeam = null;
|
||||
if (isset($entityAccessData['inTeam'])) {
|
||||
$inTeam = $entityAccessData['inTeam'];
|
||||
}
|
||||
|
||||
if (is_null($action)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isset($data->$action)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = $data->$action;
|
||||
|
||||
if ($value === 'all' || $value === 'yes' || $value === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$value || $value === 'no') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($isOwner)) {
|
||||
if ($entity) {
|
||||
$isOwner = $this->checkIsOwner($user, $entity);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isOwner) {
|
||||
if ($value === 'own' || $value === 'team') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (is_null($inTeam) && $entity) {
|
||||
$inTeam = $this->checkInTeam($user, $entity);
|
||||
}
|
||||
|
||||
if ($inTeam) {
|
||||
if ($value === 'team') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkIsOwner(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->hasAttribute('assignedUserId')) {
|
||||
if ($entity->has('assignedUserId')) {
|
||||
if ($user->id === $entity->get('assignedUserId')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if ($entity->hasAttribute('createdById')) {
|
||||
if ($entity->has('createdById')) {
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
if ($entity->hasLinkMultipleId('assignedUsers', $user->id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkInTeam(User $user, Entity $entity)
|
||||
{
|
||||
$userTeamIdList = $user->getLinkMultipleIdList('teams');
|
||||
|
||||
if (!$entity->hasRelation('teams') || !$entity->hasAttribute('teamsIds')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$entityTeamIdList = $entity->getLinkMultipleIdList('teams');
|
||||
|
||||
if (empty($entityTeamIdList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($userTeamIdList as $id) {
|
||||
if (in_array($id, $entityTeamIdList)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'delete')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_object($data)) {
|
||||
if ($data->edit !== 'no' || $data->create !== 'no') {
|
||||
if (
|
||||
$this->config->get('aclAllowDeleteCreated')
|
||||
&&
|
||||
$entity->has('createdById') && $entity->get('createdById') == $user->id
|
||||
) {
|
||||
$isDeletedAllowed = false;
|
||||
if (!$entity->has('assignedUserId')) {
|
||||
$isDeletedAllowed = true;
|
||||
} else {
|
||||
if (!$entity->get('assignedUserId')) {
|
||||
$isDeletedAllowed = true;
|
||||
} else if ($entity->get('assignedUserId') == $entity->get('createdById')) {
|
||||
$isDeletedAllowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isDeletedAllowed) {
|
||||
$createdAt = $entity->get('createdAt');
|
||||
if ($createdAt) {
|
||||
$deleteThresholdPeriod = $this->config->get(
|
||||
'aclAllowDeleteCreatedThresholdPeriod',
|
||||
$this->allowDeleteCreatedThresholdPeriod
|
||||
);
|
||||
if (\Espo\Core\Utils\DateTime::isAfterThreshold($createdAt, $deleteThresholdPeriod)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getOwnerUserIdAttribute(Entity $entity)
|
||||
{
|
||||
if ($this->ownerUserIdAttribute) {
|
||||
return $this->ownerUserIdAttribute;
|
||||
}
|
||||
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
return 'assignedUsersIds';
|
||||
}
|
||||
|
||||
if ($entity->hasAttribute('assignedUserId')) {
|
||||
return 'assignedUserId';
|
||||
}
|
||||
|
||||
if ($entity->hasAttribute('createdById')) {
|
||||
return 'createdById';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,39 +29,39 @@
|
||||
|
||||
namespace Espo\Core\Acl;
|
||||
|
||||
use \Espo\Core\Interfaces\Injectable;
|
||||
use Espo\Core\Interfaces\Injectable;
|
||||
|
||||
use \Espo\Entities\User;
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Base implements Injectable
|
||||
use Espo\Core\{
|
||||
ORM\EntityManager,
|
||||
AclManager,
|
||||
Utils\Config,
|
||||
};
|
||||
|
||||
/** @deprecated */
|
||||
class Base extends Acl implements Injectable
|
||||
{
|
||||
protected $dependencyList = [
|
||||
'config',
|
||||
'entityManager',
|
||||
'aclManager',
|
||||
];
|
||||
protected $dependencyList = [];
|
||||
|
||||
protected $dependencies = []; // for backward compatibility
|
||||
|
||||
protected $scope;
|
||||
protected $dependencies = [];
|
||||
|
||||
protected $injections = [];
|
||||
|
||||
protected $ownerUserIdAttribute = null;
|
||||
public function __construct(string $scope, EntityManager $entityManager, AclManager $aclManager, Config $config)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
parent::__construct($scope, $entityManager, $aclManager, $config);
|
||||
|
||||
protected $allowDeleteCreatedThresholdPeriod = '24 hours';
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function inject($name, $object)
|
||||
{
|
||||
$this->injections[$name] = $object;
|
||||
}
|
||||
|
||||
public function __construct($scope)
|
||||
{
|
||||
$this->init();
|
||||
$this->scope = $scope;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
@@ -69,7 +69,7 @@ class Base implements Injectable
|
||||
|
||||
protected function getInjection($name)
|
||||
{
|
||||
return $this->injections[$name];
|
||||
return $this->injections[$name] ?? $this->$name ?? null;
|
||||
}
|
||||
|
||||
protected function addDependencyList(array $list)
|
||||
@@ -88,233 +88,4 @@ class Base implements Injectable
|
||||
{
|
||||
return array_merge($this->dependencyList, $this->dependencies);
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->getInjection('config');
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->getInjection('entityManager');
|
||||
}
|
||||
|
||||
protected function getAclManager()
|
||||
{
|
||||
return $this->getInjection('aclManager');
|
||||
}
|
||||
|
||||
public function checkReadOnlyTeam(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_object($data) || !isset($data->read)) {
|
||||
return false;
|
||||
}
|
||||
return $data->read === 'team';
|
||||
}
|
||||
|
||||
public function checkReadNo(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_object($data) || !isset($data->read)) {
|
||||
return false;
|
||||
}
|
||||
return $data->read === 'no';
|
||||
}
|
||||
|
||||
public function checkReadOnlyOwn(User $user, $data)
|
||||
{
|
||||
if (empty($data) || !is_object($data) || !isset($data->read)) {
|
||||
return false;
|
||||
}
|
||||
return $data->read === 'own';
|
||||
}
|
||||
|
||||
public function checkEntity(User $user, Entity $entity, $data, $action)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
return $this->checkScope($user, $data, $action, $entity);
|
||||
}
|
||||
|
||||
public function checkScope(User $user, $data, $action = null, Entity $entity = null, $entityAccessData = array())
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_null($data)) {
|
||||
return false;
|
||||
}
|
||||
if ($data === false) {
|
||||
return false;
|
||||
}
|
||||
if ($data === true) {
|
||||
return true;
|
||||
}
|
||||
if (is_string($data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$isOwner = null;
|
||||
if (isset($entityAccessData['isOwner'])) {
|
||||
$isOwner = $entityAccessData['isOwner'];
|
||||
}
|
||||
$inTeam = null;
|
||||
if (isset($entityAccessData['inTeam'])) {
|
||||
$inTeam = $entityAccessData['inTeam'];
|
||||
}
|
||||
|
||||
if (is_null($action)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isset($data->$action)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = $data->$action;
|
||||
|
||||
if ($value === 'all' || $value === 'yes' || $value === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$value || $value === 'no') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($isOwner)) {
|
||||
if ($entity) {
|
||||
$isOwner = $this->checkIsOwner($user, $entity);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isOwner) {
|
||||
if ($value === 'own' || $value === 'team') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (is_null($inTeam) && $entity) {
|
||||
$inTeam = $this->checkInTeam($user, $entity);
|
||||
}
|
||||
|
||||
if ($inTeam) {
|
||||
if ($value === 'team') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkIsOwner(User $user, Entity $entity)
|
||||
{
|
||||
if ($entity->hasAttribute('assignedUserId')) {
|
||||
if ($entity->has('assignedUserId')) {
|
||||
if ($user->id === $entity->get('assignedUserId')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if ($entity->hasAttribute('createdById')) {
|
||||
if ($entity->has('createdById')) {
|
||||
if ($user->id === $entity->get('createdById')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
if ($entity->hasLinkMultipleId('assignedUsers', $user->id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkInTeam(User $user, Entity $entity)
|
||||
{
|
||||
$userTeamIdList = $user->getLinkMultipleIdList('teams');
|
||||
|
||||
if (!$entity->hasRelation('teams') || !$entity->hasAttribute('teamsIds')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$entityTeamIdList = $entity->getLinkMultipleIdList('teams');
|
||||
|
||||
if (empty($entityTeamIdList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($userTeamIdList as $id) {
|
||||
if (in_array($id, $entityTeamIdList)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, $data)
|
||||
{
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->checkEntity($user, $entity, $data, 'delete')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_object($data)) {
|
||||
if ($data->edit !== 'no' || $data->create !== 'no') {
|
||||
if (
|
||||
$this->getConfig()->get('aclAllowDeleteCreated')
|
||||
&&
|
||||
$entity->has('createdById') && $entity->get('createdById') == $user->id
|
||||
) {
|
||||
$isDeletedAllowed = false;
|
||||
if (!$entity->has('assignedUserId')) {
|
||||
$isDeletedAllowed = true;
|
||||
} else {
|
||||
if (!$entity->get('assignedUserId')) {
|
||||
$isDeletedAllowed = true;
|
||||
} else if ($entity->get('assignedUserId') == $entity->get('createdById')) {
|
||||
$isDeletedAllowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isDeletedAllowed) {
|
||||
$createdAt = $entity->get('createdAt');
|
||||
if ($createdAt) {
|
||||
$deleteThresholdPeriod = $this->getConfig()->get('aclAllowDeleteCreatedThresholdPeriod', $this->allowDeleteCreatedThresholdPeriod);
|
||||
if (\Espo\Core\Utils\DateTime::isAfterThreshold($createdAt, $deleteThresholdPeriod)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getOwnerUserIdAttribute(Entity $entity)
|
||||
{
|
||||
if ($this->ownerUserIdAttribute) {
|
||||
return $this->ownerUserIdAttribute;
|
||||
}
|
||||
|
||||
if ($entity->hasLinkMultipleField('assignedUsers')) {
|
||||
return 'assignedUsersIds';
|
||||
}
|
||||
|
||||
if ($entity->hasAttribute('assignedUserId')) {
|
||||
return 'assignedUserId';
|
||||
}
|
||||
|
||||
if ($entity->hasAttribute('createdById')) {
|
||||
return 'createdById';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
application/Espo/Core/Acl/EntityAcl.php
Normal file
41
application/Espo/Core/Acl/EntityAcl.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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\Core\Acl;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
/**
|
||||
* @todo Add methods.
|
||||
*/
|
||||
interface EntityAcl
|
||||
{
|
||||
|
||||
}
|
||||
@@ -29,6 +29,17 @@
|
||||
|
||||
namespace Espo\Core\Acl;
|
||||
|
||||
use Espo\Core\{
|
||||
Utils\Metadata,
|
||||
Utils\DataCache,
|
||||
Utils\FieldUtil,
|
||||
};
|
||||
|
||||
use StdClass;
|
||||
|
||||
/**
|
||||
* Lists of restricted fields can be obtained from here. Restricted fields are specified in metadata > entityAcl.
|
||||
*/
|
||||
class GlobalRestricton
|
||||
{
|
||||
protected $fieldTypeList = [
|
||||
@@ -47,36 +58,32 @@ class GlobalRestricton
|
||||
'nonAdminReadOnly' // read-only for non-admin users
|
||||
];
|
||||
|
||||
protected $cacheFilePath = 'data/cache/application/entityAcl.php';
|
||||
|
||||
private $metadata;
|
||||
|
||||
private $fileManager;
|
||||
|
||||
private $fieldManagerUtil;
|
||||
|
||||
private $data;
|
||||
|
||||
protected $cacheKey = 'entityAcl';
|
||||
|
||||
private $metadata;
|
||||
private $dataCache;
|
||||
private $fieldUtil;
|
||||
|
||||
public function __construct(
|
||||
\Espo\Core\Utils\Metadata $metadata,
|
||||
\Espo\Core\Utils\File\Manager $fileManager,
|
||||
\Espo\Core\Utils\FieldManagerUtil $fieldManagerUtil,
|
||||
bool $useCache = true
|
||||
)
|
||||
{
|
||||
Metadata $metadata, DataCache $dataCache, FieldUtil $fieldUtil, bool $useCache = true
|
||||
) {
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
$this->fieldManagerUtil = $fieldManagerUtil;
|
||||
$this->dataCache = $dataCache;
|
||||
$this->fieldUtil = $fieldUtil;
|
||||
|
||||
$isFromCache = false;
|
||||
|
||||
if ($useCache) {
|
||||
if (file_exists($this->cacheFilePath)) {
|
||||
$this->data = include($this->cacheFilePath);
|
||||
if ($this->dataCache->has($this->cacheKey)) {
|
||||
$this->data = $this->dataCache->get($this->cacheKey);
|
||||
|
||||
$isFromCache = true;
|
||||
|
||||
if (!($this->data instanceof \StdClass)) {
|
||||
if (! $this->data instanceof StdClass) {
|
||||
$GLOBALS['log']->error("ACL GlobalRestricton: Bad data fetched from cache.");
|
||||
|
||||
$this->data = null;
|
||||
}
|
||||
}
|
||||
@@ -95,25 +102,25 @@ class GlobalRestricton
|
||||
|
||||
protected function storeCacheFile()
|
||||
{
|
||||
$this->getFileManager()->putPhpContents($this->cacheFilePath, $this->data, true);
|
||||
$this->dataCache->store($this->cacheKey, $this->data, true);
|
||||
}
|
||||
|
||||
protected function buildData()
|
||||
{
|
||||
$scopeList = array_keys($this->getMetadata()->get(['entityDefs'], []));
|
||||
$scopeList = array_keys($this->metadata->get(['entityDefs'], []));
|
||||
|
||||
$data = (object) [];
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
$fieldList = array_keys($this->getMetadata()->get(['entityDefs', $scope, 'fields'], []));
|
||||
$linkList = array_keys($this->getMetadata()->get(['entityDefs', $scope, 'links'], []));
|
||||
$fieldList = array_keys($this->metadata->get(['entityDefs', $scope, 'fields'], []));
|
||||
$linkList = array_keys($this->metadata->get(['entityDefs', $scope, 'links'], []));
|
||||
|
||||
$isNotEmpty = false;
|
||||
|
||||
$scopeData = (object) [
|
||||
'fields' => (object) [],
|
||||
'attributes' => (object) [],
|
||||
'links' => (object) []
|
||||
'links' => (object) [],
|
||||
];
|
||||
|
||||
foreach ($this->fieldTypeList as $type) {
|
||||
@@ -121,10 +128,13 @@ class GlobalRestricton
|
||||
$resultAttributeList = [];
|
||||
|
||||
foreach ($fieldList as $field) {
|
||||
if ($this->getMetadata()->get(['entityAcl', $scope, 'fields', $field, $type])) {
|
||||
if ($this->metadata->get(['entityAcl', $scope, 'fields', $field, $type])) {
|
||||
$isNotEmpty = true;
|
||||
|
||||
$resultFieldList[] = $field;
|
||||
$fieldAttributeList = $this->getFieldManagerUtil()->getAttributeList($scope, $field);
|
||||
|
||||
$fieldAttributeList = $this->fieldUtil->getAttributeList($scope, $field);
|
||||
|
||||
foreach ($fieldAttributeList as $attribute) {
|
||||
$resultAttributeList[] = $attribute;
|
||||
}
|
||||
@@ -136,9 +146,11 @@ class GlobalRestricton
|
||||
}
|
||||
foreach ($this->linkTypeList as $type) {
|
||||
$resultLinkList = [];
|
||||
|
||||
foreach ($linkList as $link) {
|
||||
if ($this->getMetadata()->get(['entityAcl', $scope, 'links', $link, $type])) {
|
||||
if ($this->metadata->get(['entityAcl', $scope, 'links', $link, $type])) {
|
||||
$isNotEmpty = true;
|
||||
|
||||
$resultLinkList[] = $link;
|
||||
}
|
||||
}
|
||||
@@ -153,44 +165,52 @@ class GlobalRestricton
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
public function getScopeRestrictedFieldList(string $scope, string $type) : array
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
if (!property_exists($this->data, $scope)) {
|
||||
return [];
|
||||
}
|
||||
if (!property_exists($this->data->$scope, 'fields')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
protected function getFieldManagerUtil()
|
||||
{
|
||||
return $this->fieldManagerUtil;
|
||||
}
|
||||
|
||||
public function getScopeRestrictedFieldList($scope, $type)
|
||||
{
|
||||
if (!property_exists($this->data, $scope)) return [];
|
||||
if (!property_exists($this->data->$scope, 'fields')) return [];
|
||||
if (!property_exists($this->data->$scope->fields, $type)) return [];
|
||||
if (!property_exists($this->data->$scope->fields, $type)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->data->$scope->fields->$type;
|
||||
}
|
||||
|
||||
public function getScopeRestrictedAttributeList($scope, $type)
|
||||
public function getScopeRestrictedAttributeList(string $scope, string $type) : array
|
||||
{
|
||||
if (!property_exists($this->data, $scope)) return [];
|
||||
if (!property_exists($this->data->$scope, 'attributes')) return [];
|
||||
if (!property_exists($this->data->$scope->attributes, $type)) return [];
|
||||
if (!property_exists($this->data, $scope)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!property_exists($this->data->$scope, 'attributes')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!property_exists($this->data->$scope->attributes, $type)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->data->$scope->attributes->$type;
|
||||
}
|
||||
|
||||
public function getScopeRestrictedLinkList($scope, $type)
|
||||
public function getScopeRestrictedLinkList(string $scope, string $type) : array
|
||||
{
|
||||
if (!property_exists($this->data, $scope)) return [];
|
||||
if (!property_exists($this->data->$scope, 'links')) return [];
|
||||
if (!property_exists($this->data->$scope->links, $type)) return [];
|
||||
if (!property_exists($this->data, $scope)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!property_exists($this->data->$scope, 'links')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!property_exists($this->data->$scope->links, $type)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->data->$scope->links->$type;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user