diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/impl/SmsAlertNotifyHandlerImpl.java b/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/impl/SmsAlertNotifyHandlerImpl.java index f0ab01c2d30..c80bbc5d90c 100644 --- a/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/impl/SmsAlertNotifyHandlerImpl.java +++ b/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/impl/SmsAlertNotifyHandlerImpl.java @@ -38,11 +38,11 @@ @Slf4j @ConditionalOnProperty("common.sms.tencent.app-id") final class SmsAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl { - + private final TencentSmsClient tencentSmsClient; - + private final ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter"); - + @Override public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, Alert alert) { // SMS notification @@ -60,7 +60,7 @@ public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, Alert a throw new AlertNoticeException("[Sms Notify Error] " + e.getMessage()); } } - + @Override public byte type() { return 0; diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsAlibabaConfig.java b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsAlibabaConfig.java new file mode 100644 index 00000000000..25feeaa0ebc --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsAlibabaConfig.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.pojo.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * Alibaba Sms Sender configuration dto + */ +@Data +public class SmsAlibabaConfig { + + @NotBlank(message = "SecretId cannot be empty") + private String secretId; + + @NotBlank(message = "SecretKey cannot be empty") + private String secretKey; + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsNoticeSender.java b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsNoticeSender.java new file mode 100644 index 00000000000..b2aecead57c --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsNoticeSender.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.pojo.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Sms Sender configuration dto + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SmsNoticeSender { + + @NotBlank(message = "Type cannot be empty") + private String type; + + private SmsTencentConfig tencent; + + private SmsAlibabaConfig alibaba; + + private boolean enable = true; +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsTencentConfig.java b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsTencentConfig.java new file mode 100644 index 00000000000..f54affd5978 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/SmsTencentConfig.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.pojo.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Tencent Sms Sender configuration dto + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SmsTencentConfig { + + @NotBlank(message = "SecretId cannot be empty") + private String secretId; + + @NotBlank(message = "SecretKey cannot be empty") + private String secretKey; + + @NotBlank(message = "SignName cannot be empty") + private String signName; + + @NotBlank(message = "AppId cannot be null") + private String appId; + + @NotBlank(message = "templateId cannot be null") + private String templateId; + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java new file mode 100644 index 00000000000..b80ef9fa4cd --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.service.impl; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Type; +import org.apache.hertzbeat.manager.dao.GeneralConfigDao; +import org.apache.hertzbeat.manager.pojo.dto.SmsNoticeSender; +import org.springframework.stereotype.Service; + +/** + * SmsGeneralConfigServiceImpl class is the implementation of general sms configuration service, + * which inherits the AbstractGeneralConfigServiceImpl class. + */ + +@Service +public class SmsGeneralConfigServiceImpl extends AbstractGeneralConfigServiceImpl { + + /** + * SmsGeneralConfigServiceImpl's constructor creates an instance of this class + * through the default constructor or deserialization construction (setBeanProps). + * The parameter generalConfigDao is used for dao layer operation data, + * and objectMapper is used for object mapping. + * @param generalConfigDao dao layer operation data, needed to create an instance of this class + * @param objectMapper object mapping , needed to create an instance of this class + */ + public SmsGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) { + super(generalConfigDao, objectMapper); + } + + @Override + public String type() { + return "sms"; + } + + /** + * This method is used to get the TypeReference of NoticeSender type for subsequent processing. + * a TypeReference of NoticeSender type + */ + @Override + protected TypeReference getTypeReference() { + return new TypeReference<>() { + @Override + public Type getType() { + return SmsNoticeSender.class; + } + }; + } +} diff --git a/web-app/src/app/pojo/AlibabaSmsConfig.ts b/web-app/src/app/pojo/AlibabaSmsConfig.ts new file mode 100644 index 00000000000..4f072c57180 --- /dev/null +++ b/web-app/src/app/pojo/AlibabaSmsConfig.ts @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export class AlibabaSmsConfig { + secretId!: string; + secretKey!: string; + signName!: string; + appId!: string; + templateId!: string; +} diff --git a/web-app/src/app/pojo/SmsNoticeSender.ts b/web-app/src/app/pojo/SmsNoticeSender.ts new file mode 100644 index 00000000000..ffb58105322 --- /dev/null +++ b/web-app/src/app/pojo/SmsNoticeSender.ts @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AlibabaSmsConfig } from './AlibabaSmsConfig'; +import { TencentSmsConfig } from './TencentSmsConfig'; + +export class SmsNoticeSender { + id!: number; + type!: string; + tencent!: TencentSmsConfig; + alibaba!: AlibabaSmsConfig; + enable!: boolean; + creator!: string; + modifier!: string; + gmtCreate!: number; + gmtUpdate!: number; +} diff --git a/web-app/src/app/pojo/TencentSmsConfig.ts b/web-app/src/app/pojo/TencentSmsConfig.ts new file mode 100644 index 00000000000..c91b24fe945 --- /dev/null +++ b/web-app/src/app/pojo/TencentSmsConfig.ts @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export class TencentSmsConfig { + secretId!: string; + secretKey!: string; + signName!: string; + appId!: string; + templateId!: string; +} diff --git a/web-app/src/app/routes/setting/settings/message-server/message-server.component.html b/web-app/src/app/routes/setting/settings/message-server/message-server.component.html index dbadf2d1bf8..dc23399183b 100644 --- a/web-app/src/app/routes/setting/settings/message-server/message-server.component.html +++ b/web-app/src/app/routes/setting/settings/message-server/message-server.component.html @@ -39,16 +39,33 @@ - - - - {{ 'common.button.setting' | i18n }} - + + + {{ 'common.button.setting' | i18n }} - - - - + + + {{ 'alert.notice.sender.sms.type' | i18n }}: {{ 'alert.notice.sender.sms.type.' + smsNoticeSender.type | i18n }} +
+ + {{ 'alert.notice.sender.sms.tencent.secretId' | i18n }}: {{ smsNoticeSender.tencent.secretId }} +
+
+ + {{ 'alert.notice.sender.sms.tencent.secretKey' | i18n }}: {{ smsNoticeSender.tencent.secretKey }} +
+
+ + {{ 'alert.notice.sender.sms.tencent.signName' | i18n }}: {{ smsNoticeSender.tencent.signName }} +
+
+ + {{ 'alert.notice.sender.sms.tencent.appId' | i18n }}: {{ smsNoticeSender.tencent.appId }} +
+
+ + {{ 'alert.notice.sender.sms.tencent.templateId' | i18n }}: {{ smsNoticeSender.tencent.templateId }} +
@@ -112,3 +129,75 @@ + + + +
+
+ + {{ 'alert.notice.sender.sms.type' | i18n }} + + + + + + + + + + {{ + 'alert.notice.sender.sms.tencent.secretId' | i18n + }} + + + + + + {{ + 'alert.notice.sender.sms.tencent.secretKey' | i18n + }} + + + + + + {{ + 'alert.notice.sender.sms.tencent.signName' | i18n + }} + + + + + + {{ 'alert.notice.sender.sms.tencent.appId' | i18n }} + + + + + + {{ + 'alert.notice.sender.sms.tencent.templateId' | i18n + }} + + + + + + + + {{ 'alert.notice.sender.enable' | i18n }} + + + + +
+
+
diff --git a/web-app/src/app/routes/setting/settings/message-server/message-server.component.ts b/web-app/src/app/routes/setting/settings/message-server/message-server.component.ts index d3392fa007d..b919d1a2b63 100644 --- a/web-app/src/app/routes/setting/settings/message-server/message-server.component.ts +++ b/web-app/src/app/routes/setting/settings/message-server/message-server.component.ts @@ -24,6 +24,9 @@ import { ALAIN_I18N_TOKEN } from '@delon/theme'; import { NzMessageService } from 'ng-zorro-antd/message'; import { NzNotificationService } from 'ng-zorro-antd/notification'; import { finalize } from 'rxjs/operators'; +import { AlibabaSmsConfig } from 'src/app/pojo/AlibabaSmsConfig'; +import { SmsNoticeSender } from 'src/app/pojo/SmsNoticeSender'; +import { TencentSmsConfig } from 'src/app/pojo/TencentSmsConfig'; import { EmailNoticeSender } from '../../../../pojo/EmailNoticeSender'; import { GeneralConfigService } from '../../../../service/general-config.service'; @@ -45,13 +48,17 @@ export class MessageServerComponent implements OnInit { senderServerLoading: boolean = true; loading: boolean = false; isEmailServerModalVisible: boolean = false; + isSmsServerModalVisible: boolean = false; + smsType: string = 'tencent'; emailSender = new EmailNoticeSender(); + smsNoticeSender = new SmsNoticeSender(); ngOnInit(): void { - this.loadSenderServer(); + this.loadEmailSenderServer(); + this.loadSmsSenderServer(); } - loadSenderServer() { + loadEmailSenderServer() { this.senderServerLoading = true; let senderInit$ = this.noticeSenderSvc.getGeneralConfig('email').subscribe( message => { @@ -116,4 +123,91 @@ export class MessageServerComponent implements OnInit { } ); } + + loadSmsSenderServer() { + this.senderServerLoading = true; + let senderInit$ = this.noticeSenderSvc.getGeneralConfig('sms').subscribe( + message => { + this.senderServerLoading = false; + if (message.code === 0) { + if (message.data) { + this.smsNoticeSender = message.data; + this.smsType = message.data.type; + } else { + this.smsNoticeSender = new SmsNoticeSender(); + this.smsNoticeSender.type = 'tencent'; + this.smsNoticeSender.tencent = new TencentSmsConfig(); + } + } else { + console.warn(message.msg); + } + senderInit$.unsubscribe(); + }, + error => { + console.error(error.msg); + this.senderServerLoading = false; + senderInit$.unsubscribe(); + } + ); + } + + onConfigSmsServer() { + this.isSmsServerModalVisible = true; + } + + onCancelSmsServer() { + this.isSmsServerModalVisible = false; + } + + onSmsTypeChange(value: string) { + if (value === 'tencent') { + // tencent sms sender + this.smsType = 'tencent'; + this.smsNoticeSender.type = 'tencent'; + } else if (value === 'alibaba') { + // alibaba sms sender + this.smsType = 'alibaba'; + this.smsNoticeSender.type = 'alibaba'; + } + } + + onSaveSmsServer() { + if (this.senderForm?.invalid) { + Object.values(this.senderForm.controls).forEach(control => { + if (control.invalid) { + control.markAsDirty(); + control.updateValueAndValidity({ onlySelf: true }); + } + }); + return; + } + if (this.smsNoticeSender.type === 'tencent') { + this.smsNoticeSender.alibaba = new AlibabaSmsConfig(); + } + if (this.smsNoticeSender.type === 'alibaba') { + this.smsNoticeSender.tencent = new TencentSmsConfig(); + } + const modalOk$ = this.noticeSenderSvc + .saveGeneralConfig(this.smsNoticeSender, 'sms') + .pipe( + finalize(() => { + modalOk$.unsubscribe(); + this.senderServerLoading = false; + }) + ) + .subscribe( + message => { + if (message.code === 0) { + this.isSmsServerModalVisible = false; + this.notifySvc.success(this.i18nSvc.fanyi('common.notify.apply-success'), ''); + } else { + this.notifySvc.error(this.i18nSvc.fanyi('common.notify.apply-fail'), message.msg); + } + }, + error => { + this.isSmsServerModalVisible = false; + this.notifySvc.error(this.i18nSvc.fanyi('common.notify.apply-fail'), error.msg); + } + ); + } } diff --git a/web-app/src/assets/i18n/en-US.json b/web-app/src/assets/i18n/en-US.json index c798b6b6d89..4a9cf506e35 100644 --- a/web-app/src/assets/i18n/en-US.json +++ b/web-app/src/assets/i18n/en-US.json @@ -336,6 +336,14 @@ "alert.notice.sender.mail.ssl": "Enable SSL", "alert.notice.sender.mail.starttls": "Enable STARTTLS", "alert.notice.sender.mail.enable": "Enable Email Configuration", + "alert.notice.sender.sms.type": "Sms Type", + "alert.notice.sender.sms.type.tencent": "Tencent Sms", + "alert.notice.sender.sms.type.alibaba": "Alibaba Sms", + "alert.notice.sender.sms.tencent.secretId": "Tencent Sms SecretId", + "alert.notice.sender.sms.tencent.secretKey": "Tencent Sms SecretKey", + "alert.notice.sender.sms.tencent.signName": "Tencent Sms SignName", + "alert.notice.sender.sms.tencent.appId": "Tencent Sms AppId", + "alert.notice.sender.sms.tencent.templateId": "Tencent Sms TemplateId", "alert.export.switch-type": "Please select the export file format!", "alert.export.use-type": "Export rules in {{type}} file format", "dashboard.alerts.title": "Recently Alarms List", diff --git a/web-app/src/assets/i18n/zh-CN.json b/web-app/src/assets/i18n/zh-CN.json index d8ea6a49071..8218fe13370 100644 --- a/web-app/src/assets/i18n/zh-CN.json +++ b/web-app/src/assets/i18n/zh-CN.json @@ -337,6 +337,14 @@ "alert.notice.sender.mail.ssl": "是否启用SSL", "alert.notice.sender.mail.starttls": "是否启用STARTTLS", "alert.notice.sender.mail.enable": "是否启用邮箱配置", + "alert.notice.sender.sms.type": "短信类型", + "alert.notice.sender.sms.type.tencent": "腾讯短信", + "alert.notice.sender.sms.type.alibaba": "阿里短信", + "alert.notice.sender.sms.tencent.secretId": "腾讯短信SecretId", + "alert.notice.sender.sms.tencent.secretKey": "腾讯短信SecretKey", + "alert.notice.sender.sms.tencent.signName": "腾讯短信SignName", + "alert.notice.sender.sms.tencent.appId": "腾讯短信AppId", + "alert.notice.sender.sms.tencent.templateId": "腾讯短信TemplateId", "alert.export.switch-type": "请选择导出文件格式!", "alert.export.use-type": "以 {{type}} 文件格式导出阈值规则", "dashboard.alerts.title": "最近告警列表", @@ -559,8 +567,8 @@ "settings.server": "消息服务配置", "settings.server.email": "邮件服务器", "settings.server.email.setting": "配置邮件服务器", - "settings.server.sms": "短信服务器", - "settings.server.sms.setting": "配置短信服务器", + "settings.server.sms": "短信配置", + "settings.server.sms.setting": "配置短信参数", "settings.system-config": "系统配置", "settings.system-config.locale": "系统语言", "settings.system-config.locale.zh_CN": "简体中文(zh_CN)", diff --git a/web-app/src/assets/i18n/zh-TW.json b/web-app/src/assets/i18n/zh-TW.json index 97d1f040d43..671de56b5fb 100644 --- a/web-app/src/assets/i18n/zh-TW.json +++ b/web-app/src/assets/i18n/zh-TW.json @@ -336,6 +336,14 @@ "alert.notice.sender.mail.ssl": "是否啟用SSL", "alert.notice.sender.mail.starttls": "是否啟用STARTTLS", "alert.notice.sender.mail.enable": "啟用郵件設定", + "alert.notice.sender.sms.type": "騰訊類型", + "alert.notice.sender.sms.type.tencent": "騰訊短訊", + "alert.notice.sender.sms.type.alibaba": "阿裏短訊", + "alert.notice.sender.sms.tencent.secretId": "騰訊短訊SecretId", + "alert.notice.sender.sms.tencent.secretKey": "騰訊短訊SecretKey", + "alert.notice.sender.sms.tencent.signName": "騰訊短訊SignName", + "alert.notice.sender.sms.tencent.appId": "騰訊短訊AppId", + "alert.notice.sender.sms.tencent.templateId": "騰訊短訊TemplateId", "alert.export.switch-type": "請選擇導出文件格式!", "alert.export.use-type": "以 {{type}} 文件格式導出阈值規則", "dashboard.alerts.title": "最近告警列表", @@ -556,8 +564,8 @@ "settings.server": "消息服務配置", "settings.server.email": "郵件服務器", "settings.server.email.setting": "配置郵件服務器", - "settings.server.sms": "短信服務器", - "settings.server.sms.setting": "配置短信服務器", + "settings.server.sms": "短信配置", + "settings.server.sms.setting": "配置短信參數", "settings.system-config": "系統配置", "settings.system-config.locale": "系統語言", "settings.system-config.locale.zh_CN": "簡體中文(zh_CN)",