Skip to content

Commit

Permalink
[feature]Support config email server on web-ui (#954)
Browse files Browse the repository at this point in the history
Co-authored-by: tomsun28 <tomsun28@outlook.com>
  • Loading branch information
zqr10159 and tomsun28 authored May 21, 2023
1 parent b282a2c commit 32e1d7e
Show file tree
Hide file tree
Showing 32 changed files with 1,084 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.dromara.hertzbeat.common.entity.manager;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import java.time.LocalDateTime;

import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;

/**
* 消息通知服务端配置实体
* @author zqr10159
*/
@Entity
@Table(name = "hzb_config")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Message notification server config entity | 消息通知服务端配置实体")
@EntityListeners(AuditingEntityListener.class)
public class GeneralConfig {

@Id
@Schema(title = "Config type: 1-SMS 2-Email, primary key ", description = "配置类型: 1-短信 2-邮件, 主键",
accessMode = READ_WRITE)
@Min(1)
@NotNull
private Byte type;

@Schema(title = "Config content", description = "配置内容,格式为json", accessMode = READ_WRITE)
@Column(length = 4096)
private String content;

@Schema(title = "Whether to enable this policy",
description = "是否启用此配置",
example = "true", accessMode = READ_WRITE)
private boolean enable = true;

@Schema(title = "The creator of this record", description = "此条记录创建者", example = "tom", accessMode = READ_ONLY)
@CreatedBy
private String creator;

@Schema(title = "This record was last modified by",
description = "此条记录最新修改者",
example = "tom", accessMode = READ_ONLY)
@LastModifiedBy
private String modifier;

@Schema(title = "This record creation time (millisecond timestamp)",
description = "记录创建时间", accessMode = READ_ONLY)
@CreatedDate
private LocalDateTime gmtCreate;

@Schema(title = "Record the latest modification time (timestamp in milliseconds)",
description = "记录最新修改时间", accessMode = READ_ONLY)
@LastModifiedDate
private LocalDateTime gmtUpdate;
}
6 changes: 6 additions & 0 deletions manager/data/hzb_config.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE `hzb_config` (
`type` tinyint(5) NOT NULL COMMENT '配置类型:1-短信,2-邮件',
`content` json DEFAULT NULL COMMENT '配置内容',
`enabled` tinyint(1) DEFAULT NULL COMMENT '标志位,使用原生配置为0,使用数据库配置为1',
PRIMARY KEY (`type`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
Expand All @@ -29,7 +30,7 @@
*
*/

@SpringBootApplication
@SpringBootApplication(exclude = MailSenderAutoConfiguration.class)
@EnableJpaAuditing
@EnableScheduling
@EnableJpaRepositories(basePackages = {"org.dromara.hertzbeat"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,28 @@

package org.dromara.hertzbeat.manager.component.alerter.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.common.entity.alerter.Alert;
import org.dromara.hertzbeat.common.entity.manager.GeneralConfig;
import org.dromara.hertzbeat.common.entity.manager.NoticeReceiver;
import org.dromara.hertzbeat.common.util.ResourceBundleUtil;
import org.dromara.hertzbeat.manager.component.alerter.AlertNotifyHandler;
import org.dromara.hertzbeat.manager.config.MailConfigProperties;
import org.dromara.hertzbeat.manager.dao.GeneralConfigDao;
import org.dromara.hertzbeat.manager.pojo.dto.NoticeSender;
import org.dromara.hertzbeat.manager.service.MailService;
import org.dromara.hertzbeat.manager.support.exception.AlertNoticeException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;
import java.util.ResourceBundle;

/**
Expand All @@ -42,19 +48,54 @@
@Component
@RequiredArgsConstructor
@Slf4j
@ConditionalOnProperty("spring.mail.username")
final class EmailAlertNotifyHandlerImpl implements AlertNotifyHandler {

private final JavaMailSender javaMailSender;

private final MailConfigProperties mailConfigProperties;

private final MailService mailService;

@Value("${spring.mail.username}")
private String emailFromUser;

private final GeneralConfigDao generalConfigDao;

private final ObjectMapper objectMapper;

private static final Byte TYPE = 2;

private final ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");

@Override
public void send(NoticeReceiver receiver, Alert alert) throws AlertNoticeException {
try {
//获取sender
JavaMailSenderImpl sender = (JavaMailSenderImpl) javaMailSender;
try {
GeneralConfig emailConfig = generalConfigDao.findByType(TYPE);
if (emailConfig != null && emailConfig.isEnable() && emailConfig.getContent() != null) {
// 若启用数据库配置
String content = emailConfig.getContent();
NoticeSender noticeSenderConfig = objectMapper.readValue(content, NoticeSender.class);
sender.setHost(noticeSenderConfig.getEmailHost());
sender.setPort(noticeSenderConfig.getEmailPort());
sender.setUsername(noticeSenderConfig.getEmailUsername());
sender.setPassword(noticeSenderConfig.getEmailPassword());
Properties props = sender.getJavaMailProperties();
props.put("spring.mail.smtp.ssl.enable", noticeSenderConfig.isEmailSsl());
emailFromUser = noticeSenderConfig.getEmailUsername();
} else {
// 若数据库未配置则启用yml配置
sender.setHost(mailConfigProperties.getHost());
sender.setPort(mailConfigProperties.getPort());
sender.setUsername(mailConfigProperties.getUsername());
sender.setPassword(mailConfigProperties.getPassword());
emailFromUser = mailConfigProperties.getUsername();
}
} catch (Exception e) {
log.error("Type not found {}",e.getMessage());
}
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
messageHelper.setSubject(bundle.getString("alerter.notify.title"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.dromara.hertzbeat.manager.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;

import java.util.Properties;

/**
*
* @author zqr10159
*/

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "spring.mail")
public class MailConfigProperties {
private String host;
private String username;
private String password;
private Integer port;
private boolean ssl;

@Bean
public JavaMailSender javaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host);
mailSender.setPort(port);
mailSender.setUsername(username);
mailSender.setPassword(password);

Properties props = mailSender.getJavaMailProperties();
props.put("spring.mail.smtp.ssl.enable", ssl);
props.put("spring.mail.smtp.socketFactory.port", port);
props.put("spring.mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("spring.mail.debug", "false");
props.put("spring.mail.default-encoding", "UTF-8");

return mailSender;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.dromara.hertzbeat.manager.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hertzbeat.common.entity.dto.Message;
import org.dromara.hertzbeat.manager.pojo.dto.NoticeSender;
import org.dromara.hertzbeat.manager.service.impl.MailGeneralConfigServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


import javax.validation.Valid;

import java.util.List;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

/**
* Alert sender Configuration API
* 告警发送端配置API
*
* @author zqr10159
*
*/
@RestController
@RequestMapping(value = "/api/config", produces = {APPLICATION_JSON_VALUE})
@Tag(name = "Alert sender Configuration API | 告警发送端配置API")
@Slf4j
public class NoticeSenderConfigController {
@Autowired
private MailGeneralConfigServiceImpl mailConfigService;

@PostMapping(path = "/sender")
@Operation(summary = "Save the sender config", description = "保存发送端配置")
public ResponseEntity<Message<String>> saveOrUpdateConfig(
@RequestBody @Valid NoticeSender noticeSender) {
mailConfigService.saveConfig(noticeSender, noticeSender.isEmailEnable());
return ResponseEntity.ok(new Message<>("发送端配置保存成功|The sender configuration is saved successfully"));
}

@GetMapping(path = "/senders")
@Operation(summary = "Get the sender config", description = "获取发送端配置")
public ResponseEntity<Message<List<NoticeSender>>> getConfig(){
List<NoticeSender> senders = mailConfigService.getConfigs();
return ResponseEntity.ok(new Message<>(senders));
}

@DeleteMapping(path = "/sender/{id}")
@Operation(summary = "Delete the sender config", description = "删除发送端配置")
public ResponseEntity<Message<String>> deleteConfig(){
mailConfigService.deleteConfig();
return ResponseEntity.ok(new Message<>("发送端配置删除成功|The sender configuration is deleted"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.dromara.hertzbeat.manager.dao;

import org.dromara.hertzbeat.common.entity.manager.GeneralConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Component;

/**
* 消息通知服务端配置Dao
*
* <p>该接口继承了JpaRepository和JpaSpecificationExecutor两个接口,提供基本的CRUD操作和规范查询能力。</p>
*
* @version 1.0
* @since 2023/5/9 22:39
* @author zqr10159
*/
@Component
public interface GeneralConfigDao extends JpaRepository<GeneralConfig, Long>, JpaSpecificationExecutor<GeneralConfig> {

/**
* 通过类型删除
*
* @param type 类型
* @return 返回受影响的行数
*/
int deleteByType(Byte type);

/**
* 通过类型查询
*
* @param type 类型
* @return 返回查询到的配置信息
*/
GeneralConfig findByType(Byte type);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.dromara.hertzbeat.manager.pojo.dto;

import lombok.Data;

import javax.validation.constraints.*;


/**
* 邮件账号配置dto
* @author zqr
*/
@Data
public class NoticeSender {

@NotNull(message = "类型不能为空|Type cannot be empty")
private Integer type;

@NotBlank(message = "邮件主机不能为空|Mail host cannot be empty")
private String emailHost;

@NotBlank(message = "用户名不能为空|Username cannot be empty")
@Email
private String emailUsername;

@NotBlank(message = "密码不能为空|Password cannot be empty")
private String emailPassword;

@NotNull(message = "邮件端口不能为空|Mail port cannot be null")
@Max(message = "邮件端口不得大于65535|Mail port must be less than or equal to 65535", value = 65535)
@Min(message = "邮件端口不得小于1|Mail port must be greater than or equal to 1", value = 1)
private Integer emailPort;

private boolean emailSsl;

private boolean emailEnable;
}
Loading

0 comments on commit 32e1d7e

Please sign in to comment.