WecomCenterSave.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php declare(strict_types = 0);
  2. /*
  3. ** WeCom Center - POST controller. Dispatches actions and redirects back.
  4. */
  5. namespace Modules\WecomCenter\Actions;
  6. use CController;
  7. use CControllerResponseRedirect;
  8. use CUrl;
  9. use CWebUser;
  10. use Exception;
  11. use Modules\WecomCenter\Lib\Helper;
  12. use Modules\WecomCenter\Lib\I18n;
  13. class WecomCenterSave extends CController {
  14. protected function init() {
  15. $this->disableCsrfValidation();
  16. }
  17. protected function checkInput() {
  18. return true;
  19. }
  20. protected function checkPermissions() {
  21. return CWebUser::getType() == USER_TYPE_SUPER_ADMIN;
  22. }
  23. protected function doAction() {
  24. $mediatypeid = (string) ($_REQUEST['mediatypeid'] ?? '');
  25. try {
  26. // Strategy apply buttons are submitted as name="apply_strategy" value=<preset>.
  27. if (isset($_REQUEST['apply_strategy'])) {
  28. $this->applyStrategy($mediatypeid, (string) $_REQUEST['apply_strategy']);
  29. }
  30. else {
  31. $op = (string) ($_REQUEST['op'] ?? '');
  32. switch ($op) {
  33. case 'save_alert': $this->saveAlert($mediatypeid); break;
  34. case 'save_triggers': $this->saveTriggers(); break;
  35. case 'save_robot': $this->saveRobot($mediatypeid); break;
  36. case 'test_robot': $this->testRobot($mediatypeid); break;
  37. case 'import_template': $this->importTemplate(); break;
  38. case 'save_map': $this->saveMap(); break;
  39. case 'apply_switch': $this->applySwitch(); break;
  40. case 'init_env': $this->initEnv(); break;
  41. default: error(I18n::t('msg.unknown_op'));
  42. }
  43. }
  44. }
  45. catch (Exception $e) {
  46. error($e->getMessage());
  47. }
  48. $url = (new CUrl('zabbix.php'))->setArgument('action', 'wecom.center.view');
  49. if ($mediatypeid !== '') {
  50. $url->setArgument('mediatypeid', $mediatypeid);
  51. }
  52. $tab = (string) ($_REQUEST['tab'] ?? '');
  53. if (in_array($tab, ['alert', 'opt', 'maint'], true)) {
  54. $url->setArgument('tab', $tab);
  55. }
  56. $this->setResponse(new CControllerResponseRedirect($url));
  57. }
  58. private function applyStrategy(string $mediatypeid, string $key): void {
  59. if (!isset(Helper::STRATEGY_PRESETS[$key])) {
  60. throw new Exception(I18n::t('msg.bad_scheme'));
  61. }
  62. $tid = Helper::templateHostid();
  63. if ($tid === null) {
  64. throw new Exception(I18n::t('msg.no_template_host'));
  65. }
  66. $preset = Helper::STRATEGY_PRESETS[$key];
  67. // 1) threshold on the media (global "how severe still notifies")
  68. if ($mediatypeid !== '') {
  69. $user = Helper::ensureRobotUser('wecomrobot');
  70. $mask = Helper::severityMaskFromMin((int) $preset['min']);
  71. Helper::applyMedia($user['userid'], $mediatypeid, $mask, 0);
  72. }
  73. // 2) classify + write severities
  74. $res = Helper::applyStrategy($tid, $preset['targets']);
  75. Helper::saveStrategyKey($key);
  76. info(I18n::t('msg.strategy_applied', [
  77. I18n::t($preset['label']),
  78. $res['trigger'],
  79. $res['prototype'],
  80. $res['discovered']
  81. ]));
  82. }
  83. private function saveAlert(string $mediatypeid): void {
  84. $active = isset($_REQUEST['enabled']) ? 0 : 1; // media: 0=enabled, 1=disabled
  85. $indices = [];
  86. for ($i = 1; $i <= 6; $i++) {
  87. if (isset($_REQUEST['sev_'.$i])) {
  88. $indices[] = $i;
  89. }
  90. }
  91. $mask = Helper::severityMask($indices);
  92. if ($mask === 0 && $active === 0) {
  93. $mask = 2;
  94. }
  95. $user = Helper::ensureRobotUser('wecomrobot');
  96. Helper::applyMedia($user['userid'], $mediatypeid, $mask, $active);
  97. info(I18n::t('msg.saved'));
  98. }
  99. private function saveRobot(string $mediatypeid): void {
  100. $url = trim((string) ($_REQUEST['webhook_url'] ?? ''));
  101. if ($url !== '') {
  102. Helper::setWebhookKey($url);
  103. }
  104. $user = Helper::ensureRobotUser('wecomrobot');
  105. $cur = Helper::currentMedia($user, $mediatypeid);
  106. $mask = $cur['severity'] ?? 48;
  107. $active = $cur['active'] ?? 0;
  108. Helper::applyMedia($user['userid'], $mediatypeid, $mask, $active);
  109. info(I18n::t('msg.robot_saved'));
  110. }
  111. private function testRobot(string $mediatypeid): void {
  112. $mt = Helper::getMediatype($mediatypeid);
  113. if (!$mt) {
  114. throw new Exception(I18n::t('msg.no_mediatype'));
  115. }
  116. $url = Helper::webhookUrl($mt);
  117. if ($url === '') {
  118. throw new Exception(I18n::t('msg.no_url'));
  119. }
  120. $text = '['.I18n::t('page.title').'] Test OK - '.date('Y-m-d H:i:s');
  121. $res = Helper::testWebhook($url, $text);
  122. $body = (string) $res['body'];
  123. $ok = (strpos($body, '"errcode":0') !== false) || (strpos($body, '"errcode": 0') !== false);
  124. if ($ok) {
  125. info(I18n::t('msg.tested'));
  126. }
  127. else {
  128. error(I18n::t('msg.test_failed', [$res['status'], $body]));
  129. }
  130. }
  131. private function importTemplate(): void {
  132. $file = (string) ($_REQUEST['template_file'] ?? '');
  133. if ($file === '') {
  134. throw new Exception(I18n::t('msg.no_template'));
  135. }
  136. $module_dir = dirname(__DIR__);
  137. $res = Helper::importTemplate($module_dir, $file);
  138. $n = isset($res['templates']) && is_array($res['templates']) ? count($res['templates']) : 0;
  139. info(I18n::t('msg.imported', [$n]));
  140. }
  141. private function saveTriggers(): void {
  142. $ids = (string) ($_REQUEST['trig_ids'] ?? '');
  143. $ids = array_filter(array_map('trim', explode(',', $ids)));
  144. if (!$ids) {
  145. throw new Exception(I18n::t('msg.no_triggers'));
  146. }
  147. $map = [];
  148. foreach ($ids as $id) {
  149. $id = (string) (int) $id;
  150. if ($id === '' || $id === '0') {
  151. continue;
  152. }
  153. $map[$id] = isset($_REQUEST['trig_'.$id]) ? 0 : 1;
  154. }
  155. $n = Helper::setTriggersStatus($map);
  156. info(I18n::t('msg.triggers_saved', [$n]));
  157. }
  158. private function saveMap(): void {
  159. $hostid = (string) ($_REQUEST['hostid'] ?? '');
  160. $lat = trim((string) ($_REQUEST['lat'] ?? ''));
  161. $lon = trim((string) ($_REQUEST['lon'] ?? ''));
  162. if ($hostid === '') {
  163. throw new Exception(I18n::t('msg.no_host'));
  164. }
  165. Helper::setHostLocation($hostid, $lat, $lon);
  166. info(I18n::t('msg.map_saved'));
  167. }
  168. private function applySwitch(): void {
  169. $src = (string) ($_REQUEST['switch_src'] ?? '');
  170. $dst = (string) ($_REQUEST['switch_dst'] ?? '');
  171. if ($src === '' || $dst === '') {
  172. throw new Exception(I18n::t('msg.need_both'));
  173. }
  174. if ($src === $dst) {
  175. throw new Exception(I18n::t('msg.same_tpl'));
  176. }
  177. $n = Helper::switchApply($src, $dst);
  178. info(I18n::t('msg.switch_applied', [$n]));
  179. }
  180. private function initEnv(): void {
  181. $key = trim((string) ($_REQUEST['key'] ?? $_REQUEST['webhook_url'] ?? ''));
  182. $proto = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
  183. $host = (string) ($_SERVER['HTTP_HOST'] ?? '');
  184. $zbxUrl = $host !== '' ? $proto.'://'.$host : '';
  185. $r = Helper::initializeEnvironment($key, $zbxUrl);
  186. $parts = [];
  187. $parts[] = $r['created_mediatype'] ? I18n::t('msg.init_mediatype_new') : I18n::t('msg.init_mediatype_ok');
  188. $parts[] = $r['created_user'] ? I18n::t('msg.init_user_new') : I18n::t('msg.init_user_ok');
  189. $parts[] = $r['created_action'] ? I18n::t('msg.init_action_new') : I18n::t('msg.init_action_ok');
  190. if ($r['key_set']) {
  191. $parts[] = I18n::t('msg.init_key_set');
  192. }
  193. info(I18n::t('msg.init_done', [implode(' · ', $parts)]));
  194. }
  195. }