Compare commits

...

905 Commits
5.9.3 ... 6.0.8

Author SHA1 Message Date
Yuri Kuznetsov
d3d710b2b9 v 2020-12-04 15:04:36 +02:00
Yuri Kuznetsov
4426d81e77 fix category tree 2020-12-04 14:28:04 +02:00
Yuri Kuznetsov
6b3e81e3fd settings currency validation 2020-12-03 11:56:44 +02:00
Yuri Kuznetsov
dd708778d6 field clone validations 2020-12-03 11:56:15 +02:00
Yuri Kuznetsov
0bc06f3cae fix autofollow 2020-12-02 11:04:33 +02:00
Yuri Kuznetsov
0ab8853455 fix notification for portal user 2020-12-01 13:14:17 +02:00
Yuri Kuznetsov
a612ffd2d2 fix pdf google maps 2020-12-01 11:40:23 +02:00
Yuri Kuznetsov
bc19a6bb5f flotr2 fix 2020-11-30 12:48:53 +02:00
Eymen Elkum
8cc6a2ddf0 fix bc (#1853) 2020-11-29 11:25:07 +02:00
Yuri Kuznetsov
c1f0c47cf7 bc fix 2020-11-28 19:33:12 +02:00
Yuri Kuznetsov
7e71eb0aeb fix warning 2020-11-27 18:42:52 +02:00
Taras Machyshyn
196f787a1f Fix installer for PHP 8 2020-11-27 17:32:00 +02:00
Taras Machyshyn
b7bec1793c Fix installer for PHP 8 2020-11-27 12:26:57 +02:00
Taras Machyshyn
b97aa8e3a7 Fix gitignore 2020-11-27 12:26:30 +02:00
Taras Machyshyn
21dcf59f21 Fix gitignore 2020-11-27 12:25:06 +02:00
Taras Machyshyn
326b6c8c53 Merge branch 'hotfix/6.0.7' of https://github.com/espocrm/espocrm into hotfix/6.0.7 2020-11-27 12:16:34 +02:00
Taras Machyshyn
7ebf0e7bf8 Fix installer for PHP 8 2020-11-27 12:16:01 +02:00
Yuri Kuznetsov
014df8b9d3 Merge branch 'hotfix/6.0.7' of github.com:espocrm/espocrm into hotfix/6.0.7 2020-11-27 12:12:28 +02:00
Yuri Kuznetsov
6d85055147 fix loaders 2020-11-27 12:12:16 +02:00
Taras Machyshyn
077f7d8855 Fix installer for PHP 8 2020-11-27 12:03:04 +02:00
Taras Machyshyn
296484360f Fix installer for PHP 8 2020-11-27 11:03:40 +02:00
Yuri Kuznetsov
1071f8a045 v 2020-11-26 12:09:45 +02:00
Yuri Kuznetsov
962d3a049c disable edit access to user email address 2020-11-26 09:44:22 +02:00
Yuri Kuznetsov
161859606a ceanup 2020-11-21 14:20:14 +02:00
Yuri Kuznetsov
a71df0cff6 fix layout 2020-11-20 09:52:54 +02:00
Yuri Kuznetsov
fb9ff0b8c0 fix deprecated 2020-11-18 13:16:24 +02:00
Yuri Kuznetsov
d1a62baa12 fix deprecated 2020-11-18 12:53:17 +02:00
Yuri Kuznetsov
cdec7ccfe8 v 2020-11-18 11:34:14 +02:00
Yuri Kuznetsov
25bc3a40f7 fix export currency 2020-11-18 09:41:54 +02:00
Yuri Kuznetsov
02e5c1fc44 v 2020-11-16 13:40:49 +02:00
Yuri Kuznetsov
844e9dd8e3 Merge branch 'hotfix/6.0.5' of github.com:espocrm/espocrm into hotfix/6.0.5 2020-11-16 13:38:16 +02:00
Yuri Kuznetsov
39f2ec83d5 fix duplicate attachments multiple 2020-11-16 13:35:53 +02:00
Taras Machyshyn
e4d2af03a5 Fixed PHP binary path 2020-11-16 13:34:24 +02:00
Taras Machyshyn
37616d69bf Merge branch 'hotfix/6.0.5' of https://github.com/espocrm/espocrm into hotfix/6.0.5 2020-11-16 13:28:03 +02:00
Taras Machyshyn
4e36f71dd8 Fixed PHP binary path 2020-11-16 13:27:16 +02:00
Yuri Kuznetsov
b5877ac32a fix person name 2020-11-16 13:03:56 +02:00
Yuri Kuznetsov
92de588a6e update npm packages 2020-11-16 11:07:12 +02:00
Yuri Kuznetsov
700f4b5b10 fix export 2020-11-14 10:24:22 +02:00
Yuri Kuznetsov
9c0a7b6778 app service changes 2020-11-13 12:39:27 +02:00
Yuri Kuznetsov
9a54c66f68 preferences fixes 2020-11-13 12:32:13 +02:00
Yuri Kuznetsov
83332178a0 fix acl check command 2020-11-12 15:05:03 +02:00
Yuri Kuznetsov
fb33c2acf1 fix task panel layout 2020-11-10 12:48:40 +02:00
Yuri Kuznetsov
3c5914b5d9 fix text filter by foreign field 2020-11-10 09:22:20 +02:00
Taras Machyshyn
8c48f72a3c Command fix 2020-11-09 15:16:30 +02:00
Taras Machyshyn
a8ce780718 Upgrade fix 2020-11-04 10:23:07 +02:00
Yuri Kuznetsov
31eff86578 fix link search blur 2020-11-03 16:44:20 +02:00
Yuri Kuznetsov
892f9f01f6 export xlsx currency format 2020-11-03 10:43:33 +02:00
Yuri Kuznetsov
860a58847d currency format 10 $ 2020-11-03 10:03:12 +02:00
Yuri Kuznetsov
1ed90d2306 v 2020-11-02 12:55:01 +02:00
Yuri Kuznetsov
aff0b350f3 fix portal runner 2020-11-02 12:54:13 +02:00
Yuri Kuznetsov
651b0be5ed add log to slim 2020-10-31 13:38:11 +02:00
Yuri Kuznetsov
cead33c09d template manager image 2020-10-30 09:26:37 +02:00
Yuri Kuznetsov
80602c084f fix pdf page number 2020-10-29 16:34:49 +02:00
Yuri Kuznetsov
b0420b8b93 fix email folder 2020-10-28 13:19:49 +02:00
Yuri Kuznetsov
b47018cbab hide email menu items in portal 2020-10-28 11:58:44 +02:00
Yuri Kuznetsov
ea69ab6eaf v 2020-10-28 11:12:51 +02:00
Eymen Elkum
92887401b2 address view remove duplicated codes (#1823) 2020-10-28 11:10:52 +02:00
Yuri Kuznetsov
df0bda6324 Merge branch 'hotfix/6.0.3' of github.com:espocrm/espocrm into hotfix/6.0.3 2020-10-28 11:05:37 +02:00
Yuri Kuznetsov
9d67808496 fix tester 2020-10-28 11:02:24 +02:00
Yuri Kuznetsov
cf33a98f20 fix activities and select manager 2020-10-27 17:04:49 +02:00
Yuri Kuznetsov
afbda344ec fix export specific fields 2020-10-27 14:25:47 +02:00
Yuri Kuznetsov
1079597584 fix 2fa 2020-10-27 14:13:00 +02:00
Yuri Kuznetsov
af9b411a4c diff all patch versions 2020-10-27 12:07:39 +02:00
Yuri Kuznetsov
cd49d951d8 v 2020-10-27 11:59:55 +02:00
Yuri Kuznetsov
7d63c114aa fix export all fields 2020-10-27 11:06:52 +02:00
Yuri Kuznetsov
af6f05ba07 formula fix logical operator priority 2020-10-27 10:31:42 +02:00
Yuri Kuznetsov
46f8eb0cdb formula fix logical not 2020-10-27 10:23:03 +02:00
Pomazan Bogdan
c543bb5a5b Update Admin.json (#1814) 2020-10-26 15:36:46 +02:00
Yuri Kuznetsov
d1997089e4 v 2020-10-26 13:06:11 +02:00
Yuri Kuznetsov
57dd0177f9 fix export 2020-10-25 18:56:57 +02:00
Yuri Kuznetsov
ba76e5ee3d fix language manager 2020-10-25 18:54:34 +02:00
Yuri Kuznetsov
76c93b842c case close reject actions only if available in status list 2020-10-23 10:25:26 +03:00
Yuri Kuznetsov
e73bff5ddf v 2020-10-22 12:14:40 +03:00
Yuri Kuznetsov
7d5c0d754e fix upgrade script 2020-10-22 11:47:59 +03:00
Taras Machyshyn
e08a74b129 Bug fixes 2020-10-22 11:30:00 +03:00
Taras Machyshyn
be07aafaf4 Fix 2020-10-21 15:33:42 +03:00
Taras Machyshyn
e2bf27e524 Fix 2020-10-21 12:00:47 +03:00
Yuri Kuznetsov
b0157adbe2 cs fix 2020-10-21 09:40:34 +03:00
Yuri Kuznetsov
239593afb5 fix mass actions 2020-10-21 09:31:42 +03:00
Yuri Kuznetsov
b97d764588 fix error msg 2020-10-19 15:30:36 +03:00
Yuri Kuznetsov
bf8e7af984 export fixes 2020-10-19 15:19:24 +03:00
Yuri Kuznetsov
bf68c475e5 email queue items filters email 2020-10-19 13:37:06 +03:00
Yuri Kuznetsov
29624239ba search queue items 2020-10-19 13:35:43 +03:00
Yuri Kuznetsov
4cb3c4918b campaign log search by email address 2020-10-19 12:59:36 +03:00
Yuri Kuznetsov
26fa0d65e1 fix campaign log search 2020-10-19 12:57:17 +03:00
Yuri Kuznetsov
958baed3df fix email invalid on bounced 2020-10-19 12:35:48 +03:00
Yuri Kuznetsov
40d6fb7565 fix export 2020-10-15 19:40:37 +03:00
Yuri Kuznetsov
a7551b7dbf fix request getContentType 2020-10-15 17:35:58 +03:00
Yuri Kuznetsov
9ed33c4dc4 remove self assign in portal 2020-10-14 16:23:02 +03:00
Yuri Kuznetsov
6b18fbe8f7 select manager fix 2020-10-14 15:48:52 +03:00
Yuri Kuznetsov
53b9880ea8 entry point changes 2020-10-14 15:15:09 +03:00
Yuri Kuznetsov
62538664df Merge branch 'master' of github.com:espocrm/espocrm 2020-10-14 13:17:56 +03:00
Yuri Kuznetsov
f678fb16cc ouauth callback changes 2020-10-14 13:17:46 +03:00
Yuri Kuznetsov
fe09aa1cd9 cs fix 2020-10-13 11:01:52 +03:00
Yuri Kuznetsov
710decc610 fix htmlizer and email template no id 2020-10-13 10:47:37 +03:00
Yuri Kuznetsov
5d481d3528 email auto reply error log 2020-10-13 10:47:27 +03:00
Yuri Kuznetsov
8bcd3b72c5 hook fix 2020-10-13 09:56:13 +03:00
Yuri Kuznetsov
0a0da810e9 application state changes 2020-10-13 09:56:04 +03:00
Yuri Kuznetsov
e630c046fe Merge branch 'hotfix/5.9.5' 2020-10-12 14:01:49 +03:00
Yuri Kuznetsov
2857b5c53d fix import button 2020-10-12 14:00:25 +03:00
Yuri Kuznetsov
0965c61f55 fix reminder submition 2020-10-12 10:14:17 +03:00
Yuri Kuznetsov
9dd318b176 fix label 2020-10-10 16:08:58 +03:00
Yuri Kuznetsov
f8beca720c label fixes 2020-10-10 16:06:57 +03:00
Yuri Kuznetsov
d8f58dcc1d upgrade cleanup 2020-10-09 14:58:34 +03:00
Yuri Kuznetsov
32aaaa350e v 2020-10-09 14:37:50 +03:00
Yuri Kuznetsov
0f6d1c6817 fix diff: ignore upgrades 2020-10-09 13:56:41 +03:00
Yuri Kuznetsov
8c5a342a5a fix diff 2020-10-09 13:53:07 +03:00
Yuri Kuznetsov
257401898b upgrade cleanup files and fix msg 2020-10-09 12:24:24 +03:00
Yuri Kuznetsov
e7ff3f903a fix email modal 2020-10-08 14:05:28 +03:00
Taras Machyshyn
6f82638b5d Upgrade script 2020-10-07 17:46:08 +03:00
Taras Machyshyn
0625ce51c4 Upgrade script 2020-10-07 17:26:11 +03:00
Taras Machyshyn
f5670436d0 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-07 17:19:05 +03:00
Taras Machyshyn
5d20a56ac8 Upgrade script 2020-10-07 17:18:34 +03:00
Yuri Kuznetsov
020cf9713a Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-07 16:49:33 +03:00
Yuri Kuznetsov
fe1361fc9c portal action list restriction 2020-10-07 16:49:01 +03:00
Taras Machyshyn
36621be496 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-07 15:51:31 +03:00
Taras Machyshyn
25690030d1 Installation fixes 2020-10-07 15:50:57 +03:00
Yuri Kuznetsov
fcd6be3a0c fix password recovery 2020-10-07 15:39:03 +03:00
Yuri Kuznetsov
ad8dfa487c fix convert lead 2020-10-07 15:13:39 +03:00
Yuri Kuznetsov
7f6f54628d cs fix 2020-10-07 15:04:42 +03:00
Taras Machyshyn
8ea0b072c6 Installation fixes 2020-10-07 14:22:21 +03:00
Yuri Kuznetsov
0df6248226 getPhpSafeContents for unix 2020-10-07 13:12:55 +03:00
Yuri Kuznetsov
26a132658e date after before validation autocomplete 2020-10-07 12:42:51 +03:00
Yuri Kuznetsov
d02529ee86 Merge branch 'hotfix/5.9.5' 2020-10-07 11:02:01 +03:00
Yuri Kuznetsov
0cec0fef51 fix image orientation 2020-10-07 11:01:32 +03:00
Yuri Kuznetsov
e56f6ab75d fix image orientation 2020-10-07 10:55:39 +03:00
Yuri Kuznetsov
a4980aa8f2 cs fix 2020-10-07 10:53:21 +03:00
Yuri Kuznetsov
fd219b49be calendar modal fix 2020-10-06 13:44:35 +03:00
Yuri Kuznetsov
b90579aadc cs fix 2020-10-06 13:44:18 +03:00
Yuri Kuznetsov
0b39d7f6b6 cs fix 2020-10-06 12:13:17 +03:00
Yuri Kuznetsov
a44ce06162 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-06 12:02:35 +03:00
Yuri Kuznetsov
f1eb2ab5d5 cs fix 2020-10-06 12:00:48 +03:00
Yuri Kuznetsov
9a965bfba4 v 2020-10-05 15:27:48 +03:00
Yuri Kuznetsov
7349f37786 fix admin panel 2020-10-05 12:21:11 +03:00
Yuri Kuznetsov
3d03dfaef7 css fix 2020-10-03 19:01:19 +03:00
Yuri Kuznetsov
5bf88eaff1 categories tree improvements 2020-10-03 18:59:56 +03:00
Yuri Kuznetsov
f3c4b2ba39 image preview improvements 2020-10-03 17:24:05 +03:00
Yuri Kuznetsov
92f6fb4588 settings tooltips 2020-10-03 12:27:54 +03:00
Yuri Kuznetsov
2d6d7fd618 list tree css fix 2020-10-02 14:57:26 +03:00
Yuri Kuznetsov
3a1d997d5a orm cleanup 2020-10-01 20:18:35 +03:00
Yuri Kuznetsov
5bbb259c95 orm fix order list 2020-10-01 20:16:32 +03:00
Yuri Kuznetsov
b8e44767b3 upgrade real estate compatibility check 2020-10-01 16:27:46 +03:00
Yuri Kuznetsov
6b486beb5c fix autoload 2020-10-01 14:25:12 +03:00
Yuri Kuznetsov
aab1265e4e data cache get safe contents 2020-10-01 14:08:03 +03:00
Yuri Kuznetsov
676181a4be fix ldap 2020-10-01 13:32:06 +03:00
Yuri Kuznetsov
839e5b7c74 data cache support onlt array and stdclass 2020-10-01 12:51:25 +03:00
Yuri Kuznetsov
aff7003ceb cs fix 2020-10-01 12:01:51 +03:00
Yuri Kuznetsov
66aa60f303 file rename in loop for windows 2020-10-01 11:44:01 +03:00
Yuri Kuznetsov
b196811cf9 fix notice 2020-10-01 10:24:36 +03:00
Yuri Kuznetsov
3fdddadd53 cs fix 2020-09-30 17:42:07 +03:00
Yuri Kuznetsov
7af2d1d3ac v 2020-09-30 15:00:22 +03:00
Yuri Kuznetsov
63670e3245 ldap fix 2020-09-30 12:24:36 +03:00
Yuri Kuznetsov
389931bf22 cs fix 2020-09-30 12:24:31 +03:00
Yuri Kuznetsov
76a67d15a3 ldap fix 2020-09-30 12:18:17 +03:00
Yuri Kuznetsov
8e65f2d375 cleanup 2020-09-30 12:17:58 +03:00
Yuri Kuznetsov
56737f5d67 ldap fix 2020-09-30 12:04:22 +03:00
Yuri Kuznetsov
20f8fae2f0 fix email import 2020-09-30 10:16:58 +03:00
Yuri Kuznetsov
17b5d77d33 fix json function 2020-09-30 09:44:45 +03:00
Yuri Kuznetsov
cbe32c88b6 email: move to folder from trash 2020-09-30 09:18:22 +03:00
Yuri Kuznetsov
dee291f3f6 email folder select modal css fix 2020-09-30 09:13:59 +03:00
Yuri Kuznetsov
0b20c8e13f fix docs link 2020-09-29 15:16:32 +03:00
Yuri Kuznetsov
c0af0173e9 json retrieve function 2020-09-29 13:28:39 +03:00
Yuri Kuznetsov
79f4c4b5d2 cs fix 2020-09-29 13:07:48 +03:00
Yuri Kuznetsov
31c8be2ee1 cs fixes 2020-09-29 10:06:49 +03:00
Yuri Kuznetsov
061b237032 portal fixes 2020-09-29 10:05:54 +03:00
Yuri Kuznetsov
d3466e201d fix 2020-09-29 09:38:43 +03:00
Taras Machyshyn
c69c7d2194 Added new options in upgrade command 2020-09-28 19:46:19 +03:00
Yuri Kuznetsov
05e1624e47 fix notice 2020-09-28 16:04:18 +03:00
Yuri Kuznetsov
03e32412ca varchar 150 max length by default 2020-09-28 15:25:58 +03:00
Yuri Kuznetsov
451a2376a8 fix field manager 2020-09-28 15:22:38 +03:00
Yuri Kuznetsov
167c774446 email: only read access in poral roles 2020-09-28 15:11:08 +03:00
Yuri Kuznetsov
054262a002 fix tester 2020-09-28 13:10:26 +03:00
Yuri Kuznetsov
ecbc3c537f cs fix 2020-09-28 12:57:25 +03:00
Yuri Kuznetsov
d51bbfdfab fix portal role clear cache 2020-09-28 12:36:09 +03:00
Yuri Kuznetsov
ae343cddbe fix dashlet layout field 2020-09-28 12:20:38 +03:00
Yuri Kuznetsov
bb03fec604 portal index refactoring 2020-09-25 15:13:37 +03:00
Yuri Kuznetsov
248c9a6b00 entry point route detection 2020-09-25 14:46:18 +03:00
Yuri Kuznetsov
dec5e0be5f cs fix 2020-09-25 13:26:22 +03:00
Yuri Kuznetsov
bcbb29d94e fix portal list view url 2020-09-25 13:09:17 +03:00
Yuri Kuznetsov
3e2f995ba8 v 2020-09-25 12:39:50 +03:00
Yuri Kuznetsov
56b3b9d94d Merge branch 'master' of github.com:espocrm/espocrm 2020-09-25 12:16:01 +03:00
Yuri Kuznetsov
9b2ac0d443 fix record grid 2020-09-25 12:15:48 +03:00
Yuri Kuznetsov
3ee78c29cb cs fixes 2020-09-25 10:24:14 +03:00
Yuri Kuznetsov
548e829f2f cs fix 2020-09-25 10:16:05 +03:00
Taras Machyshyn
749c161aaa Upgrade fixes 2020-09-23 19:31:52 +03:00
Yuri Kuznetsov
aee6b99a47 fix language 2020-09-23 15:45:26 +03:00
Yuri Kuznetsov
700262e07b cleanup 2020-09-23 12:37:50 +03:00
Yuri Kuznetsov
c4cd9d3ee8 manual merge 2020-09-23 12:23:56 +03:00
Yuri Kuznetsov
235d8f2264 package lock version 2020-09-23 11:14:29 +03:00
Yuri Kuznetsov
6268f84b45 upgrade command fixes 2020-09-23 10:36:00 +03:00
Yuri Kuznetsov
e2b49931c3 Merge branch 'hotfix/5.9.4' 2020-09-23 10:18:25 +03:00
Yuri Kuznetsov
9cfab5a7ea upgrade fix 2020-09-23 10:17:07 +03:00
Yuri Kuznetsov
66114e4748 bc fix 2020-09-22 15:38:30 +03:00
Yuri Kuznetsov
4ea9868285 email account fixes 2020-09-22 15:24:49 +03:00
Yuri Kuznetsov
2c09eacbd4 fix bc 2020-09-22 14:48:40 +03:00
Yuri Kuznetsov
2d5c01f25d fix upgrade 2020-09-22 13:20:32 +03:00
Yuri Kuznetsov
9610695701 fix email account 2020-09-22 10:01:00 +03:00
Yuri Kuznetsov
b7062a2b75 imap: support tls 2020-09-22 09:53:01 +03:00
Yuri Kuznetsov
3100d43af0 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-09-21 17:41:12 +03:00
Yuri Kuznetsov
53606cbde5 cs fix 2020-09-21 17:40:56 +03:00
Yuri Kuznetsov
ca6d1d24f4 fix tests 2020-09-21 15:24:27 +03:00
Yuri Kuznetsov
928a8c75e8 data cache usage 2020-09-21 15:12:35 +03:00
Yuri Kuznetsov
693df2d6fb data cache usage 2020-09-21 14:43:36 +03:00
Yuri Kuznetsov
bc3cea0b86 Data Cache usage 2020-09-21 14:14:59 +03:00
Yuri Kuznetsov
feba3cd05e fix varexport 2020-09-21 12:02:54 +03:00
Yuri Kuznetsov
e6b31b8c45 data cache usage 2020-09-21 11:48:49 +03:00
Yuri Kuznetsov
79efc87ed2 data cache usage 2020-09-21 11:40:26 +03:00
Yuri Kuznetsov
e17b88ca74 data cache usage 2020-09-21 11:30:07 +03:00
Yuri Kuznetsov
0020a5ea4a data cache usage 2020-09-21 11:20:56 +03:00
Yuri Kuznetsov
5778167b01 amend 2020-09-21 11:18:39 +03:00
Yuri Kuznetsov
2b11414445 var export fix 2020-09-21 11:16:23 +03:00
Yuri Kuznetsov
e7b51ef61d using data cache 2020-09-20 20:44:09 +03:00
Yuri Kuznetsov
ca969ee79b change metadata loader 2020-09-20 20:12:55 +03:00
Yuri Kuznetsov
9ff62f9e28 cs fix 2020-09-20 16:57:48 +03:00
Yuri Kuznetsov
5c5cbf2933 fix test 2020-09-20 16:10:28 +03:00
Yuri Kuznetsov
91c5caee63 DataCache util 2020-09-20 15:56:03 +03:00
Yuri Kuznetsov
7aa439efbb comments fix 2020-09-20 14:04:08 +03:00
Yuri Kuznetsov
7baf49aa7e cs fix 2020-09-19 23:59:59 +03:00
Yuri Kuznetsov
d7476c1de8 fix class parser 2020-09-19 16:43:07 +03:00
Yuri Kuznetsov
d3e99a6de8 cron manager fix 2020-09-19 16:28:31 +03:00
Yuri Kuznetsov
893f9d50c3 cs fixes and array values cleanup 2020-09-19 16:19:55 +03:00
Yuri Kuznetsov
a565766fcb cs fix 2020-09-19 15:46:49 +03:00
Yuri Kuznetsov
89e517e47b array value: use transactions 2020-09-19 15:45:15 +03:00
Yuri Kuznetsov
39d51bb68f cs fix 2020-09-19 14:20:52 +03:00
Yuri Kuznetsov
5e3168039a emailaddress phonenumber repository fixes 2020-09-19 14:00:07 +03:00
Yuri Kuznetsov
f75062694f rebuild fixes 2020-09-18 17:27:02 +03:00
Yuri Kuznetsov
cb3c3f18ee css changes 2020-09-18 15:07:42 +03:00
Yuri Kuznetsov
2415b29d45 css change 2020-09-18 14:40:06 +03:00
Yuri Kuznetsov
7fb162be77 dashboard fixes 2020-09-18 11:38:57 +03:00
Yuri Kuznetsov
bf93834fd3 refactoring 2020-09-17 20:17:07 +03:00
Yuri Kuznetsov
63452d1bb2 update bull 2020-09-17 17:46:57 +03:00
Yuri Kuznetsov
5e26dbd870 preload gridstack 2020-09-17 17:23:45 +03:00
Yuri Kuznetsov
fb782d67ed loader improvement 2020-09-17 17:23:30 +03:00
Yuri Kuznetsov
864c91cd18 css fix 2020-09-17 16:54:17 +03:00
Yuri Kuznetsov
038479564b update gridstack 2020-09-17 16:50:14 +03:00
Yuri Kuznetsov
08c0dfc4ef fix dashboard template 2020-09-17 16:32:41 +03:00
Yuri Kuznetsov
019291b707 css changes 2020-09-17 14:36:59 +03:00
Yuri Kuznetsov
1d84bbb548 fix warning 2020-09-17 12:52:18 +03:00
Yuri Kuznetsov
5ceb5c848e field converer class name in metadata 2020-09-17 11:14:13 +03:00
Yuri Kuznetsov
b00e94bae9 get rid of phone and email attribute types 2020-09-17 10:57:10 +03:00
Yuri Kuznetsov
46f6584577 lead capture tool 2020-09-17 10:46:51 +03:00
Yuri Kuznetsov
e3c651fcb9 Merge branch 'hotfix/5.9.4' 2020-09-16 13:46:29 +03:00
Yuri Kuznetsov
86a85ba177 Merge branch 'hotfix/5.9.4' of github.com:espocrm/espocrm into hotfix/5.9.4 2020-09-16 13:45:25 +03:00
Yuri Kuznetsov
36a4cb2451 fix formula int parsing 2020-09-16 13:44:56 +03:00
Yuri Kuznetsov
ab726e9490 fix formula int parsing 2020-09-16 13:43:46 +03:00
Yuri Kuznetsov
b9f75395b6 fix portal route 2020-09-16 13:03:02 +03:00
Yuri Kuznetsov
c0e4f83d83 fix mention hook 2020-09-16 12:53:28 +03:00
Yuri Kuznetsov
08e94694b2 fix lead capture 2020-09-16 12:51:13 +03:00
Yuri Kuznetsov
5112fd4fd3 fix export csv 2020-09-16 12:16:55 +03:00
Yuri Kuznetsov
2aafc6a82e test email error message 2020-09-16 11:51:23 +03:00
Yuri Kuznetsov
1f200d53f8 fix import update foreign 2020-09-16 11:07:32 +03:00
Yuri Kuznetsov
77a5c75007 orm: fix insert query 2020-09-16 10:50:58 +03:00
Yuri Kuznetsov
c44d4357a7 fix foreign phone number 2020-09-15 17:27:56 +03:00
Yuri Kuznetsov
2bf70e88ba fix repository usage 2020-09-15 15:29:09 +03:00
Yuri Kuznetsov
442bb998e4 Merge branch 'hotfix/5.9.4' 2020-09-15 14:34:22 +03:00
Eymen Elkum
6f60a73c62 minor fix (#1785) 2020-09-15 14:33:53 +03:00
Yuri Kuznetsov
106a5a77e7 upgrade extension check 2020-09-15 13:48:51 +03:00
Yuri Kuznetsov
2f3f13f34c list view image fit height 2020-09-15 13:34:06 +03:00
Yuri Kuznetsov
bc4a9a07b6 diff deleted fix 2020-09-15 12:53:45 +03:00
Yuri Kuznetsov
5ca5ee55ee fix diff 2020-09-15 12:25:18 +03:00
Yuri Kuznetsov
08636b550f upgrade cli check 2020-09-15 11:25:49 +03:00
Yuri Kuznetsov
b2aab26ded Merge branch 'master' of https://github.com/espocrm/espocrm 2020-09-15 11:01:58 +03:00
Yuri Kuznetsov
6d629d40e6 upgrade 6.0 changes 2020-09-15 11:01:41 +03:00
Yuri Kuznetsov
6e433ec9a4 diff fix 2020-09-15 10:43:26 +03:00
Yuri Kuznetsov
802a0229fa comment 2020-09-14 12:59:32 +03:00
Yuri Kuznetsov
41b4b86033 acl manager fix 2020-09-14 12:56:06 +03:00
Yuri Kuznetsov
63dca2712b fix action history 2020-09-14 12:40:14 +03:00
Yuri Kuznetsov
e06d104e10 bc fix 2020-09-14 12:15:09 +03:00
Yuri Kuznetsov
4ab2ee875e fix task 2020-09-14 11:55:58 +03:00
Yuri Kuznetsov
ac8debbb4b cs fixes and docs 2020-09-12 09:40:56 +03:00
Yuri Kuznetsov
8a7a2071b6 refactoring and route duplicate check 2020-09-11 22:59:11 +03:00
Yuri Kuznetsov
df471cf5a0 small fix 2020-09-11 17:29:15 +03:00
Yuri Kuznetsov
79665cc552 remove route duplicate check and cleanup 2020-09-11 17:23:59 +03:00
Taras Machyshyn
9c6932b124 Router fixes 2020-09-11 16:59:39 +03:00
Yuri Kuznetsov
4e30caf894 cleanup 2020-09-11 14:02:57 +03:00
Yuri Kuznetsov
1bbff54c07 orm usage fix 2020-09-11 13:41:44 +03:00
Yuri Kuznetsov
81ccf2a860 acceptance status fix 2020-09-11 13:32:12 +03:00
Yuri Kuznetsov
463007b218 refactor error output 2020-09-11 13:07:19 +03:00
Yuri Kuznetsov
ee53fffc67 refactor route processing 2020-09-11 12:33:35 +03:00
Taras Machyshyn
63351ed6b7 Integration tests fixes 2020-09-10 18:12:22 +03:00
Yuri Kuznetsov
87ba6f6ccc fix bc 2020-09-10 17:13:52 +03:00
Yuri Kuznetsov
efeceb3a5b fix admin ui 2020-09-10 16:56:14 +03:00
Yuri Kuznetsov
bb6fddad09 fix import 2020-09-10 16:49:41 +03:00
Yuri Kuznetsov
def9f6b70c cs fix 2020-09-10 16:34:02 +03:00
Yuri Kuznetsov
95bbbb1daa fix record service 2020-09-10 16:10:23 +03:00
Yuri Kuznetsov
0c759b9016 fix additionalTables 2020-09-10 16:03:34 +03:00
Yuri Kuznetsov
cb2d2dd363 code style fix 2020-09-10 12:54:24 +03:00
Taras Machyshyn
88948c4b66 BeforeUpgrade script 2020-09-10 12:35:42 +03:00
Yuri Kuznetsov
799626cfdc entity deprecated log 2020-09-10 12:13:47 +03:00
Yuri Kuznetsov
ab82a8748f fix orm usage and cs fix 2020-09-10 11:12:21 +03:00
Yuri Kuznetsov
6f78840aec orm usage fix 2020-09-10 11:00:50 +03:00
Yuri Kuznetsov
b94dc3c733 cs fix 2020-09-10 10:59:56 +03:00
Yuri Kuznetsov
de3c6bc45b cs fix 2020-09-10 10:34:45 +03:00
Yuri Kuznetsov
c17ae13fcf language functions 2020-09-10 10:29:36 +03:00
Yuri Kuznetsov
e936ecbabd duplicate ui fix 2020-09-10 10:20:33 +03:00
Yuri Kuznetsov
0f5105fee2 upgrade cleanup 2020-09-09 16:44:10 +03:00
Yuri Kuznetsov
07571ecc32 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-09-09 16:43:21 +03:00
Yuri Kuznetsov
3a4bc97abb revert 2020-09-09 16:43:12 +03:00
Taras Machyshyn
412966d8d0 Upgrade script: fixes 2020-09-09 16:10:46 +03:00
Taras Machyshyn
d8bf6048c1 Upgrade script: check MyISAM 2020-09-09 15:49:58 +03:00
Yuri Kuznetsov
f13f72ea16 fix upgrade 2020-09-09 15:11:46 +03:00
Yuri Kuznetsov
a7818227bd fixes 2020-09-09 12:36:37 +03:00
Yuri Kuznetsov
a4c45ecdcd fix grunt 2020-09-09 12:15:48 +03:00
Yuri Kuznetsov
a21671f1b7 entityManagerProxy 2020-09-09 12:09:09 +03:00
Yuri Kuznetsov
3fc0349550 fixes 2020-09-09 11:37:32 +03:00
Yuri Kuznetsov
fa177c41b7 v 2020-09-09 10:24:38 +03:00
Yuri Kuznetsov
f3675fb838 Merge branch 'hotfix/5.9.4' 2020-09-08 17:42:43 +03:00
Yuri Kuznetsov
72fd9184f4 fix link manager ui 2020-09-08 17:42:19 +03:00
Yuri Kuznetsov
2196020705 import refactoring 2020-09-08 17:29:59 +03:00
Yuri Kuznetsov
81465a50d6 do not allow sub dirs for services 2020-09-08 16:42:09 +03:00
Yuri Kuznetsov
a0ccbfcac5 container cleanup 2020-09-08 16:40:05 +03:00
Yuri Kuznetsov
eaa3cf6137 container services cleanup 2020-09-08 16:08:18 +03:00
Yuri Kuznetsov
32d4e2f281 fix orm usage 2020-09-08 15:51:33 +03:00
Yuri Kuznetsov
6454f6843b fix entity manager ui reset to default 2020-09-08 15:48:05 +03:00
Yuri Kuznetsov
22e67d39b0 fix portal preferences layout 2020-09-08 15:29:43 +03:00
Yuri Kuznetsov
7efbf6fd66 fix tests 2020-09-08 13:33:57 +03:00
Yuri Kuznetsov
eaf9c97f52 mass email: set teams for sent emails 2020-09-08 12:32:52 +03:00
Yuri Kuznetsov
5f7cee768d cs fixes 2020-09-08 12:27:32 +03:00
Yuri Kuznetsov
9c3b0aa289 console command exit 2020-09-08 12:09:02 +03:00
Yuri Kuznetsov
b3bf52bd9b console command no exception 2020-09-08 12:07:58 +03:00
Yuri Kuznetsov
1f07688881 import console command in classes 2020-09-08 12:03:19 +03:00
Yuri Kuznetsov
aafa30dbf9 export tool rename 2020-09-08 11:51:24 +03:00
Yuri Kuznetsov
e8f2e5efd1 import tool 2020-09-08 11:48:12 +03:00
Yuri Kuznetsov
c39e5bc02c fix controller manager 2020-09-08 11:21:53 +03:00
Yuri Kuznetsov
6576b5ef79 tools changes 2020-09-07 17:20:56 +03:00
o-data
bec4b2d627 Fix typo error for the word "unsubsribe" (previously: "unsubsbribe") (#1779)
* Update EmailTemplate.json

https://forum.espocrm.com/forum/bug-reports/62259-tipos-in-emailtemplate-create

* Update EmailTemplate.json

https://forum.espocrm.com/forum/bug-reports/62259-tipos-in-emailtemplate-create

* Update EmailTemplate.json

https://forum.espocrm.com/forum/bug-reports/62259-tipos-in-emailtemplate-create

* Update EmailTemplate.json

* Update EmailTemplate.json

https://forum.espocrm.com/forum/bug-reports/62259-tipos-in-emailtemplate-create
2020-09-07 15:42:39 +03:00
Yuri Kuznetsov
a36798534d fix 2020-09-07 14:58:33 +03:00
Yuri Kuznetsov
dbd945e828 cleanup 2020-09-07 14:56:02 +03:00
Yuri Kuznetsov
b5655bf8ee fixes 2020-09-07 14:42:44 +03:00
Yuri Kuznetsov
3637cf4512 list export in tools 2020-09-07 14:20:44 +03:00
Yuri Kuznetsov
4693d2aae8 fix tests 2020-09-07 13:01:06 +03:00
Yuri Kuznetsov
ece49bc4dd label manager in tool 2020-09-07 12:50:02 +03:00
Yuri Kuznetsov
f60115f18d entity manager in tools 2020-09-07 12:30:59 +03:00
Yuri Kuznetsov
90fdbc872e fieldUtil usage 2020-09-07 09:29:27 +03:00
Yuri Kuznetsov
7d5ad5d030 naming fix 2020-09-07 09:00:53 +03:00
Yuri Kuznetsov
bd0e7909a1 field manager hook refactor 2020-09-06 22:30:45 +03:00
Yuri Kuznetsov
cf3229a3c9 field manager tool 2020-09-06 22:11:48 +03:00
Yuri Kuznetsov
407f5fa53a classes folder 2020-09-06 15:54:44 +03:00
Yuri Kuznetsov
b1edce46ff cs fix 2020-09-06 11:12:52 +03:00
Yuri Kuznetsov
551ed091e7 cleanup 2020-09-04 15:38:37 +03:00
Yuri Kuznetsov
7645fa4e90 emailSender usage and fixes 2020-09-04 15:35:09 +03:00
Yuri Kuznetsov
396ce79d22 cleanup 2020-09-04 15:08:24 +03:00
Yuri Kuznetsov
60ad79fd64 email sending fixes and changes 2020-09-04 15:07:18 +03:00
Yuri Kuznetsov
2c9a6aa456 fix exception 2020-09-04 12:50:18 +03:00
Yuri Kuznetsov
3577dfda9f fix exception 2020-09-04 12:33:37 +03:00
Yuri Kuznetsov
31549f2851 duplicate handling change 2020-09-04 12:08:04 +03:00
Yuri Kuznetsov
c8ea3f869e error handling body 2020-09-04 12:07:53 +03:00
Yuri Kuznetsov
bc01c9f7c6 error handling fix 2020-09-04 11:26:08 +03:00
Yuri Kuznetsov
592df35acf cs fix 2020-09-04 10:17:15 +03:00
Yuri Kuznetsov
66f98aadf9 email sender test and fixes 2020-09-03 16:24:11 +03:00
Yuri Kuznetsov
17e420f01b email sender refactoring 2020-09-03 15:35:41 +03:00
Yuri Kuznetsov
44f6d57832 fix request 2020-09-03 14:52:34 +03:00
Yuri Kuznetsov
ae2cb10382 fix di 2020-09-03 13:47:57 +03:00
Taras Machyshyn
d68e08c3fd Merge branch 'master' of https://github.com/espocrm/espocrm 2020-09-03 12:23:43 +03:00
Taras Machyshyn
3921e8c287 Integration tests fixes 2020-09-03 12:22:50 +03:00
Yuri Kuznetsov
caf79d1657 email importer refactoring 2020-09-03 12:22:33 +03:00
Yuri Kuznetsov
7477ba64d2 unit tests fixes and changes 2020-09-03 10:35:10 +03:00
Yuri Kuznetsov
e006261fcf comment 2020-09-02 18:04:30 +03:00
Yuri Kuznetsov
2ddd9c2fc6 comment 2020-09-02 17:57:37 +03:00
Yuri Kuznetsov
5a7253f89b di service loading checking class correspondance 2020-09-02 17:56:47 +03:00
Yuri Kuznetsov
b68bc0f0b8 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-09-02 14:07:17 +03:00
Yuri Kuznetsov
edc4984f58 controller short param list 2020-09-02 13:59:48 +03:00
Taras Machyshyn
c8a2ca87ba Fixed Integration tests 2020-09-02 13:26:13 +03:00
Yuri Kuznetsov
4dcc9c42c8 cleanup and cs fixes 2020-09-02 11:37:40 +03:00
Yuri Kuznetsov
912fa4a85c fix tests 2020-09-02 11:33:51 +03:00
Yuri Kuznetsov
a64a4608be fixes 2020-09-02 11:20:16 +03:00
Yuri Kuznetsov
b20773f2f5 update composer 2020-09-02 11:03:11 +03:00
Yuri Kuznetsov
f9a440c708 fixes 2020-09-02 10:45:33 +03:00
Yuri Kuznetsov
d002768a5f refactoring 2020-09-02 10:09:15 +03:00
Yuri Kuznetsov
e0fcb9f225 request getParsedBody 2020-09-01 19:41:41 +03:00
Yuri Kuznetsov
a7ed16c72f controller ob_clean and some cs fix 2020-09-01 18:42:29 +03:00
Yuri Kuznetsov
1129d1c145 di refactoring 2020-09-01 17:50:28 +03:00
Yuri Kuznetsov
ee599c7ab8 cs fixes and orm usage fixes 2020-09-01 12:26:49 +03:00
Yuri Kuznetsov
1a5be5bf91 cs fix 2020-09-01 11:33:18 +03:00
Yuri Kuznetsov
db0020d428 orm usage fixes 2020-09-01 11:28:59 +03:00
Yuri Kuznetsov
138ca4299b fix orm usage 2020-09-01 11:10:46 +03:00
Yuri Kuznetsov
e9af1ebd80 comment fix 2020-08-31 20:23:00 +03:00
Yuri Kuznetsov
4d26e404b0 typo fix 2020-08-31 18:02:01 +03:00
Yuri Kuznetsov
b41813fa23 bc fix 2020-08-31 17:48:25 +03:00
Yuri Kuznetsov
b18796fd45 fix tests 2020-08-31 14:47:50 +03:00
Yuri Kuznetsov
d44898ed8c fixes 2020-08-31 13:30:01 +03:00
Yuri Kuznetsov
bb246cb4fd fix orm is related 2020-08-31 12:56:08 +03:00
Yuri Kuznetsov
17ceb3e721 fix syntax 2020-08-31 12:12:01 +03:00
Yuri Kuznetsov
8435c579c9 fix next number length index 2020-08-31 12:07:55 +03:00
Yuri Kuznetsov
3b4eb893b6 cleanup 2020-08-29 18:56:35 +03:00
Yuri Kuznetsov
54704bcee6 fixes 2020-08-29 18:39:59 +03:00
Yuri Kuznetsov
8bbfd862e4 cs fix 2020-08-28 16:28:17 +03:00
Yuri Kuznetsov
c909de0271 orm quote identifier 2020-08-28 14:47:04 +03:00
Yuri Kuznetsov
bd7f80a64e fix 2020-08-28 14:16:20 +03:00
Yuri Kuznetsov
2e15b5b271 orm fixes 2020-08-28 14:15:31 +03:00
Yuri Kuznetsov
0a61820f15 orm sth handling in repository 2020-08-28 13:27:34 +03:00
Yuri Kuznetsov
4b1af45cd6 orm improvements, relation where 2020-08-28 11:25:08 +03:00
Yuri Kuznetsov
756e3fcf39 cleanup 2020-08-27 17:33:53 +03:00
Yuri Kuznetsov
bb34ec1be3 cleanup 2020-08-27 17:32:07 +03:00
Yuri Kuznetsov
f98b86ae4d websocket app runner 2020-08-27 17:29:41 +03:00
Yuri Kuznetsov
eaa9a869f2 cleanup 2020-08-27 16:44:18 +03:00
Yuri Kuznetsov
d1f3dbf89b move defaults to resources 2020-08-27 16:41:57 +03:00
Yuri Kuznetsov
58c6208716 di usage 2020-08-27 15:09:14 +03:00
Yuri Kuznetsov
83eb252e82 update cron expression 2020-08-27 15:01:31 +03:00
Yuri Kuznetsov
fd7da4d2fc update semver 2020-08-27 14:52:15 +03:00
Yuri Kuznetsov
4f76c98cec cleanup not need methods 2020-08-27 14:37:41 +03:00
Yuri Kuznetsov
b7186e5da9 fix contact 2020-08-27 14:22:28 +03:00
Yuri Kuznetsov
b3276fb329 update tcpdf 2020-08-27 13:51:57 +03:00
Yuri Kuznetsov
5d2a31e65e preload refactoring 2020-08-27 13:31:10 +03:00
Yuri Kuznetsov
8eaa01f1bc toDb protected 2020-08-27 13:17:22 +03:00
Yuri Kuznetsov
9bee6e12b4 cleanup 2020-08-27 13:14:28 +03:00
Yuri Kuznetsov
50b2de8ce2 get rid off lock table sql 2020-08-27 13:12:44 +03:00
Yuri Kuznetsov
78b9e608e9 locker 2020-08-27 12:58:22 +03:00
Yuri Kuznetsov
944c91d842 rdb transaction manager 2020-08-26 17:19:29 +03:00
Yuri Kuznetsov
a936b9fec8 test move 2020-08-26 17:04:36 +03:00
Yuri Kuznetsov
1efdc626e0 more test for transactions 2020-08-26 13:35:20 +03:00
Yuri Kuznetsov
afca969668 rdb repository forUpdate 2020-08-26 13:22:58 +03:00
Yuri Kuznetsov
f72178f142 transaction integration test 2020-08-26 13:17:53 +03:00
Yuri Kuznetsov
2f4d744078 transaction manager 2020-08-26 12:54:16 +03:00
Yuri Kuznetsov
8563129dd5 select locking 2020-08-26 10:34:30 +03:00
Yuri Kuznetsov
ef1427bc95 orm group by string 2020-08-26 09:56:25 +03:00
Yuri Kuznetsov
20c07aaca1 orm fix 2020-08-26 09:37:59 +03:00
Yuri Kuznetsov
4470b3fdec change query update 2020-08-26 09:35:41 +03:00
Yuri Kuznetsov
1e4705d20b Merge branch 'hotfix/5.9.4' 2020-08-25 18:15:10 +03:00
Yuri Kuznetsov
0a5ae621b4 fix complex text 2020-08-25 18:11:38 +03:00
Yuri Kuznetsov
4e588f6d0e cs fix 2020-08-25 18:08:06 +03:00
Yuri Kuznetsov
f60c5e29de Merge branch 'hotfix/5.9.4' of https://github.com/espocrm/espocrm into hotfix/5.9.4 2020-08-25 18:04:36 +03:00
Yuri Kuznetsov
1662cfd97d notification form fix 2020-08-25 18:01:15 +03:00
Yuri Kuznetsov
8fdc0ab84d currency rate populate improvement 2020-08-25 17:39:32 +03:00
Yuri Kuznetsov
7c96fd391f account hook 2020-08-25 17:18:16 +03:00
Yuri Kuznetsov
2acbde70cc fix di usage 2020-08-25 16:52:41 +03:00
Yuri Kuznetsov
cb7d100315 ditch createSelectQuery usage 2020-08-25 16:08:15 +03:00
Yuri Kuznetsov
d96e1bb8a8 refactoring 2020-08-25 15:34:47 +03:00
Yuri Kuznetsov
d27a67f567 get rid of createSelectQuery usage 2020-08-25 15:20:52 +03:00
Yuri Kuznetsov
47ae974304 ditch raw sql 2020-08-25 14:56:34 +03:00
Yuri Kuznetsov
6ce168faa2 ditch raw sql 2020-08-25 14:39:28 +03:00
Yuri Kuznetsov
f9a8e1d9a7 fix comment 2020-08-25 14:24:54 +03:00
Yuri Kuznetsov
18543534fb ditch createSelectQuery usage 2020-08-25 14:23:29 +03:00
Yuri Kuznetsov
5349bd8d36 ditch raw sql 2020-08-25 14:10:29 +03:00
Yuri Kuznetsov
9a140571c3 ditch raw sql 2020-08-25 13:32:32 +03:00
Yuri Kuznetsov
a4e0dc8bb7 ditch raw sql 2020-08-25 12:59:11 +03:00
Yuri Kuznetsov
14788e2a65 ditch sql usage 2020-08-25 12:10:28 +03:00
Yuri Kuznetsov
c8118245e4 ditch raw sql 2020-08-25 11:10:06 +03:00
Yuri Kuznetsov
fcff23e0c1 ditch raw sql 2020-08-25 11:04:20 +03:00
Yuri Kuznetsov
85f07ca15d ditch raw sql 2020-08-25 10:44:04 +03:00
Yuri Kuznetsov
ed5a83c4f2 ditch raw sql 2020-08-25 10:04:40 +03:00
Yuri Kuznetsov
98e3ac0603 ditch raw sql 2020-08-25 09:53:33 +03:00
Yuri Kuznetsov
df01ef4e14 ditch raw sql 2020-08-25 09:40:43 +03:00
Yuri Kuznetsov
24a3e6872c ditch raw sql 2020-08-25 09:31:58 +03:00
Yuri Kuznetsov
3d491b63f2 fix sql executor and test 2020-08-25 09:20:17 +03:00
Yuri Kuznetsov
65dda61ff3 orm: select from alias 2020-08-25 08:52:21 +03:00
Yuri Kuznetsov
6d72a784fc fix comment 2020-08-19 21:10:57 +03:00
Yuri Kuznetsov
388e4a71e1 fix name 2020-08-19 21:10:24 +03:00
Yuri Kuznetsov
1f77c6468c orm refactoring 2020-08-19 17:29:36 +03:00
Yuri Kuznetsov
a242c283f3 cs fix 2020-08-19 14:16:12 +03:00
Yuri Kuznetsov
a09ed79242 cleanup 2020-08-19 14:13:34 +03:00
Yuri Kuznetsov
5116469856 cleanup 2020-08-19 12:55:28 +03:00
Yuri Kuznetsov
81c5583b5c cleanup 2020-08-19 12:51:30 +03:00
Yuri Kuznetsov
9d1233fe24 fix match 2020-08-19 12:50:58 +03:00
Yuri Kuznetsov
43c59f8d3e clearnup 2020-08-19 12:33:06 +03:00
Yuri Kuznetsov
3bebb7ff07 remove raw sql 2020-08-19 12:24:09 +03:00
Yuri Kuznetsov
05409dacde set id for autoincrement after insert 2020-08-19 11:36:49 +03:00
Yuri Kuznetsov
65929eec4b orm renaming 2020-08-18 21:02:49 +03:00
Yuri Kuznetsov
3d7a04be8e query executor method rename 2020-08-18 20:01:13 +03:00
Yuri Kuznetsov
0f1b8ecb39 orm fix 2020-08-18 19:55:14 +03:00
Yuri Kuznetsov
177d48e5a6 orm alias and select sub query 2020-08-18 19:50:10 +03:00
Yuri Kuznetsov
8b6b7dec06 remove raw sql 2020-08-18 17:14:12 +03:00
Yuri Kuznetsov
7011ef7615 cs fix 2020-08-18 15:14:55 +03:00
Yuri Kuznetsov
a8beabcd23 remove sql usage 2020-08-18 15:07:47 +03:00
Yuri Kuznetsov
c114ee8acb remove raw sql 2020-08-18 14:52:31 +03:00
Yuri Kuznetsov
aa121e326b remove raw sql 2020-08-18 14:15:12 +03:00
Yuri Kuznetsov
ad0c5a01dd fix 2020-08-18 13:58:54 +03:00
Yuri Kuznetsov
b66d60dd7d query builder use index 2020-08-18 13:55:46 +03:00
Yuri Kuznetsov
14993ad169 orm changes 2020-08-18 13:17:40 +03:00
Yuri Kuznetsov
dbf7147f22 fix 2020-08-18 13:04:30 +03:00
Yuri Kuznetsov
d3a8de29e3 category fix 2020-08-18 13:01:36 +03:00
Yuri Kuznetsov
98c42569ea grand orm improvements 2020-08-18 12:55:32 +03:00
Yuri Kuznetsov
1deebf0833 fix 2020-08-17 18:01:02 +03:00
Yuri Kuznetsov
3bc6b156a2 fix msg 2020-08-17 18:00:02 +03:00
Yuri Kuznetsov
0a52c50c47 cleanup 2020-08-17 17:58:20 +03:00
Yuri Kuznetsov
04c29294d6 fixes 2020-08-17 17:52:01 +03:00
Yuri Kuznetsov
9c28933882 preload 2020-08-17 17:51:49 +03:00
Yuri Kuznetsov
a5d8aed6fb app fix 2020-08-17 16:53:29 +03:00
Yuri Kuznetsov
4c52e36a0e test change 2020-08-17 16:27:56 +03:00
Yuri Kuznetsov
7c2403f470 orm fixes 2020-08-17 16:24:08 +03:00
Yuri Kuznetsov
99dfa52915 orm fix 2020-08-17 15:52:25 +03:00
Yuri Kuznetsov
3c5b61eca4 remove sth from relation select builder 2020-08-17 15:48:44 +03:00
Yuri Kuznetsov
2185479c01 changing account filters 2020-08-17 15:18:04 +03:00
Yuri Kuznetsov
fcbd48bc49 contact accountId change 2020-08-17 15:13:35 +03:00
Yuri Kuznetsov
db03f4f408 fixes 2020-08-17 13:49:20 +03:00
Yuri Kuznetsov
2f0e0d2a3b fix tests 2020-08-17 13:30:03 +03:00
Yuri Kuznetsov
1aeb5639c7 fix syntax 2020-08-17 11:53:30 +03:00
Yuri Kuznetsov
d14da8af12 fix test code 2020-08-17 11:53:22 +03:00
Yuri Kuznetsov
38e529ec14 fix tests 2020-08-17 11:14:24 +03:00
Yuri Kuznetsov
b44f055013 fix test 2020-08-17 10:34:17 +03:00
Yuri Kuznetsov
18aee37057 remove sql usage, person name field defs changes 2020-08-16 14:55:40 +03:00
Yuri Kuznetsov
83b5b9051d remove sql usage 2020-08-16 13:38:55 +03:00
Yuri Kuznetsov
e4141283f1 cleanup 2020-08-16 12:55:50 +03:00
Yuri Kuznetsov
209ad19164 orm fix and remove orm usage 2020-08-16 12:55:12 +03:00
Yuri Kuznetsov
52afb8d9d1 remove orm usage 2020-08-15 14:35:51 +03:00
Yuri Kuznetsov
ec6c1b0578 remove orm usage 2020-08-15 14:14:26 +03:00
Yuri Kuznetsov
7e97a9b2a4 fix meeting 2020-08-15 13:08:26 +03:00
Yuri Kuznetsov
8230dd07c4 no sql usage 2020-08-15 13:02:26 +03:00
Yuri Kuznetsov
16e7826981 no sql usage 2020-08-15 12:42:46 +03:00
Yuri Kuznetsov
17b9ae5089 fix bool search 2020-08-15 12:42:07 +03:00
Yuri Kuznetsov
85b38bc0e1 raw sql usage removal 2020-08-15 10:47:50 +03:00
Yuri Kuznetsov
ab8a9c8d36 orm changes 2020-08-15 10:47:34 +03:00
Yuri Kuznetsov
c8fb6d9805 orm fixes and removing sql usag 2020-08-14 17:26:44 +03:00
Yuri Kuznetsov
35d0d7956d orm custom select 2020-08-14 15:19:02 +03:00
Yuri Kuznetsov
1e6cc7e8a2 custom order 2020-08-14 14:04:03 +03:00
Yuri Kuznetsov
6dff9d06c9 refactoring 2020-08-14 13:45:23 +03:00
Yuri Kuznetsov
6de31ead9d orm custom where clause for fields 2020-08-14 12:25:27 +03:00
Yuri Kuznetsov
6dc8cd7031 query composer refactoring 2020-08-14 11:19:04 +03:00
Yuri Kuznetsov
60209027fc dependeeSelect, get rid of handleSelectParams usage 2020-08-13 18:09:52 +03:00
Yuri Kuznetsov
7d186672ec cleanup and fixes 2020-08-13 16:38:31 +03:00
Yuri Kuznetsov
6dd757e70f comment 2020-08-13 16:04:53 +03:00
Yuri Kuznetsov
56207f7f48 fix 2020-08-13 15:46:09 +03:00
Yuri Kuznetsov
bf5dc8a282 refactoring 2020-08-13 15:39:28 +03:00
Yuri Kuznetsov
0ec56ef0d3 relation columnAttributeMap 2020-08-13 15:33:19 +03:00
Yuri Kuznetsov
07b49d0147 orm order by to select if distinct 2020-08-13 12:21:34 +03:00
Yuri Kuznetsov
39d8b8f8ec link multiple fix 2020-08-12 16:59:34 +03:00
Yuri Kuznetsov
50564c5db8 orm fix 2020-08-12 16:36:31 +03:00
Yuri Kuznetsov
e9aad35e70 relateById 2020-08-12 15:41:29 +03:00
Yuri Kuznetsov
47d82ac120 fix 2020-08-12 15:13:29 +03:00
Yuri Kuznetsov
4cb7d22657 orm refactoring 2020-08-12 15:01:31 +03:00
Yuri Kuznetsov
e7992e356a grand orm refactoring 2020-08-12 14:38:49 +03:00
Yuri Kuznetsov
0fd8f9d29f email index change 2020-08-10 13:42:03 +03:00
Yuri Kuznetsov
bf033c31af date fix 2020-08-08 10:33:20 +03:00
Yuri Kuznetsov
aa788a17d9 fix date field issue 2020-08-07 18:00:17 +03:00
Yuri Kuznetsov
96c598d454 change 2020-08-05 17:05:29 +03:00
Yuri Kuznetsov
7cddf329d0 fix 2020-08-05 16:47:25 +03:00
Yuri Kuznetsov
f95660406f orm refactoring 2020-08-05 15:22:29 +03:00
Yuri Kuznetsov
338caebfaf orm refactoring 2020-08-05 14:28:43 +03:00
Yuri Kuznetsov
77ba946861 orm refactoring 2020-08-05 14:12:49 +03:00
Yuri Kuznetsov
cb37282a14 amend 2020-08-05 13:30:38 +03:00
Yuri Kuznetsov
3d40aefef5 orm refactoring 2020-08-05 13:28:49 +03:00
Yuri Kuznetsov
e7b0489294 orm refactoring 2020-08-05 12:50:20 +03:00
Yuri Kuznetsov
2690fcdacd test fix 2020-08-05 11:38:55 +03:00
Yuri Kuznetsov
0cc6d69c66 orm refactoring 2020-08-05 11:34:50 +03:00
Yuri Kuznetsov
3312d440c1 orm refactoring 2020-08-04 22:34:18 +03:00
Yuri Kuznetsov
dba5650f1a fix 2020-08-04 20:57:42 +03:00
Yuri Kuznetsov
81cab7acbf orm refactoring 2020-08-04 20:17:50 +03:00
Yuri Kuznetsov
42cb2eb9bb orm usage 2020-08-04 18:01:06 +03:00
Yuri Kuznetsov
1d0476e1b8 orm refactoring 2020-08-04 17:46:50 +03:00
Yuri Kuznetsov
4ea2455958 fixes 2020-08-04 16:08:07 +03:00
Yuri Kuznetsov
2338c57357 orm usage 2020-08-04 14:44:15 +03:00
Yuri Kuznetsov
019e1579f6 orm usage 2020-08-04 14:36:54 +03:00
Yuri Kuznetsov
df547b2022 orm usage 2020-08-04 14:01:47 +03:00
Yuri Kuznetsov
ce3b8b6f50 fixes and orm usage 2020-08-04 13:10:01 +03:00
Yuri Kuznetsov
4e24ee66f5 orm refactoring 2020-08-04 11:51:06 +03:00
Yuri Kuznetsov
f82495c1cc orm usage 2020-08-03 14:02:42 +03:00
Yuri Kuznetsov
c78c88cf92 fix bc 2020-08-03 13:44:36 +03:00
Yuri Kuznetsov
03b82e81f0 fix 2020-08-03 13:39:15 +03:00
Yuri Kuznetsov
90fe6a7416 stream service changes 2020-08-03 13:34:13 +03:00
Yuri Kuznetsov
30014d640b fix follow 2020-08-03 13:34:04 +03:00
Yuri Kuznetsov
2be2b7f459 orm fixes 2020-08-03 12:48:24 +03:00
Yuri Kuznetsov
659ae36ca6 orm changes 2020-08-03 11:43:16 +03:00
Yuri Kuznetsov
c92a4bcf36 orm changes 2020-08-03 10:54:04 +03:00
Yuri Kuznetsov
931786eadb fix validators 2020-08-03 10:36:56 +03:00
Yuri Kuznetsov
068e8121dc changes 2020-08-02 23:33:45 +03:00
Yuri Kuznetsov
4e938d98fc orm changes 2020-08-02 23:25:58 +03:00
Yuri Kuznetsov
da3e214ecd orm refactoring 2020-08-02 23:16:30 +03:00
Yuri Kuznetsov
e88799265f orm changes 2020-08-02 22:17:35 +03:00
Yuri Kuznetsov
dcb717db48 cleanup 2020-08-02 20:41:23 +03:00
Yuri Kuznetsov
9e78c0f9e1 orm changes 2020-08-02 19:26:15 +03:00
Yuri Kuznetsov
3b0596a93c formating fix 2020-08-02 19:17:46 +03:00
Yuri Kuznetsov
0c8593a958 orm refactoring 2020-08-02 19:11:57 +03:00
Yuri Kuznetsov
4e75524d6f mapper insert on duplicate update 2020-08-02 14:42:02 +03:00
Yuri Kuznetsov
e17b8dba4b orm usage 2020-08-02 13:55:16 +03:00
Yuri Kuznetsov
11dc206fac cleanup 2020-08-02 13:48:55 +03:00
Yuri Kuznetsov
f2ebd47ded merge 2020-08-02 13:48:19 +03:00
Yuri Kuznetsov
036ad99ba6 fix deprecation 2020-08-02 13:45:32 +03:00
Yuri Kuznetsov
904830579c orm refactoring 2020-07-31 17:49:37 +03:00
Yuri Kuznetsov
a37d380440 orm usage 2020-07-31 15:11:06 +03:00
Yuri Kuznetsov
1d6889879d rdb fix 2020-07-31 15:10:59 +03:00
Yuri Kuznetsov
b54cd7fbd9 RDBSelectBuilder 2020-07-31 11:41:44 +03:00
Yuri Kuznetsov
113b0ac446 repository changes and test 2020-07-31 10:38:25 +03:00
Yuri Kuznetsov
e30061e2a0 cs fix 2020-07-26 19:59:28 +03:00
Yuri Kuznetsov
2b406aa7cc cs fix 2020-07-25 19:35:51 +03:00
Yuri Kuznetsov
6cf5bbed95 container changes 2020-07-25 19:24:40 +03:00
Yuri Kuznetsov
1579671259 orm fix 2020-07-25 14:54:54 +03:00
Yuri Kuznetsov
567d8416ec auth refactor 2020-07-25 14:07:08 +03:00
Yuri Kuznetsov
644e848011 orm usage 2020-07-24 16:45:39 +03:00
Yuri Kuznetsov
dc4eccb043 relationship entities 2020-07-24 16:45:28 +03:00
Yuri Kuznetsov
be8ea6bab3 cs fix 2020-07-24 15:38:26 +03:00
Yuri Kuznetsov
246d42469f orm usage 2020-07-24 15:33:36 +03:00
Yuri Kuznetsov
8890aa6618 fixes 2020-07-24 15:33:29 +03:00
Yuri Kuznetsov
2b2620c954 orm usage 2020-07-24 12:37:54 +03:00
Yuri Kuznetsov
e594957c0b import confirm leavout 2020-07-24 11:08:11 +03:00
Yuri Kuznetsov
a3b2f18a32 import fixes and orm usage 2020-07-24 10:56:06 +03:00
Yuri Kuznetsov
742b28a3c8 fix 2020-07-24 10:11:47 +03:00
Yuri Kuznetsov
8340c5ba1d cs fixes 2020-07-24 09:47:00 +03:00
Yuri Kuznetsov
d44935bc29 fix 2020-07-24 09:45:12 +03:00
Yuri Kuznetsov
efcbae5554 fixes 2020-07-23 20:14:55 +03:00
Yuri Kuznetsov
73c22bf815 comments 2020-07-23 19:56:48 +03:00
Yuri Kuznetsov
e715d9e5b5 orm changes 2020-07-23 19:55:15 +03:00
Yuri Kuznetsov
d1c1995018 Merge branch 'hotfix/5.9.4' 2020-07-23 17:46:41 +03:00
Yuri Kuznetsov
7fda7abbe6 attachments fixes 2020-07-23 17:46:00 +03:00
Yuri Kuznetsov
bea8bd4057 mapper interface change 2020-07-23 15:02:15 +03:00
Yuri Kuznetsov
5d3996ae03 orm usage 2020-07-23 15:02:02 +03:00
Yuri Kuznetsov
3d5bc3bb0c orm mapper mass insert 2020-07-23 13:43:37 +03:00
Yuri Kuznetsov
2ec8022001 entity with out class 2020-07-23 13:16:11 +03:00
Yuri Kuznetsov
2dbbf72a6c cs fixes 2020-07-23 11:11:04 +03:00
Yuri Kuznetsov
fbbe0e06cf disable hooks while rebuild 2020-07-23 11:10:57 +03:00
Yuri Kuznetsov
455ef1138f orm usage and fixes 2020-07-23 10:54:49 +03:00
Yuri Kuznetsov
2398ef7efe change 2020-07-22 18:25:56 +03:00
Yuri Kuznetsov
f68c594a7e cleanup 2020-07-22 15:41:49 +03:00
Yuri Kuznetsov
8004e4eda8 currency use orm 2020-07-22 15:39:19 +03:00
Yuri Kuznetsov
1e682a3e9a cron: orm usage 2020-07-22 15:32:55 +03:00
Yuri Kuznetsov
6546d987e5 orm fix 2020-07-22 14:54:16 +03:00
Yuri Kuznetsov
e4195f7b60 orm usage 2020-07-22 12:08:58 +03:00
Yuri Kuznetsov
27cdb68240 cs fix 2020-07-22 11:43:01 +03:00
Yuri Kuznetsov
a59ea11aac orm query refactor and createDeleteQuery method 2020-07-22 11:31:59 +03:00
Yuri Kuznetsov
5fde8f9f4b formula functions change 2020-07-21 16:07:24 +03:00
Yuri Kuznetsov
3d05606ad6 formula functions changes 2020-07-21 14:51:02 +03:00
Yuri Kuznetsov
f2da244a3c fix pdf 2020-07-21 14:47:54 +03:00
Yuri Kuznetsov
c6e26b1323 move select manager to select 2020-07-21 11:42:18 +03:00
Yuri Kuznetsov
1550d289df Merge branch 'master' of https://github.com/espocrm/espocrm 2020-07-20 18:20:23 +03:00
Yuri Kuznetsov
81a6d05621 htmlizer code change 2020-07-20 18:13:31 +03:00
Yuri Kuznetsov
78c372b2f8 select manager code changes 2020-07-20 17:55:06 +03:00
Yuri Kuznetsov
59ec071908 diff refactoring 2020-07-20 13:38:14 +03:00
Yuri Kuznetsov
687e67faed comment 2020-07-18 18:52:18 +03:00
Yuri Kuznetsov
46e98d4660 Merge branch 'hotfix/5.9.4' 2020-07-18 15:02:52 +03:00
Yuri Kuznetsov
fa0cf9c9fd cleanup 2020-07-18 15:02:25 +03:00
Yuri Kuznetsov
0e851eb687 Merge branch 'hotfix/5.9.4' 2020-07-18 15:01:24 +03:00
Yuri Kuznetsov
3c651f8633 lang fixes 2020-07-18 14:47:02 +03:00
Yuri Kuznetsov
2b5f1c28e8 lang.js refactoring 2020-07-18 14:41:48 +03:00
Yuri Kuznetsov
7fea881d17 refactor po 2020-07-18 14:21:05 +03:00
Yuri Kuznetsov
61de366e05 merge 2020-07-18 12:29:22 +03:00
Yuri Kuznetsov
ada64bba0c fix dayOfWeek 2020-07-18 12:22:43 +03:00
Yuri Kuznetsov
ab582b92c9 more formula day of week tests 2020-07-17 21:57:40 +03:00
Yuri Kuznetsov
506a6a7779 cs fix 2020-07-17 17:09:47 +03:00
Yuri Kuznetsov
f87dcda391 entry point refactor 2020-07-17 17:08:30 +03:00
Yuri Kuznetsov
2d94ad60f3 diff: no delete tests 2020-07-17 13:00:49 +03:00
Yuri Kuznetsov
333ed98e37 update lodash 2020-07-17 10:26:24 +03:00
Yuri Kuznetsov
69b5f8a1cc api runner refactoring 2020-07-16 22:36:24 +03:00
Yuri Kuznetsov
cefad1c76f Merge branch 'hotfix/5.9.4' 2020-07-16 20:15:21 +03:00
Yuri Kuznetsov
8fe96b140a tcpdf header 2020-07-16 20:14:48 +03:00
Yuri Kuznetsov
3b25a1a001 error message 4 seconds 2020-07-16 19:59:46 +03:00
Yuri Kuznetsov
f4d98f177c fix typos 2020-07-16 19:57:04 +03:00
Yuri Kuznetsov
9f4f38bb0d webhook verify peer 2020-07-16 19:50:53 +03:00
Yuri Kuznetsov
b42ebfde2f formula refactoring 2020-07-16 17:37:22 +03:00
Yuri Kuznetsov
1bd73d7872 admin search use keywords 2020-07-16 12:48:48 +03:00
Yuri Kuznetsov
6d83f77fcf webhook comments 2020-07-15 23:23:08 +03:00
Yuri Kuznetsov
17c1070fc1 cs fix 2020-07-15 23:07:50 +03:00
Yuri Kuznetsov
f86a493ba6 app runners refactoring 2020-07-15 17:33:18 +03:00
Yuri Kuznetsov
32119b6afd docs fix 2020-07-15 16:11:56 +03:00
Yuri Kuznetsov
e11661eadc cs fix 2020-07-15 15:14:50 +03:00
Yuri Kuznetsov
0fc2201d80 cs fix 2020-07-15 14:39:40 +03:00
Yuri Kuznetsov
bbe96f67f6 formula changes 2020-07-15 14:34:05 +03:00
Yuri Kuznetsov
f4b2d9b1df formula functions change 2020-07-15 12:39:59 +03:00
Yuri Kuznetsov
42d894fd5a file storage changes and comments 2020-07-15 11:04:48 +03:00
Yuri Kuznetsov
e8c750c18f formula changes 2020-07-14 22:41:05 +03:00
Yuri Kuznetsov
89cb84d784 fix 2020-07-14 19:02:46 +03:00
Yuri Kuznetsov
daa6e8360a cleanup 2020-07-14 18:49:56 +03:00
Yuri Kuznetsov
24429255dc fix formula exceptions 2020-07-14 18:38:20 +03:00
Yuri Kuznetsov
7c55ae98e5 formula fixes and comments 2020-07-14 18:35:02 +03:00
Yuri Kuznetsov
81ed21962f formula refactoring, using arguments 2020-07-14 18:17:34 +03:00
Yuri Kuznetsov
d9752ed970 formula refactoring 2020-07-14 15:03:21 +03:00
Yuri Kuznetsov
c6293580d9 compatibility fixes 2020-07-14 13:39:05 +03:00
Yuri Kuznetsov
5ddb76c137 fix mapper 2020-07-14 12:19:38 +03:00
Yuri Kuznetsov
20893622d4 fix tests 2020-07-14 11:47:43 +03:00
Yuri Kuznetsov
35445dbf2e fix entity 2020-07-14 11:47:32 +03:00
Yuri Kuznetsov
fbe6e3c1e6 fix mapper and tests 2020-07-14 11:15:23 +03:00
Yuri Kuznetsov
1d35922155 api runner 2020-07-13 12:29:11 +03:00
Yuri Kuznetsov
ea31174cc4 application refactoring 2020-07-13 12:05:35 +03:00
Yuri Kuznetsov
f5ea5f673c manual merge 2020-07-13 10:55:33 +03:00
Yuri Kuznetsov
e76490880a v 2020-07-13 10:48:13 +03:00
Yuri Kuznetsov
e12bb1320c fix cookies 2020-07-13 10:47:57 +03:00
Yuri Kuznetsov
827e16cf93 application runners and fixes 2020-07-12 19:37:22 +03:00
Yuri Kuznetsov
1b61205281 aoolication runners 2020-07-12 19:11:53 +03:00
Yuri Kuznetsov
269f2b4850 extension and upgrade scripts fix 2020-07-12 14:27:07 +03:00
Yuri Kuznetsov
d346e35901 comment fix 2020-07-12 14:17:21 +03:00
Yuri Kuznetsov
2f87691309 orm refactoring and comments 2020-07-12 14:16:26 +03:00
Yuri Kuznetsov
8e6c778a82 refactoring 2020-07-12 13:02:24 +03:00
Yuri Kuznetsov
f36732f7d4 orm refactoring and comments 2020-07-12 11:14:27 +03:00
Yuri Kuznetsov
e63d60ab3d cleanup 2020-07-11 23:35:58 +03:00
Yuri Kuznetsov
460f3fcfd6 orm refactoring 2020-07-11 23:34:19 +03:00
Yuri Kuznetsov
1f52ab9a3f cleanyp 2020-07-11 19:39:16 +03:00
Yuri Kuznetsov
397a9cdf1f fix 2020-07-11 16:46:22 +03:00
Yuri Kuznetsov
4560ef7ef7 fix comment 2020-07-11 16:38:27 +03:00
Yuri Kuznetsov
dc41dff9a0 cleanup 2020-07-11 16:36:41 +03:00
Yuri Kuznetsov
3e6d9d1b11 auth refactoring 2020-07-11 16:34:05 +03:00
Yuri Kuznetsov
1513f45662 auth login result 2020-07-11 16:09:53 +03:00
Yuri Kuznetsov
3e8426da1a auth refactoring 2020-07-11 15:19:48 +03:00
Yuri Kuznetsov
bb29373e16 refactoring 2020-07-11 12:24:35 +03:00
Yuri Kuznetsov
da7ac548c5 comments 2020-07-11 10:30:01 +03:00
Yuri Kuznetsov
b37441eaa8 admin quick server preserve search 2020-07-10 16:40:08 +03:00
Yuri Kuznetsov
a546b77c10 admin quick search 2020-07-10 16:23:24 +03:00
Yuri Kuznetsov
392cb956d2 comments 2020-07-10 14:41:16 +03:00
Yuri Kuznetsov
76273a4d86 mail classes comments and type hinting 2020-07-10 12:55:10 +03:00
Yuri Kuznetsov
eb32b41bd4 comments 2020-07-10 12:29:10 +03:00
Yuri Kuznetsov
767456ca9a mail sender changes 2020-07-10 12:29:04 +03:00
Yuri Kuznetsov
c12354138a fix 2020-07-10 11:42:07 +03:00
Yuri Kuznetsov
1fd93a1fb8 fix 2020-07-10 11:19:20 +03:00
Yuri Kuznetsov
9c36937a9e refactoring 2020-07-09 21:50:45 +03:00
Yuri Kuznetsov
3d382e67b6 refactoring and fixes 2020-07-09 20:27:28 +03:00
Yuri Kuznetsov
ecdcab7371 attachment fixes 2020-07-09 14:17:24 +03:00
Yuri Kuznetsov
a5609f3cad fix 2020-07-09 13:44:24 +03:00
Yuri Kuznetsov
5c0bc397c1 fix test 2020-07-09 12:56:32 +03:00
Yuri Kuznetsov
21e9131c65 fix preferences 2020-07-09 12:49:36 +03:00
Yuri Kuznetsov
8159e33fef fix tester 2020-07-09 12:23:35 +03:00
Yuri Kuznetsov
d2411e380b fix tests 2020-07-09 11:36:11 +03:00
Yuri Kuznetsov
a2017a0a75 dev 2020-07-09 11:08:52 +03:00
Yuri Kuznetsov
16fcc4d61e dev 2020-07-09 11:00:52 +03:00
Yuri Kuznetsov
b6b4909f3c fix 2020-07-08 22:50:48 +03:00
Yuri Kuznetsov
773abf3028 dev 2020-07-08 17:50:53 +03:00
Yuri Kuznetsov
f8f7c4fbff dev 2020-07-08 17:30:25 +03:00
Yuri Kuznetsov
c84abfb542 do not display auth error message 2020-07-08 16:15:30 +03:00
Yuri Kuznetsov
656f66f567 fix menu items 2020-07-08 16:07:27 +03:00
Yuri Kuznetsov
75386b4355 dev 2020-07-08 15:42:38 +03:00
Yuri Kuznetsov
434b3020a0 fix 2020-07-08 14:34:13 +03:00
Yuri Kuznetsov
64b0adee30 dev 2020-07-08 12:41:34 +03:00
Yuri Kuznetsov
6351dc030c fix 2020-07-08 12:38:43 +03:00
Yuri Kuznetsov
f261690d76 dev 2020-07-08 12:37:59 +03:00
Yuri Kuznetsov
de37982a64 dev 2020-07-08 12:18:34 +03:00
Yuri Kuznetsov
4266a38c01 dev 2020-07-08 12:04:35 +03:00
Yuri Kuznetsov
8daec77bb4 dev 2020-07-08 11:20:53 +03:00
Yuri Kuznetsov
4267c78f68 dev 2020-07-08 11:11:55 +03:00
Yuri Kuznetsov
2f7843687f dev 2020-07-08 10:30:56 +03:00
Yuri Kuznetsov
1648eb78f0 dev 2020-07-08 10:13:39 +03:00
Yuri Kuznetsov
2b8143b4fb dev 2020-07-08 10:12:29 +03:00
Yuri Kuznetsov
b2d6e7c37e dev 2020-07-07 20:16:57 +03:00
Yuri Kuznetsov
22d41a144f dev 2020-07-07 20:03:37 +03:00
Yuri Kuznetsov
f71d52c5ba dev 2020-07-07 19:55:00 +03:00
Yuri Kuznetsov
1a86438f32 dev 2020-07-07 19:34:32 +03:00
Yuri Kuznetsov
20aadf26a5 dev 2020-07-07 19:17:35 +03:00
Yuri Kuznetsov
d6514bc946 dev 2020-07-07 19:04:11 +03:00
Yuri Kuznetsov
3f417198d7 dev 2020-07-07 18:50:33 +03:00
Yuri Kuznetsov
62da2245c1 dev 2020-07-07 18:38:14 +03:00
Yuri Kuznetsov
627fa8f89e dev 2020-07-07 18:20:17 +03:00
Yuri Kuznetsov
13e24501e5 cleanup 2020-07-07 18:17:58 +03:00
Yuri Kuznetsov
0002ec1a8e fix 2020-07-07 18:17:35 +03:00
Yuri Kuznetsov
62d7948b67 cleanup 2020-07-07 18:13:39 +03:00
Yuri Kuznetsov
54ca25571e dev 2020-07-07 16:09:29 +03:00
Yuri Kuznetsov
a64bf2e97f fix comment 2020-07-07 16:08:33 +03:00
Yuri Kuznetsov
029a5587e6 dev 2020-07-07 16:05:27 +03:00
Yuri Kuznetsov
918ce84b1b fixes 2020-07-02 22:17:03 +03:00
Yuri Kuznetsov
4622e9fe01 dev 2020-07-02 21:53:24 +03:00
Yuri Kuznetsov
d707979b7d fixes 2020-07-02 21:47:37 +03:00
Yuri Kuznetsov
0c224e2a22 cleanup 2020-07-02 21:39:54 +03:00
Yuri Kuznetsov
b4b4ec2f89 dev 2020-07-02 21:38:29 +03:00
Yuri Kuznetsov
07b297f7ef dev 2020-07-02 19:40:11 +03:00
Yuri Kuznetsov
e7804062f3 dev 2020-07-02 19:00:56 +03:00
Yuri Kuznetsov
efed7969fc dev 2020-07-02 18:49:11 +03:00
Yuri Kuznetsov
c8a1edea1a dev 2020-07-02 18:09:55 +03:00
Yuri Kuznetsov
8a0d2c9b6a dev 2020-07-02 17:12:58 +03:00
Yuri Kuznetsov
784b0e8e40 dev 2020-07-02 12:54:57 +03:00
Yuri Kuznetsov
9ac3cc23f7 dev 2020-07-02 12:36:33 +03:00
Yuri Kuznetsov
0e1b88fd25 dev 2020-07-02 12:28:21 +03:00
Yuri Kuznetsov
7084b38a5a dev 2020-07-02 12:11:26 +03:00
Yuri Kuznetsov
7cba7fad95 dev 2020-07-02 10:32:59 +03:00
Yuri Kuznetsov
73d67763c9 dev 2020-07-01 14:57:20 +03:00
Yuri Kuznetsov
29217453ab Merge branch 'hotfix/5.9.4' 2020-07-01 08:38:40 +03:00
Yuri Kuznetsov
eca5bdea71 fix formula where 2020-07-01 08:38:14 +03:00
Yuri Kuznetsov
34fe3f53c3 slim cleanup 2020-06-30 15:36:02 +03:00
Yuri Kuznetsov
78353460d1 get rid of useController route condition 2020-06-30 14:34:38 +03:00
Yuri Kuznetsov
210c76bad1 slim headers deprecated usage fix 2020-06-30 13:56:03 +03:00
Yuri Kuznetsov
d7326b927d container info sort 2020-06-30 10:59:36 +03:00
Yuri Kuznetsov
a4cf749d6d log aware 2020-06-30 10:52:53 +03:00
Yuri Kuznetsov
b7d256687a app info container command 2020-06-30 10:43:50 +03:00
Yuri Kuznetsov
ccce2eb137 fix container configuration 2020-06-30 10:43:42 +03:00
Yuri Kuznetsov
46a0c1f7bf fix 2020-06-30 10:14:49 +03:00
Yuri Kuznetsov
a84d6f4121 fix doc 2020-06-30 10:13:52 +03:00
Yuri Kuznetsov
10793ebdda refactoring 2020-06-30 10:11:26 +03:00
Yuri Kuznetsov
9c6bec3761 Merge branch 'hotfix/5.9.4' 2020-06-30 08:53:10 +03:00
Yuri Kuznetsov
2ab4173e85 oauth client fix 2020-06-30 08:51:29 +03:00
Yuri Kuznetsov
195db973dc get image url use ssl verify peer 2020-06-30 08:50:09 +03:00
Yuri Kuznetsov
b15148f9f7 cleanup 2020-06-29 20:02:32 +03:00
Yuri Kuznetsov
ae6f669629 remobe getOrmMetadata method 2020-06-29 20:01:20 +03:00
Yuri Kuznetsov
a50c66557e cleanup 2020-06-29 19:58:15 +03:00
Yuri Kuznetsov
9a09822f7a fix comment 2020-06-29 19:57:29 +03:00
Yuri Kuznetsov
0a3174cba9 entity maanger comments and type hint additions 2020-06-29 19:56:54 +03:00
Yuri Kuznetsov
d5414ece84 select manager comments 2020-06-29 19:18:18 +03:00
Yuri Kuznetsov
fc4de43db3 acl comments and fixes 2020-06-29 17:37:51 +03:00
Yuri Kuznetsov
e4138b894c acl changes 2020-06-29 17:23:07 +03:00
Yuri Kuznetsov
5b74430751 cleanup 2020-06-29 16:09:53 +03:00
Yuri Kuznetsov
22f6d2d1b9 comments 2020-06-29 16:01:31 +03:00
Yuri Kuznetsov
318e164a01 cleanup deprecation 2020-06-29 15:58:34 +03:00
Yuri Kuznetsov
969d40f5d8 acl comments 2020-06-29 15:53:29 +03:00
Yuri Kuznetsov
c7f8b4899a docs fixes 2020-06-29 15:50:40 +03:00
Yuri Kuznetsov
a81086493f acl manager docs 2020-06-29 15:49:55 +03:00
Yuri Kuznetsov
b773f22bd2 app state comments 2020-06-29 14:45:59 +03:00
Yuri Kuznetsov
2b34b86746 controller refactoring 2020-06-29 14:41:14 +03:00
Yuri Kuznetsov
78c4350ff7 fix application state 2020-06-29 14:41:04 +03:00
Yuri Kuznetsov
ecd33b0f54 stream controller refactoring 2020-06-29 14:35:34 +03:00
Yuri Kuznetsov
7753eb32af controller refactoring 2020-06-29 14:29:33 +03:00
Yuri Kuznetsov
9d3fbf8d27 controllers refactoring 2020-06-29 14:24:49 +03:00
Yuri Kuznetsov
7f3d099148 cs fixes and cleanup 2020-06-29 13:45:03 +03:00
Yuri Kuznetsov
518ed97ed4 controllers refactoring 2020-06-29 13:30:40 +03:00
Yuri Kuznetsov
6b46ac2fde controller manager check data type 2020-06-29 13:30:31 +03:00
Yuri Kuznetsov
6b9f0f07ec Merge branch 'feature/di-setter' 2020-06-29 11:35:36 +03:00
Yuri Kuznetsov
553c7e9caa test fixes 2020-06-29 11:34:08 +03:00
Yuri Kuznetsov
bef0826f9d fix rdb repo 2020-06-29 11:20:29 +03:00
Yuri Kuznetsov
8fa4ec20a8 fix case repo 2020-06-29 11:10:47 +03:00
Yuri Kuznetsov
5ad7562f17 fix test 2020-06-29 11:10:32 +03:00
Yuri Kuznetsov
b74d95894b fix test 2020-06-28 17:49:13 +03:00
Yuri Kuznetsov
562cd42344 portal config refactoring and type hinring 2020-06-28 11:35:39 +03:00
Yuri Kuznetsov
078bdfc28f deprcated tag 2020-06-28 10:27:29 +03:00
Yuri Kuznetsov
3c5e84bc44 ditch isAdmin isPortal isSuperAdmin 2020-06-28 09:48:20 +03:00
Yuri Kuznetsov
e61a6a00d8 application class comments and cleanup 2020-06-28 09:24:48 +03:00
Yuri Kuznetsov
f7b1441050 comments and datime type hint 2020-06-27 23:51:29 +03:00
Yuri Kuznetsov
d0e6689dc4 cleanup 2020-06-27 23:25:18 +03:00
Yuri Kuznetsov
9af8dde878 auth refactor 2020-06-27 19:49:37 +03:00
Yuri Kuznetsov
bfed745758 refactor 2020-06-27 19:49:28 +03:00
Yuri Kuznetsov
cc22abba50 notificators di 2020-06-27 19:19:11 +03:00
Yuri Kuznetsov
ca84177e87 password recovery di 2020-06-27 18:54:58 +03:00
Yuri Kuznetsov
4508991ca2 cleanup using di 2020-06-27 17:43:55 +03:00
Yuri Kuznetsov
0b1ddecd32 export di refactoring 2020-06-27 15:07:22 +03:00
Yuri Kuznetsov
59025f7d4c preferencesAware 2020-06-27 14:56:16 +03:00
Yuri Kuznetsov
8c75651650 services refactoring 2020-06-27 14:34:25 +03:00
Yuri Kuznetsov
44ea2aee40 fix repository 2020-06-27 14:34:17 +03:00
Yuri Kuznetsov
7401647d6a record service fix 2020-06-27 14:05:28 +03:00
Yuri Kuznetsov
fbd496e663 cs fixes 2020-06-27 12:47:02 +03:00
Yuri Kuznetsov
e22818f51f Merge branch 'hotfix/5.9.4' into feature/di-setter 2020-06-27 12:37:16 +03:00
Yuri Kuznetsov
cd5537cc26 fix user generate new possword hidden if group email account used 2020-06-27 12:36:56 +03:00
Yuri Kuznetsov
1933194d35 user service refactoring 2020-06-27 12:29:45 +03:00
Yuri Kuznetsov
aef08dcd75 webhook service refactoring 2020-06-27 12:13:20 +03:00
Yuri Kuznetsov
fd4c49d3d2 team service refactoring 2020-06-27 12:06:37 +03:00
Yuri Kuznetsov
c1518cb509 stream service refactoring 2020-06-27 11:57:42 +03:00
Yuri Kuznetsov
43e424d44d applicationState 2020-06-27 11:26:59 +03:00
Yuri Kuznetsov
4dfd313d10 services refactoring 2020-06-26 20:12:57 +03:00
Yuri Kuznetsov
9e68f4cd2c service refactoring 2020-06-26 18:30:52 +03:00
Yuri Kuznetsov
3fe373e20c cs fixes 2020-06-26 17:40:35 +03:00
Yuri Kuznetsov
1f2852a369 service refactoring 2020-06-26 17:15:43 +03:00
Yuri Kuznetsov
abe4d91622 cleanup 2020-06-26 16:54:54 +03:00
Yuri Kuznetsov
0649b18952 services refactoring 2020-06-26 16:53:39 +03:00
Yuri Kuznetsov
aee81c1533 services refactoring 2020-06-26 16:10:07 +03:00
Yuri Kuznetsov
451b8ea1e5 services refactoring 2020-06-26 14:12:18 +03:00
Yuri Kuznetsov
578cf90f85 formula refactoring 2020-06-25 19:24:10 +03:00
Yuri Kuznetsov
869fa35353 hook decoupling 2020-06-25 17:06:58 +03:00
Yuri Kuznetsov
4d8cfb05ee merge hotfix 2020-06-25 13:42:33 +03:00
Yuri Kuznetsov
b9d9463cc9 fix tests 2020-06-25 13:39:48 +03:00
Yuri Kuznetsov
2c01caa7be select manager class 2020-06-25 13:02:19 +03:00
Yuri Kuznetsov
65e925ec22 repositories refactoring 2020-06-25 12:43:33 +03:00
Yuri Kuznetsov
1144956c99 repository decoupling 2020-06-25 11:56:29 +03:00
Yuri Kuznetsov
cf586dcd75 repository refactoring 2020-06-25 10:50:20 +03:00
Yuri Kuznetsov
94008f5a53 fix metadata service null acl check 2020-06-25 08:35:47 +03:00
Yuri Kuznetsov
6c5dd4a120 entry point traits 2020-06-24 17:43:51 +03:00
Yuri Kuznetsov
e87490aad8 acl changes 2020-06-24 16:54:52 +03:00
Yuri Kuznetsov
cb55cec3f0 acl manager code improvements 2020-06-24 12:48:08 +03:00
Yuri Kuznetsov
8bfec9ec7e acl di 2020-06-24 11:32:47 +03:00
Yuri Kuznetsov
bf410b2258 cleanup 2020-06-24 09:02:23 +03:00
Yuri Kuznetsov
6eaab67081 fix injectable factory 2020-06-23 21:06:14 +03:00
Yuri Kuznetsov
d1ff4b0ede injectable factory fix 2020-06-23 20:50:58 +03:00
Yuri Kuznetsov
5bc4dc297d acl with factory 2020-06-23 19:10:41 +03:00
Yuri Kuznetsov
79f8a5e87c decoupling 2020-06-23 18:50:21 +03:00
Yuri Kuznetsov
5c0eec9c83 job interface move 2020-06-23 16:59:00 +03:00
Yuri Kuznetsov
42f6dab4ce entry point changes 2020-06-23 16:46:18 +03:00
Yuri Kuznetsov
7bcb6a320e decoupling 2020-06-23 16:14:11 +03:00
Yuri Kuznetsov
771acbea35 loader classes 2020-06-23 13:49:46 +03:00
Yuri Kuznetsov
8520bbcf85 decoupling 2020-06-23 13:13:01 +03:00
Yuri Kuznetsov
253838bba9 decoupling 2020-06-23 12:15:11 +03:00
Yuri Kuznetsov
0f2a26b744 formula comments fix 2020-06-22 21:26:51 +03:00
Yuri Kuznetsov
53db712015 decoupling 2020-06-22 20:30:20 +03:00
Yuri Kuznetsov
6f2fc808cd decoupling 2020-06-22 19:24:44 +03:00
Yuri Kuznetsov
6b2fdf5400 decoupling 2020-06-22 19:16:40 +03:00
Yuri Kuznetsov
b2fa393673 portal application changes 2020-06-22 15:30:01 +03:00
Yuri Kuznetsov
5292d13ae6 application method changes 2020-06-22 15:25:07 +03:00
Yuri Kuznetsov
bfa3a2948d Merge branch 'stable' 2020-06-22 13:53:50 +03:00
Yuri Kuznetsov
2340a58e8f container get rid of setUser 2020-06-22 12:38:40 +03:00
Yuri Kuznetsov
6d696d94d8 fix container 2020-06-22 11:08:47 +03:00
Yuri Kuznetsov
57360e5fea container default loaders 2020-06-22 10:33:34 +03:00
Yuri Kuznetsov
5c8d6ee901 file manager fix 2020-06-22 10:28:34 +03:00
Yuri Kuznetsov
7850eda22e fix typo 2020-06-21 23:56:45 +03:00
Yuri Kuznetsov
38bda84426 cleanup 2020-06-21 23:17:52 +03:00
Yuri Kuznetsov
954267c830 container configuration 2020-06-21 23:13:31 +03:00
Yuri Kuznetsov
0dc5437ddd loader interface 2020-06-21 19:53:10 +03:00
Yuri Kuznetsov
36dbc16fcf use loader for injectable factory 2020-06-21 19:51:35 +03:00
Yuri Kuznetsov
d20cc4c45e changes in loader 2020-06-21 19:45:31 +03:00
Yuri Kuznetsov
8b9e376609 container changes 2020-06-21 19:41:54 +03:00
Yuri Kuznetsov
bc9395029b container has 2020-06-21 16:51:38 +03:00
Yuri Kuznetsov
6a2af9ffe4 method rename 2020-06-21 16:03:16 +03:00
Yuri Kuznetsov
9005656062 injectable factory constructor injections for injectable 2020-06-21 15:55:05 +03:00
Yuri Kuznetsov
965dc73351 controller use injectable factory 2020-06-21 09:20:57 +03:00
Yuri Kuznetsov
5dc31fac5b select manager in another class 2020-06-20 22:08:23 +03:00
Yuri Kuznetsov
4254382e7f cleanup 2020-06-20 22:00:02 +03:00
Yuri Kuznetsov
9c0a8266ab select manager with injectable factory 2020-06-20 21:58:36 +03:00
Yuri Kuznetsov
407c8204aa change currency converted hook 2020-06-20 21:08:17 +03:00
Yuri Kuznetsov
e218aaaed2 internalAclManager fix 2020-06-20 20:38:42 +03:00
Yuri Kuznetsov
d07a21fdaa cleanup 2020-06-20 20:16:20 +03:00
Yuri Kuznetsov
e8b69e133e hook manager changes 2020-06-20 20:11:31 +03:00
Yuri Kuznetsov
b02d2a7f8d fix comment 2020-06-20 19:31:08 +03:00
Yuri Kuznetsov
b9e3c22a1e class parser skip not instantiable 2020-06-20 19:27:33 +03:00
Yuri Kuznetsov
80ab030c4a entry point manager use factory 2020-06-20 17:23:20 +03:00
Yuri Kuznetsov
5483919dd3 comment fix 2020-06-20 17:18:36 +03:00
Yuri Kuznetsov
b21daf47a7 remove test 2020-06-20 17:10:53 +03:00
Yuri Kuznetsov
917ec1091a injectable factory create with 2020-06-20 17:06:59 +03:00
Yuri Kuznetsov
30bb9f4fcc di setter 2020-06-20 15:54:49 +03:00
Yuri Kuznetsov
626da4c8bb services changes 2020-06-20 11:50:13 +03:00
Yuri Kuznetsov
813462744b service changes 2020-06-19 22:17:43 +03:00
Yuri Kuznetsov
970b648145 file storage with factory 2020-06-19 21:13:22 +03:00
Yuri Kuznetsov
b9fce4527a auth factorie improvements 2020-06-19 20:51:26 +03:00
Yuri Kuznetsov
597b157f83 injectable setter 2020-06-19 18:55:36 +03:00
Yuri Kuznetsov
4f82ae38cf service improvements 2020-06-19 17:26:40 +03:00
Yuri Kuznetsov
74e4012fee di improvements 2020-06-18 22:42:58 +03:00
Yuri Kuznetsov
74d18be94a fix typo 2020-06-18 14:55:57 +03:00
Yuri Kuznetsov
56788af48b command change and test 2020-06-18 14:54:48 +03:00
Yuri Kuznetsov
e618b3d0aa fix grunt tests 2020-06-18 14:18:09 +03:00
Yuri Kuznetsov
9f9cfbd581 change import flags 2020-06-18 12:49:35 +03:00
Yuri Kuznetsov
c2e5f3ac2f command: supporting --flag 2020-06-18 12:49:22 +03:00
Yuri Kuznetsov
9ccf4f6083 import commands 2 2020-06-18 12:33:13 +03:00
Yuri Kuznetsov
eb3fb9ec1c reverting import 2020-06-18 12:04:57 +03:00
Yuri Kuznetsov
69f0f8d8bf grand impromenets for customization abilities 2020-06-17 19:27:51 +03:00
Yuri Kuznetsov
af7a73ec42 class finder 2020-06-17 16:30:34 +03:00
Yuri Kuznetsov
c0b68e7da5 class parser change 2020-06-17 16:21:39 +03:00
Yuri Kuznetsov
050c88ca55 email send no block 2020-06-17 12:19:26 +03:00
Yuri Kuznetsov
cc4f5b9ff5 import improvements 2020-06-16 12:50:49 +03:00
Yuri Kuznetsov
1645034f6e Merge branch 'hotfix/5.9.3' 2020-06-16 12:50:29 +03:00
Yuri Kuznetsov
b5e9f98fd1 email insert field 2020-06-15 10:30:41 +03:00
1095 changed files with 66431 additions and 32901 deletions

6
.gitignore vendored
View File

@@ -7,7 +7,7 @@
/data/tmp/*
/build
/node_modules
npm-debug.log
/npm-debug.log
/test.php
/main.html
@@ -15,7 +15,7 @@ npm-debug.log
!/tests/unit/testData/cache/.data
/tests/integration/config.php
.phpunit.result.cache
composer.phar
vendor/
/composer.phar
/vendor/
/custom/Espo/Custom/*
/install/config.php

View File

@@ -49,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',
@@ -211,6 +212,7 @@ module.exports = function (grunt) {
'daemon.php',
'rebuild.php',
'clear_cache.php',
'preload.php',
'upgrade.php',
'extension.php',
'websocket.php',
@@ -288,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'
}
]
}
@@ -313,11 +315,11 @@ module.exports = function (grunt) {
});
grunt.registerTask("unit-tests-run", function() {
cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php tests/unit", {stdio: 'inherit'});
cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php ./tests/unit", {stdio: 'inherit'});
});
grunt.registerTask("integration-tests-run", function() {
cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php tests/integration", {stdio: 'inherit'});
cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php ./tests/integration", {stdio: 'inherit'});
});
grunt.registerTask("zip", function() {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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';

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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';

View File

@@ -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;
}
}

View File

@@ -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)
{

View File

@@ -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');
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View 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);
}
}

View File

@@ -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;
}

View File

@@ -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
{

View File

@@ -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,7 +46,7 @@ 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 (isset($data->$field) && $data->$field !== null && !is_array($data->$field)) {
return false;
@@ -53,7 +55,7 @@ class ArrayType extends BaseType
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);

View File

@@ -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;
}
}

View File

@@ -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
{

View File

@@ -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 &&

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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';

View File

@@ -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';

View File

@@ -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
{

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -27,7 +27,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\TemplateHelpers;
namespace Espo\Classes\TemplateHelpers;
class GoogleMaps
{
@@ -148,14 +148,12 @@ class GoogleMaps
$GLOBALS['log']->debug("Template helper _googleMapsImage: URL: {$url}.");
$image = \Espo\Core\TemplateHelpers\GoogleMaps::getImage($url);
$image = \Espo\Classes\TemplateHelpers\GoogleMaps::getImage($url);
if (!$image) {
return null;
}
$filePath = tempnam(sys_get_temp_dir(), 'google_maps_image');
file_put_contents($filePath, $image);

View File

@@ -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();
}
}

View 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";
}
}

View File

@@ -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);
}
}

View File

@@ -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
{
@@ -66,10 +66,10 @@ class Attachment extends \Espo\Core\Controllers\Record
$fileData = $this->getRecordService()->getFileData($id);
$response->headers->set('Content-Type', $fileData->type);
$response->headers->set('Content-Disposition', 'Content-Disposition: attachment; filename="'.$fileData->name.'"');
$response->setHeader('Content-Type', $fileData->type);
$response->setHeader('Content-Disposition', 'Content-Disposition: attachment; filename="'.$fileData->name.'"');
if ($fileData->size) {
$response->headers->set('Content-Length', $fileData->size);
$response->setHeader('Content-Length', $fileData->size);
}
return $fileData->contents;

View File

@@ -29,7 +29,7 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\Forbidden;
class AuthLogRecord extends \Espo\Core\Controllers\Record
{

View File

@@ -29,7 +29,7 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\Forbidden;
class AuthToken extends \Espo\Core\Controllers\Record
{

View File

@@ -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);
}
}

View File

@@ -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
{

View File

@@ -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);
}
}

View File

@@ -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'),
]);
}
}

View File

@@ -29,8 +29,7 @@
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
@@ -40,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,

View File

@@ -29,7 +29,7 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\Forbidden;
class EmailAddress extends \Espo\Core\Controllers\Record
{

View File

@@ -33,4 +33,3 @@ class EmailFilter extends \Espo\Core\Controllers\Record
{
}

View File

@@ -29,7 +29,7 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\BadRequest;
class EmailFolder extends \Espo\Core\Controllers\Record
{

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -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();
}
}

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -29,7 +29,7 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\Forbidden;
class LastViewed extends \Espo\Core\Controllers\Base
{

View File

@@ -47,6 +47,8 @@ class Layout extends \Espo\Core\Controllers\Base
public function putActionUpdate($params, $data, $request)
{
$data = json_decode($request->getBodyContents());
if (is_object($data)) $data = get_object_vars($data);
if (!$this->getUser()->isAdmin()) throw new Forbidden();

View File

@@ -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();
}

View File

@@ -29,9 +29,6 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
use \Espo\Core\Exceptions\BadRequest;
class LeadCaptureLogRecord extends \Espo\Core\Controllers\Record
{

View File

@@ -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();

View File

@@ -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()

View File

@@ -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
{

View File

@@ -29,8 +29,6 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
class PhoneNumber extends \Espo\Core\Controllers\Record
{

View File

@@ -29,7 +29,7 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\Forbidden;
class Portal extends \Espo\Core\Controllers\Record
{

View File

@@ -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
{

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -29,8 +29,6 @@
namespace Espo\Controllers;
use \Espo\Core\Exceptions\Error;
class Template extends \Espo\Core\Controllers\Record
{

View File

@@ -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);

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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);
}

View 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';
}
}
}

View File

@@ -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';
}
}
}

View 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
{
}

View File

@@ -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;
}

View 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 ScopeAcl
{
}

View File

@@ -29,16 +29,26 @@
namespace Espo\Core\Acl;
use \Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Error;
use \Espo\ORM\Entity;
use \Espo\Entities\User;
use Espo\Entities\User;
use \Espo\Core\Utils\Config;
use \Espo\Core\Utils\Metadata;
use \Espo\Core\Utils\FieldManagerUtil;
use \Espo\Core\Utils\File\Manager as FileManager;
use Espo\Core\{
ORM\EntityManager,
ORM\Entity,
Utils\Config,
Utils\Metadata,
Utils\FieldUtil,
Utils\DataCache,
};
use StdClass;
use Traversable;
/**
* A table is generated for each user. Multiple roles are merged into a single table.
* This table is used for access checking.
*/
class Table
{
protected $type = 'acl';
@@ -47,7 +57,7 @@ class Table
private $data = null;
protected $cacheFilePath;
protected $cacheKey;
protected $actionList = ['read', 'stream', 'edit', 'delete', 'create'];
@@ -59,26 +69,35 @@ class Table
protected $fieldLevelList = ['yes', 'no'];
protected $valuePermissionHighestLevels = array();
protected $valuePermissionHighestLevels = [];
protected $valuePermissionList = [];
private $fileManager;
protected $forbiddenAttributesCache = [];
private $metadata;
private $fieldManager;
protected $forbiddenAttributesCache = array();
protected $forbiddenFieldsCache = array();
protected $forbiddenFieldsCache = [];
protected $isStrictModeForced = false;
protected $isStrictMode = false;
public function __construct(User $user, Config $config = null, FileManager $fileManager = null, Metadata $metadata = null, FieldManagerUtil $fieldManager = null)
{
protected $entityManager;
protected $user;
protected $config;
protected $metadata;
protected $fieldUtil;
protected $dataCache;
public function __construct(
EntityManager $entityManager,
User $user,
Config $config = null,
Metadata $metadata = null,
FieldUtil $fieldUtil = null,
DataCache $dataCache
) {
$this->entityManager = $entityManager;
$this->data = (object) [
'table' => (object) [],
'fieldTable' => (object) [],
@@ -92,39 +111,34 @@ class Table
}
$this->user = $user;
$this->metadata = $metadata;
if ($fieldManager) {
$this->fieldManager = $fieldManager;
}
$this->fieldUtil = $fieldUtil;
$this->dataCache = $dataCache;
if (!$this->user->isFetched()) {
throw new Error('User must be fetched before ACL check.');
}
if ($fileManager) {
$this->fileManager = $fileManager;
}
$this->valuePermissionList = $this->metadata->get(['app', $this->type, 'valuePermissionList'], []);
$this->valuePermissionHighestLevels = $this->metadata->get(['app', $this->type, 'valuePermissionHighestLevels'], array());
$this->valuePermissionHighestLevels = $this->metadata->get(['app', $this->type, 'valuePermissionHighestLevels'], []);
$this->initCacheFilePath();
$this->initCacheKey();
if ($config && $config->get('useCache') && file_exists($this->cacheFilePath)) {
$cached = include $this->cacheFilePath;
$this->data = $cached;
} else {
if ($config && $config->get('useCache') && $this->dataCache->has($this->cacheKey)) {
$this->data = $this->dataCache->get($this->cacheKey);
}
else {
$this->load();
if ($config && $fileManager && $config->get('useCache')) {
if ($config && $config->get('useCache')) {
$this->buildCache();
}
}
}
protected function initCacheFilePath()
protected function initCacheKey()
{
$this->cacheFilePath = 'data/cache/application/acl/' . $this->getUser()->id . '.php';
$this->cacheKey = 'acl/' . $this->getUser()->id;
}
protected function getUser()
@@ -137,12 +151,12 @@ class Table
return $this->metadata;
}
protected function getFieldManager()
protected function getFieldUtil()
{
return $this->fieldManager;
return $this->fieldUtil;
}
public function getMap()
public function getMap() : StdClass
{
return $this->data;
}
@@ -151,16 +165,20 @@ class Table
{
if (isset($this->data->table->$scope)) {
$data = $this->data->table->$scope;
if (is_string($data)) {
$data = $this->getScopeData($data);
return $data;
}
return $data;
}
return null;
}
public function get($permission)
public function get(string $permission) : ?string
{
if ($permission == 'table') {
return null;
@@ -169,32 +187,36 @@ class Table
if (isset($this->data->$permission)) {
return $this->data->$permission;
}
return 'no';
}
public function getLevel($scope, $action)
public function getLevel(string $scope, string $action) : string
{
if (isset($this->data->table->$scope)) {
if (isset($this->data->table->$scope->$action)) {
return $this->data->table->$scope->$action;
}
}
return 'no';
}
public function getHighestLevel($scope, $action)
public function getHighestLevel(string $scope, string $action) : string
{
if (in_array($action, $this->booleanActionList)) {
return 'yes';
} else {
$level = $this->metadata->get(['scopes', $scope, $this->type . 'HighestLevel']);
return $level ?? 'all';
}
$level = $this->metadata->get(['scopes', $scope, $this->type . 'HighestLevel']);
return $level ?? 'all';
}
private function load()
{
$valuePermissionLists = (object)[];
$valuePermissionLists = (object) [];
foreach ($this->valuePermissionList as $permission) {
$valuePermissionLists->$permission = [];
}
@@ -208,6 +230,7 @@ class Table
foreach ($roleList as $role) {
$aclTableList[] = $role->get('data');
$fieldTableList[] = $role->get('fieldData');
foreach ($this->valuePermissionList as $permission) {
$valuePermissionLists->{$permission}[] = $role->get($permission);
}
@@ -220,17 +243,20 @@ class Table
$this->applyDisabled($aclTable, $fieldTable);
$this->applyMandatory($aclTable, $fieldTable);
$this->applyAdditional($aclTable, $fieldTable, $valuePermissionLists);
$this->applyReadOnlyFields($fieldTable);
} else {
}
else {
$aclTable = (object) [];
foreach ($this->getScopeList() as $scope) {
if ($this->metadata->get("scopes.{$scope}.{$this->type}") === 'boolean') {
$aclTable->$scope = true;
} else {
if ($this->metadata->get("scopes.{$scope}.entity")) {
$aclTable->$scope = (object) [];
foreach ($this->actionList as $action) {
$aclTable->$scope->$action = 'all';
if (in_array($action, $this->booleanActionList)) {
$aclTable->$scope->$action = 'yes';
}
@@ -256,11 +282,17 @@ class Table
if (!$this->getUser()->isAdmin()) {
$permissionsDefaultsGroupName = 'permissionsDefaults';
if ($this->isStrictMode) {
$permissionsDefaultsGroupName = 'permissionsStrictDefaults';
}
foreach ($this->valuePermissionList as $permission) {
$this->data->$permission = $this->mergeValueList($valuePermissionLists->$permission, $this->metadata->get(['app', $this->type, $permissionsDefaultsGroupName, $permission, 'yes']));
$this->data->$permission = $this->mergeValueList(
$valuePermissionLists->$permission,
$this->metadata->get(['app', $this->type, $permissionsDefaultsGroupName, $permission, 'yes'])
);
if ($this->metadata->get('app.'.$this->type.'.mandatory.' . $permission)) {
$this->data->$permission = $this->metadata->get('app.'.$this->type.'.mandatory.' . $permission);
}
@@ -270,8 +302,10 @@ class Table
foreach ($this->valuePermissionList as $permission) {
if (isset($this->valuePermissionHighestLevels[$permission])) {
$this->data->$permission = $this->valuePermissionHighestLevels[$permission];
continue;
}
$this->data->$permission = 'all';
}
}
@@ -281,20 +315,34 @@ class Table
{
$roleList = [];
$userRoleList = $this->getUser()->get('roles');
if (!(is_array($userRoleList) || $userRoleList instanceof \Traversable)) {
$userRoleList = $this->entityManager
->getRepository('User')
->getRelation($this->getUser(), 'roles')
->find();
if (! $userRoleList instanceof Traversable) {
throw new Error();
}
foreach ($userRoleList as $role) {
$roleList[] = $role;
}
$teamList = $this->getUser()->get('teams');
if (!(is_array($teamList) || $teamList instanceof \Traversable)) {
$teamList = $this->entityManager
->getRepository('User')
->getRelation($this->getUser(), 'teams')
->find();
if (! $teamList instanceof Traversable) {
throw new Error();
}
foreach ($teamList as $team) {
$teamRoleList = $team->get('roles');
$teamRoleList = $this->entityManager
->getRepository('Team')
->getRelation($team, 'roles')
->find();
foreach ($teamRoleList as $role) {
$roleList[] = $role;
}
@@ -303,21 +351,27 @@ class Table
return $roleList;
}
public function getScopeForbiddenAttributeList($scope, $action = 'read', $thresholdLevel = 'no')
public function getScopeForbiddenAttributeList(string $scope, string $action = 'read', string $thresholdLevel = 'no') : array
{
$key = $scope . '_'. $action . '_' . $thresholdLevel;
if (isset($this->forbiddenAttributesCache[$key])) {
return $this->forbiddenAttributesCache[$key];
}
$fieldTableQuickAccess = $this->data->fieldTableQuickAccess;
if (!isset($fieldTableQuickAccess->$scope) || !isset($fieldTableQuickAccess->$scope->attributes) || !isset($fieldTableQuickAccess->$scope->attributes->$action)) {
if (
!isset($fieldTableQuickAccess->$scope) || !isset($fieldTableQuickAccess->$scope->attributes) ||
!isset($fieldTableQuickAccess->$scope->attributes->$action)
) {
$this->forbiddenAttributesCache[$key] = [];
return [];
}
$levelList = [];
foreach ($this->fieldLevelList as $level) {
if (array_search($level, $this->fieldLevelList) >= array_search($thresholdLevel, $this->fieldLevelList)) {
$levelList[] = $level;
@@ -327,9 +381,15 @@ class Table
$attributeList = [];
foreach ($levelList as $level) {
if (!isset($fieldTableQuickAccess->$scope->attributes->$action->$level)) continue;
if (!isset($fieldTableQuickAccess->$scope->attributes->$action->$level)) {
continue;
}
foreach ($fieldTableQuickAccess->$scope->attributes->$action->$level as $attribute) {
if (in_array($attribute, $attributeList)) continue;
if (in_array($attribute, $attributeList)) {
continue;
}
$attributeList[] = $attribute;
}
}
@@ -339,7 +399,7 @@ class Table
return $attributeList;
}
public function getScopeForbiddenFieldList($scope, $action = 'read', $thresholdLevel = 'no')
public function getScopeForbiddenFieldList(string $scope, string $action = 'read', string $thresholdLevel = 'no') : array
{
$key = $scope . '_'. $action . '_' . $thresholdLevel;
if (isset($this->forbiddenFieldsCache[$key])) {
@@ -348,12 +408,17 @@ class Table
$fieldTableQuickAccess = $this->data->fieldTableQuickAccess;
if (!isset($fieldTableQuickAccess->$scope) || !isset($fieldTableQuickAccess->$scope->fields) || !isset($fieldTableQuickAccess->$scope->fields->$action)) {
if (
!isset($fieldTableQuickAccess->$scope) || !isset($fieldTableQuickAccess->$scope->fields) ||
!isset($fieldTableQuickAccess->$scope->fields->$action)
) {
$this->forbiddenFieldsCache[$key] = [];
return [];
}
$levelList = [];
foreach ($this->fieldLevelList as $level) {
if (array_search($level, $this->fieldLevelList) >= array_search($thresholdLevel, $this->fieldLevelList)) {
$levelList[] = $level;
@@ -363,9 +428,15 @@ class Table
$fieldList = [];
foreach ($levelList as $level) {
if (!isset($fieldTableQuickAccess->$scope->fields->$action->$level)) continue;
if (!isset($fieldTableQuickAccess->$scope->fields->$action->$level)) {
continue;
}
foreach ($fieldTableQuickAccess->$scope->fields->$action->$level as $field) {
if (in_array($field, $fieldList)) continue;
if (in_array($field, $fieldList)) {
continue;
}
$fieldList[] = $field;
}
}
@@ -390,6 +461,7 @@ class Table
foreach ($this->fieldActionList as $action) {
$fieldTableQuickAccess->$scope->attributes->$action = (object) [];
$fieldTableQuickAccess->$scope->fields->$action = (object) [];
foreach ($this->fieldLevelList as $level) {
$fieldTableQuickAccess->$scope->attributes->$action->$level = [];
$fieldTableQuickAccess->$scope->fields->$action->$level = [];
@@ -397,13 +469,17 @@ class Table
}
foreach (get_object_vars($scopeData) as $field => $fieldData) {
$attributeList = $this->getFieldManager()->getAttributeList($scope, $field);
$attributeList = $this->getFieldUtil()->getAttributeList($scope, $field);
foreach ($this->fieldActionList as $action) {
if (!isset($fieldData->$action)) continue;
if (!isset($fieldData->$action)) {
continue;
}
foreach ($this->fieldLevelList as $level) {
if ($fieldData->$action === $level) {
$fieldTableQuickAccess->$scope->fields->$action->{$level}[] = $field;
foreach ($attributeList as $attribute) {
$fieldTableQuickAccess->$scope->attributes->$action->{$level}[] = $attribute;
}
@@ -423,6 +499,7 @@ class Table
}
$defaultsGroupName = 'default';
if ($this->isStrictMode) {
$defaultsGroupName = 'strictDefault';
}
@@ -430,33 +507,53 @@ class Table
$data = $this->metadata->get(['app', $this->type, $defaultsGroupName, 'scopeLevel'], []);
foreach ($data as $scope => $item) {
if (isset($table->$scope)) continue;
if (isset($table->$scope)) {
continue;
}
$value = $item;
if (is_array($item)) {
$value = (object) $item;
}
$table->$scope = $value;
}
$defaultFieldData = $this->metadata->get(['app', $this->type, $defaultsGroupName, 'fieldLevel'], []);
foreach ($this->getScopeList() as $scope) {
if (isset($table->$scope) && $table->$scope === false) continue;
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) continue;
if (isset($table->$scope) && $table->$scope === false) {
continue;
}
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) {
continue;
}
$fieldList = array_keys($this->getMetadata()->get("entityDefs.{$scope}.fields", []));
$defaultScopeFieldData = $this->metadata->get('app.'.$this->type.'.'.$defaultsGroupName.'.scopeFieldLevel.' . $scope, []);
$defaultScopeFieldData = $this->metadata->get(
'app.'.$this->type.'.'.$defaultsGroupName.'.scopeFieldLevel.' . $scope, []);
foreach (array_merge($defaultFieldData, $defaultScopeFieldData) as $field => $f) {
if (!in_array($field, $fieldList)) continue;
if (!in_array($field, $fieldList)) {
continue;
}
if (!isset($fieldTable->$scope)) {
$fieldTable->$scope = (object) [];
}
if (isset($fieldTable->$scope->$field)) continue;
if (isset($fieldTable->$scope->$field)) {
continue;
}
$fieldTable->$scope->$field = (object) [];
foreach ($this->fieldActionList as $action) {
$level = 'no';
if ($f === true) {
$level = 'yes';
} else {
@@ -472,22 +569,32 @@ class Table
foreach ($this->getScopeWithAclList() as $scope) {
if (!isset($table->$scope)) {
$aclType = $this->metadata->get('scopes.' . $scope . '.' . $this->type);
if ($aclType === true) {
$aclType = $this->defaultAclType;
}
if (!empty($aclType)) {
$paramDefaultsName = 'scopeLevelTypesDefaults';
if ($this->isStrictMode) {
$paramDefaultsName = 'scopeLevelTypesStrictDefaults';
}
$defaultValue = $this->metadata->get(['app', $this->type, $paramDefaultsName, $aclType], $this->metadata->get(['app', $this->type, $paramDefaultsName, 'record']));
$defaultValue = $this->metadata->get(
['app', $this->type, $paramDefaultsName, $aclType],
$this->metadata->get(['app', $this->type, $paramDefaultsName, 'record'])
);
if (is_array($defaultValue)) {
$defaultValue = (object) $defaultValue;
}
$table->$scope = $defaultValue;
if (is_object($table->$scope)) {
$actionList = $this->getMetadata()->get(['scopes', $scope, $this->type . 'ActionList']);
if ($actionList) {
foreach (get_object_vars($table->$scope) as $action => $level) {
if (!in_array($action, $actionList)) {
@@ -511,30 +618,43 @@ class Table
foreach ($data as $scope => $item) {
$value = $item;
if (is_array($item)) {
$value = (object) $item;
}
$table->$scope = $value;
}
$mandatoryFieldData = $this->metadata->get('app.'.$this->type.'.mandatory.fieldLevel', array());
foreach ($this->getScopeList() as $scope) {
if (isset($table->$scope) && $table->$scope === false) continue;
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) continue;
if (isset($table->$scope) && $table->$scope === false) {
continue;
}
if (!$this->getMetadata()->get('scopes.' . $scope . '.entity')) {
continue;
}
$fieldList = array_keys($this->getMetadata()->get("entityDefs.{$scope}.fields", []));
$mandatoryScopeFieldData = $this->metadata->get('app.'.$this->type.'.mandatory.scopeFieldLevel.' . $scope, array());
foreach (array_merge($mandatoryFieldData, $mandatoryScopeFieldData) as $field => $f) {
if (!in_array($field, $fieldList)) continue;
if (!in_array($field, $fieldList)) {
continue;
}
if (!isset($fieldTable->$scope)) {
$fieldTable->$scope = (object) [];
}
$fieldTable->$scope->$field = (object) [];
foreach ($this->fieldActionList as $action) {
$level = 'no';
if ($f === true) {
$level = 'yes';
} else {
@@ -569,6 +689,7 @@ class Table
$table->$scope = false;
unset($fieldTable->$scope);
}
foreach ($this->valuePermissionList as $permission) {
$valuePermissionLists->{$permission}[] = 'no';
}
@@ -578,29 +699,38 @@ class Table
private function mergeValueList(array $list, $defaultValue)
{
$result = null;
foreach ($list as $level) {
if ($level != 'not-set') {
if (is_null($result)) {
$result = $level;
continue;
}
if (array_search($result, $this->levelList) > array_search($level, $this->levelList)) {
$result = $level;
}
}
}
if (is_null($result)) {
$result = $defaultValue;
}
return $result;
}
protected function getScopeWithAclList()
{
$scopeList = [];
$scopes = $this->metadata->get('scopes');
foreach ($scopes as $scope => $d) {
if (empty($d['acl'])) continue;
if (empty($d['acl'])) {
continue;
}
$scopeList[] = $scope;
}
return $scopeList;
@@ -609,10 +739,13 @@ class Table
protected function getScopeList()
{
$scopeList = [];
$scopes = $this->metadata->get('scopes');
foreach ($scopes as $scope => $d) {
$scopeList[] = $scope;
}
return $scopeList;
}
@@ -623,7 +756,9 @@ class Table
foreach ($tableList as $table) {
foreach ($scopeList as $scope) {
if (!isset($table->$scope)) continue;
if (!isset($table->$scope)) {
continue;
}
$row = $table->$scope;
@@ -631,9 +766,11 @@ class Table
if (!isset($data->$scope)) {
$data->$scope = false;
}
} else if ($row === true) {
}
else if ($row === true) {
$data->$scope = true;
} else {
}
else {
if (!isset($data->$scope)) {
$data->$scope = (object) [];
}
@@ -641,7 +778,9 @@ class Table
$data->$scope = (object) [];
}
if (!is_object($row)) continue;
if (!is_object($row)) {
continue;
}
$actionList = $this->getMetadata()->get(['scopes', $scope, $this->type . 'ActionList'], $this->actionList);
@@ -651,7 +790,9 @@ class Table
if (!isset($data->$scope->$action)) {
$data->$scope->$action = $level;
} else {
if (array_search($data->$scope->$action, $this->levelList) > array_search($level, $this->levelList)) {
if (
array_search($data->$scope->$action, $this->levelList) > array_search($level, $this->levelList)
) {
$data->$scope->$action = $level;
}
}
@@ -679,37 +820,54 @@ class Table
private function mergeFieldTableList(array $tableList)
{
$data = (object) [];
$scopeList = $this->getScopeWithAclList();
foreach ($tableList as $table) {
foreach ($scopeList as $scope) {
if (!isset($table->$scope)) continue;
if (!isset($table->$scope)) {
continue;
}
if (!isset($data->$scope)) {
$data->$scope = (object) [];
}
if (!is_object($table->$scope)) continue;
if (!is_object($table->$scope)) {
continue;
}
$fieldList = array_keys($this->getMetadata()->get("entityDefs.{$scope}.fields", []));
foreach (get_object_vars($table->$scope) as $field => $row) {
if (!is_object($row)) continue;
if (!is_object($row)) {
continue;
}
if (!in_array($field, $fieldList)) continue;
if (!in_array($field, $fieldList)) {
continue;
}
if (!isset($data->$scope->$field)) {
$data->$scope->$field = (object) [];
}
foreach ($this->fieldActionList as $i => $action) {
if (!isset($row->$action)) continue;
if (!isset($row->$action)) {
continue;
}
$level = $row->$action;
if (!isset($data->$scope->$field->$action)) {
$data->$scope->$field->$action = $level;
} else {
if (array_search($data->$scope->$field->$action, $this->fieldLevelList) > array_search($level, $this->fieldLevelList)) {
if (
array_search(
$data->$scope->$field->$action,
$this->fieldLevelList
) > array_search($level, $this->fieldLevelList)
) {
$data->$scope->$field->$action = $level;
}
}
@@ -723,30 +881,6 @@ class Table
private function buildCache()
{
$this->fileManager->putPhpContents($this->cacheFilePath, $this->data, true);
}
protected function applyReadOnlyFields(&$fieldTable)
{
// TODO Enable in 5.4.0
return;
$scopeList = $this->getScopeWithAclList();
foreach ($scopeList as $scope) {
if (!property_exists($fieldTable, $scope)) continue;
$fieldList = array_keys($this->getMetadata()->get(['entityDefs', $scope, 'fields'], []));
foreach ($fieldList as $field) {
if ($this->getMetadata()->get(['entityDefs', $scope, 'fields', $field, 'readOnly'])) {
if (property_exists($fieldTable->$scope, $field)) {
$fieldTable->$scope->$field->edit = 'no';
} else {
$fieldTable->$scope->$field = (object) [];
foreach ($this->fieldActionList as $action) {
$fieldTable->$scope->$field->$action = 'yes';
}
$fieldTable->$scope->$field->edit = 'no';
}
}
}
}
$this->dataCache->store($this->cacheKey, $this->data);
}
}

View File

@@ -29,79 +29,78 @@
namespace Espo\Core;
use \Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Error;
use \Espo\ORM\Entity;
use \Espo\Entities\User;
use \Espo\Core\Utils\Util;
use Espo\ORM\Entity;
use Espo\Entities\User;
use Espo\Core\{
Utils\ClassFinder,
Utils\Config,
ORM\EntityManager,
Acl\Acl as BaseAcl,
Acl\ScopeAcl,
Acl\GlobalRestricton,
Acl as UserAclWrapper,
Acl\Table as AclTable,
Utils\Util,
};
use StdClass;
/**
* Used to check access for a specific user.
*/
class AclManager
{
private $container;
private $metadata;
private $implementationHashMap = [];
private $tableHashMap = [];
protected $tableClassName = '\\Espo\\Core\\Acl\\Table';
protected $tableClassName = AclTable::class;
protected $userAclClassName = '\\Espo\\Core\\Acl';
protected $userAclClassName = UserAclWrapper::class;
protected $baseImplementationClassName = BaseAcl::class;
protected $globalRestricton;
public function __construct(Container $container)
{
$this->container = $container;
$this->metadata = $container->get('metadata');
protected $injectableFactory;
protected $classFinder;
protected $config;
protected $entityManager;
$this->globalRestricton = new \Espo\Core\Acl\GlobalRestricton(
$container->get('metadata'),
$container->get('fileManager'),
$container->get('fieldManagerUtil'),
$container->get('config')->get('useCache')
);
public function __construct(
InjectableFactory $injectableFactory, ClassFinder $classFinder, Config $config, EntityManager $entityManager
) {
$this->injectableFactory = $injectableFactory;
$this->classFinder = $classFinder;
$this->config = $config;
$this->entityManager = $entityManager;
$this->globalRestricton = $this->injectableFactory->createWith(GlobalRestricton::class, [
'useCache' => $config->get('useCache'),
]);
}
protected function getContainer()
{
return $this->container;
}
protected function getMetadata()
{
return $this->metadata;
}
public function getImplementation($scope)
public function getImplementation(string $scope) : ScopeAcl
{
if (empty($this->implementationHashMap[$scope])) {
$normalizedName = Util::normilizeClassName($scope);
$className = $this->classFinder->find('Acl', $scope);
if (!$className) {
$className = $this->baseImplementationClassName;
}
$className = '\\Espo\\Custom\\Acl\\' . $normalizedName;
if (!class_exists($className)) {
$moduleName = $this->metadata->getScopeModuleName($scope);
if ($moduleName) {
$className = '\\Espo\\Modules\\' . $moduleName . '\\Acl\\' . $normalizedName;
} else {
$className = '\\Espo\\Acl\\' . $normalizedName;
}
if (!class_exists($className)) {
$className = '\\Espo\\Core\\Acl\\Base';
}
throw new Error("{$className} does not exist.");
}
if (class_exists($className)) {
$acl = new $className($scope);
$dependencyList = $acl->getDependencyList();
foreach ($dependencyList as $name) {
$acl->inject($name, $this->getContainer()->get($name));
}
$this->implementationHashMap[$scope] = $acl;
} else {
throw new Error();
}
$acl = $this->injectableFactory->createWith($className, [
'scope' => $scope,
]);
$this->implementationHashMap[$scope] = $acl;
}
return $this->implementationHashMap[$scope];
@@ -110,80 +109,115 @@ class AclManager
protected function getTable(User $user)
{
$key = $user->id;
if (empty($key)) {
$key = spl_object_hash($user);
}
if (empty($this->tableHashMap[$key])) {
$config = $this->getContainer()->get('config');
$fileManager = $this->getContainer()->get('fileManager');
$metadata = $this->getContainer()->get('metadata');
$fieldManager = $this->getContainer()->get('fieldManagerUtil');
$this->tableHashMap[$key] = new $this->tableClassName($user, $config, $fileManager, $metadata, $fieldManager);
$this->tableHashMap[$key] = $this->injectableFactory->createWith($this->tableClassName, [
'user' => $user,
]);
}
return $this->tableHashMap[$key];
}
public function getMap(User $user)
public function getMap(User $user) : StdClass
{
return $this->getTable($user)->getMap();
}
public function getLevel(User $user, $scope, $action)
/**
* Get an access level for a specific scope and action.
*/
public function getLevel(User $user, string $scope, string $action) : string
{
if ($user->isAdmin()) {
return $this->getTable($user)->getHighestLevel($scope, $action);
}
return $this->getTable($user)->getLevel($scope, $action);
}
public function get(User $user, $permission)
/**
* Get a permission. E.g. 'assignment' permission.
*/
public function get(User $user, string $permission) : ?string
{
if (substr($permission, -10) !== 'Permission') {
$permission .= 'Permission';
}
return $this->getTable($user)->get($permission);
}
public function checkReadNo(User $user, $scope)
/**
* Whether there's no 'read' access for a specific scope.
*/
public function checkReadNo(User $user, string $scope) : bool
{
if ($user->isAdmin()) {
return false;
}
$data = $this->getTable($user)->getScopeData($scope);
return $this->getImplementation($scope)->checkReadNo($user, $data);
return (bool) $this->getImplementation($scope)->checkReadNo($user, $data);
}
public function checkReadOnlyTeam(User $user, $scope)
/**
* Whether 'read' access is set to 'team' for a specific scope.
*/
public function checkReadOnlyTeam(User $user, string $scope) : bool
{
if ($user->isAdmin()) {
return false;
}
$data = $this->getTable($user)->getScopeData($scope);
return $this->getImplementation($scope)->checkReadOnlyTeam($user, $data);
return (bool) $this->getImplementation($scope)->checkReadOnlyTeam($user, $data);
}
public function checkReadOnlyOwn(User $user, $scope)
/**
* Whether 'read' access is set to 'own' for a specific scope.
*/
public function checkReadOnlyOwn(User $user, string $scope) : bool
{
if ($user->isAdmin()) {
return false;
}
$data = $this->getTable($user)->getScopeData($scope);
return $this->getImplementation($scope)->checkReadOnlyOwn($user, $data);
return (bool) $this->getImplementation($scope)->checkReadOnlyOwn($user, $data);
}
public function check(User $user, $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(User $user, $subject, ?string $action = null) : bool
{
if (is_string($subject)) {
return $this->checkScope($user, $subject, $action);
} else {
$entity = $subject;
if ($entity instanceof Entity) {
return $this->checkEntity($user, $entity, $action);
}
}
$entity = $subject;
if ($entity instanceof Entity) {
$action = $action ?? 'read';
return $this->checkEntity($user, $entity, $action);
}
return false;
}
public function checkEntity(User $user, Entity $entity, $action = 'read')
/**
* Check access to a specific entity (record).
*/
public function checkEntity(User $user, Entity $entity, string $action = 'read') : bool
{
$scope = $entity->getEntityType();
@@ -197,60 +231,79 @@ class AclManager
if ($action) {
$methodName = 'checkEntity' . ucfirst($action);
if (method_exists($impl, $methodName)) {
return $impl->$methodName($user, $entity, $data);
return (bool) $impl->$methodName($user, $entity, $data);
}
}
return $impl->checkEntity($user, $entity, $data, $action);
return (bool) $impl->checkEntity($user, $entity, $data, $action);
}
public function checkIsOwner(User $user, Entity $entity)
/**
* Whether a user is owned of an entity (record). Usually 'assignedUser' field is used for checking.
*/
public function checkIsOwner(User $user, Entity $entity) : bool
{
return $this->getImplementation($entity->getEntityType())->checkIsOwner($user, $entity);
return (bool) $this->getImplementation($entity->getEntityType())->checkIsOwner($user, $entity);
}
public function checkInTeam(User $user, Entity $entity)
/**
* Whether a user team list overlaps with teams set in an entity.
*/
public function checkInTeam(User $user, Entity $entity) : bool
{
return $this->getImplementation($entity->getEntityType())->checkInTeam($user, $entity);
return (bool) $this->getImplementation($entity->getEntityType())->checkInTeam($user, $entity);
}
public function checkScope(User $user, $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(User $user, string $scope, ?string $action = null) : bool
{
$data = $this->getTable($user)->getScopeData($scope);
return $this->getImplementation($scope)->checkScope($user, $data, $action);
return (bool) $this->getImplementation($scope)->checkScope($user, $data, $action);
}
public function checkUser(User $user, $permission, User $entity)
/**
* @deprecated Use checkUserPermission instead.
*/
public function checkUser(User $user, string $permission, User $target) : bool
{
if ($user->isAdmin()) {
return true;
}
if ($this->get($user, $permission) === 'no') {
if ($entity->id !== $user->id) {
if ($target->id !== $user->id) {
return false;
}
} else if ($this->get($user, $permission) === 'team') {
if ($entity->id != $user->id) {
if ($target->id != $user->id) {
$teamIdList1 = $user->getTeamIdList();
$teamIdList2 = $entity->getTeamIdList();
$teamIdList2 = $target->getTeamIdList();
$inTeam = false;
foreach ($teamIdList1 as $id) {
if (in_array($id, $teamIdList2)) {
$inTeam = true;
break;
}
}
if (!$inTeam) {
return false;
}
}
}
return true;
}
protected function getGlobalRestrictionTypeList(User $user, $action = 'read')
protected function getGlobalRestrictionTypeList(User $user, string $action = 'read') : array
{
$typeList = ['forbidden'];
@@ -264,6 +317,7 @@ class AclManager
if ($action === 'edit') {
$typeList[] = 'readOnly';
if (!$user->isAdmin()) {
$typeList[] = 'nonAdminReadOnly';
}
@@ -272,8 +326,12 @@ class AclManager
return $typeList;
}
public function getScopeForbiddenAttributeList(User $user, $scope, $action = 'read', $thresholdLevel = 'no')
{
/**
* Get attributes forbidden for a user.
*/
public function getScopeForbiddenAttributeList(
User $user, string $scope, string $action = 'read', string $thresholdLevel = 'no'
) : array {
$list = [];
if (!$user->isAdmin()) {
@@ -285,14 +343,19 @@ class AclManager
$list,
$this->getScopeRestrictedAttributeList($scope, $this->getGlobalRestrictionTypeList($user, $action))
);
$list = array_values($list);
}
return $list;
}
public function getScopeForbiddenFieldList(User $user, $scope, $action = 'read', $thresholdLevel = 'no')
{
/**
* Get fields forbidden for a user.
*/
public function getScopeForbiddenFieldList(
User $user, string $scope, string $action = 'read', string $thresholdLevel = 'no'
) : array {
$list = [];
if (!$user->isAdmin()) {
@@ -304,15 +367,19 @@ class AclManager
$list,
$this->getScopeRestrictedFieldList($scope, $this->getGlobalRestrictionTypeList($user, $action))
);
$list = array_values($list);
}
return $list;
}
public function getScopeForbiddenLinkList(User $user, $scope, $action = 'read', $thresholdLevel = 'no')
{
/**
* Get links forbidden for a user.
*/
public function getScopeForbiddenLinkList(
User $user, string $scope, string $action = 'read', string $thresholdLevel = 'no'
) : array {
$list = [];
if ($thresholdLevel === 'no') {
@@ -320,13 +387,19 @@ class AclManager
$list,
$this->getScopeRestrictedLinkList($scope, $this->getGlobalRestrictionTypeList($user, $action))
);
$list = array_values($list);
}
return $list;
}
public function checkUserPermission(User $user, $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(User $user, $target, string $permissionType = 'user') : bool
{
$permission = $this->get($user, $permissionType);
@@ -348,7 +421,8 @@ class AclManager
if ($permission === 'team') {
$teamIdList = $user->getLinkMultipleIdList('teams');
if (!$this->getContainer()->get('entityManager')->getRepository('User')->checkBelongsToAnyOfTeams($userId, $teamIdList)) {
if (!$this->entityManager->getRepository('User')->checkBelongsToAnyOfTeams($userId, $teamIdList)) {
return false;
}
}
@@ -356,57 +430,77 @@ class AclManager
return true;
}
public function checkAssignmentPermission(User $user, $target)
/**
* Whether a user can assign to another user.
*
* @param $target User|string User entity or user ID.
*/
public function checkAssignmentPermission(User $user, $target) : bool
{
return $this->checkUserPermission($user, $target, 'assignmentPermission');
return $this->checkUserPermission($user, $target, 'assignment');
}
public function createUserAcl(User $user)
/**
* Create a wrapper for a specific user.
*/
public function createUserAcl(User $user) : UserAclWrapper
{
$className = $this->userAclClassName;
$acl = new $className($this, $user);
return $acl;
}
public function getScopeRestrictedFieldList($scope, $type)
public function getScopeRestrictedFieldList(string $scope, $type) : array
{
if (is_array($type)) {
$typeList = $type;
$list = [];
foreach ($typeList as $type) {
$list = array_merge($list, $this->globalRestricton->getScopeRestrictedFieldList($scope, $type));
}
$list = array_values($list);
return $list;
}
return $this->globalRestricton->getScopeRestrictedFieldList($scope, $type);
}
public function getScopeRestrictedAttributeList($scope, $type)
public function getScopeRestrictedAttributeList(string $scope, $type) : array
{
if (is_array($type)) {
$typeList = $type;
$list = [];
foreach ($typeList as $type) {
$list = array_merge($list, $this->globalRestricton->getScopeRestrictedAttributeList($scope, $type));
}
$list = array_values($list);
return $list;
}
return $this->globalRestricton->getScopeRestrictedAttributeList($scope, $type);
}
public function getScopeRestrictedLinkList($scope, $type)
public function getScopeRestrictedLinkList(string $scope, $type) : array
{
if (is_array($type)) {
$typeList = $type;
$list = [];
foreach ($typeList as $type) {
$list = array_merge($list, $this->globalRestricton->getScopeRestrictedLinkList($scope, $type));
}
$list = array_values($list);
return $list;
}
return $this->globalRestricton->getScopeRestrictedLinkList($scope, $type);
}
}

View File

@@ -0,0 +1,37 @@
<?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\AclPortal;
use Espo\Core\Acl\Acl as BaseAcl;
class Acl extends BaseAcl implements PortalScopeAcl
{
use Portal;
}

View File

@@ -29,188 +29,9 @@
namespace Espo\Core\AclPortal;
use \Espo\Entities\User;
use \Espo\ORM\Entity;
class Base extends \Espo\Core\Acl\Base
/** @deprecated */
class Base extends \Espo\Core\Acl\Base implements PortalScopeAcl
{
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'];
}
$inAccount = null;
if (isset($entityAccessData['inAccount'])) {
$inAccount = $entityAccessData['inAccount'];
}
$isOwnContact = null;
if (isset($entityAccessData['isOwnContact'])) {
$isOwnContact = $entityAccessData['isOwnContact'];
}
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 === 'account' || $value === 'contact') {
return true;
}
}
if ($value === 'account') {
if (is_null($inAccount) && $entity) {
$inAccount = $this->checkInAccount($user, $entity);
}
if ($inAccount) {
return true;
} else {
if (is_null($isOwnContact) && $entity) {
$isOwnContact = $this->checkIsOwnContact($user, $entity);
}
if ($isOwnContact) {
return true;
}
}
}
if ($value === 'contact') {
if (is_null($isOwnContact) && $entity) {
$isOwnContact = $this->checkIsOwnContact($user, $entity);
}
if ($isOwnContact) {
return true;
}
}
return false;
}
public function checkReadOnlyAccount(User $user, $data)
{
if (empty($data) || !is_object($data) || !isset($data->read)) {
return false;
}
return $data->read === 'account';
}
public function checkReadOnlyContact(User $user, $data)
{
if (empty($data) || !is_object($data) || !isset($data->read)) {
return false;
}
return $data->read === 'contact';
}
public function checkIsOwner(User $user, Entity $entity)
{
if ($entity->hasAttribute('createdById')) {
if ($entity->has('createdById')) {
if ($user->id === $entity->get('createdById')) {
return true;
}
}
}
return false;
}
public function checkInAccount(User $user, Entity $entity)
{
$accountIdList = $user->getLinkMultipleIdList('accounts');
if (count($accountIdList)) {
if ($entity->hasAttribute('accountId') && $entity->getRelationParam('account', 'entity') === 'Account') {
if (in_array($entity->get('accountId'), $accountIdList)) {
return true;
}
}
if ($entity->hasRelation('accounts') && $entity->getRelationParam('accounts', 'entity') === 'Account') {
$repository = $this->getEntityManager()->getRepository($entity->getEntityType());
foreach ($accountIdList as $accountId) {
if ($repository->isRelated($entity, 'accounts', $accountId)) {
return true;
}
}
}
if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) {
if ($entity->get('parentType') === 'Account') {
if (in_array($entity->get('parentId'), $accountIdList)) {
return true;
}
}
}
}
return false;
}
public function checkIsOwnContact(User $user, Entity $entity)
{
$contactId = $user->get('contactId');
if ($contactId) {
if ($entity->hasAttribute('contactId') && $entity->getRelationParam('contact', 'entity') === 'Contact') {
if ($entity->get('contactId') === $contactId) {
return true;
}
}
if ($entity->hasRelation('contacts') && $entity->getRelationParam('contacts', 'entity') === 'Contact') {
$repository = $this->getEntityManager()->getRepository($entity->getEntityType());
if ($repository->isRelated($entity, 'contacts', $contactId)) {
return true;
}
}
if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) {
if ($entity->get('parentType') === 'Contact') {
if ($entity->get('parentId') === $contactId) {
return true;
}
}
}
}
return false;
}
use Portal;
}

View File

@@ -0,0 +1,216 @@
<?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\AclPortal;
use Espo\Entities\User;
use Espo\ORM\Entity;
trait Portal
{
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'];
}
$inAccount = null;
if (isset($entityAccessData['inAccount'])) {
$inAccount = $entityAccessData['inAccount'];
}
$isOwnContact = null;
if (isset($entityAccessData['isOwnContact'])) {
$isOwnContact = $entityAccessData['isOwnContact'];
}
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 === 'account' || $value === 'contact') {
return true;
}
}
if ($value === 'account') {
if (is_null($inAccount) && $entity) {
$inAccount = $this->checkInAccount($user, $entity);
}
if ($inAccount) {
return true;
} else {
if (is_null($isOwnContact) && $entity) {
$isOwnContact = $this->checkIsOwnContact($user, $entity);
}
if ($isOwnContact) {
return true;
}
}
}
if ($value === 'contact') {
if (is_null($isOwnContact) && $entity) {
$isOwnContact = $this->checkIsOwnContact($user, $entity);
}
if ($isOwnContact) {
return true;
}
}
return false;
}
public function checkReadOnlyAccount(User $user, $data)
{
if (empty($data) || !is_object($data) || !isset($data->read)) {
return false;
}
return $data->read === 'account';
}
public function checkReadOnlyContact(User $user, $data)
{
if (empty($data) || !is_object($data) || !isset($data->read)) {
return false;
}
return $data->read === 'contact';
}
public function checkIsOwner(User $user, Entity $entity)
{
if ($entity->hasAttribute('createdById')) {
if ($entity->has('createdById')) {
if ($user->id === $entity->get('createdById')) {
return true;
}
}
}
return false;
}
public function checkInAccount(User $user, Entity $entity)
{
$accountIdList = $user->getLinkMultipleIdList('accounts');
if (count($accountIdList)) {
if ($entity->hasAttribute('accountId') && $entity->getRelationParam('account', 'entity') === 'Account') {
if (in_array($entity->get('accountId'), $accountIdList)) {
return true;
}
}
if ($entity->hasRelation('accounts') && $entity->getRelationParam('accounts', 'entity') === 'Account') {
$repository = $this->getEntityManager()->getRepository($entity->getEntityType());
foreach ($accountIdList as $accountId) {
if ($repository->isRelated($entity, 'accounts', $accountId)) {
return true;
}
}
}
if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) {
if ($entity->get('parentType') === 'Account') {
if (in_array($entity->get('parentId'), $accountIdList)) {
return true;
}
}
}
}
return false;
}
public function checkIsOwnContact(User $user, Entity $entity)
{
$contactId = $user->get('contactId');
if ($contactId) {
if ($entity->hasAttribute('contactId') && $entity->getRelationParam('contact', 'entity') === 'Contact') {
if ($entity->get('contactId') === $contactId) {
return true;
}
}
if ($entity->hasRelation('contacts') && $entity->getRelationParam('contacts', 'entity') === 'Contact') {
$repository = $this->getEntityManager()->getRepository($entity->getEntityType());
if ($repository->isRelated($entity, 'contacts', $contactId)) {
return true;
}
}
if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) {
if ($entity->get('parentType') === 'Contact') {
if ($entity->get('parentId') === $contactId) {
return true;
}
}
}
}
return false;
}
}

View File

@@ -27,10 +27,9 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Interfaces;
namespace Espo\Core\AclPortal;
interface InjectableService
interface PortalScopeAcl
{
public function inject(string $name, object $object);
}
}

Some files were not shown because too many files have changed in this diff Show More