Compare commits

..

1 Commits

Author SHA1 Message Date
huacheng
5abbea10ba feat: [manager]feature:App/Account Controller compatible with Chinese and English #wqh 2022-04-14 21:46:58 +08:00
30 changed files with 270 additions and 366 deletions

View File

@@ -62,8 +62,6 @@
- 如果您不想部署而是直接使用我们提供SAAS监控云-[TanCloud探云](https://console.tancloud.cn),即刻 **[登录注册](https://console.tancloud.cn)** 免费使用。 - 如果您不想部署而是直接使用我们提供SAAS监控云-[TanCloud探云](https://console.tancloud.cn),即刻 **[登录注册](https://console.tancloud.cn)** 免费使用。
- 如果您是想将HertzBeat部署到内网环境搭建监控系统请参考下面的 [部署文档](https://hertzbeat.com/docs/start/quickstart) 进行操作。 - 如果您是想将HertzBeat部署到内网环境搭建监控系统请参考下面的 [部署文档](https://hertzbeat.com/docs/start/quickstart) 进行操作。
安装部署视频教程: [HertzBeat安装部署-BiliBili](https://www.bilibili.com/video/BV1GY41177YL)
### 🐵 依赖服务部署 ### 🐵 依赖服务部署
> HertzBeat最少依赖于 关系型数据库[MYSQL5+](https://www.mysql.com/) 和 时序性数据库[TDengine2+](https://www.taosdata.com/getting-started) > HertzBeat最少依赖于 关系型数据库[MYSQL5+](https://www.mysql.com/) 和 时序性数据库[TDengine2+](https://www.taosdata.com/getting-started)

View File

@@ -1,12 +1,10 @@
package com.usthe.alert; package com.usthe.alert;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* 数据仓储配置属性 * 数据仓储配置属性
*
* @author tom * @author tom
* @date 2021/11/24 10:38 * @date 2021/11/24 10:38
*/ */
@@ -14,22 +12,11 @@ import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "alerter") @ConfigurationProperties(prefix = "alerter")
public class AlerterProperties { public class AlerterProperties {
private String consoleUrl = "https://console.tancloud.cn";
public String getConsoleUrl() {
return consoleUrl;
}
public void setConsoleUrl(String url) {
this.consoleUrl = url;
}
/** /**
* 数据入口配置属性 * 数据入口配置属性
*/ */
private EntranceProperties entrance; private EntranceProperties entrance;
public EntranceProperties getEntrance() { public EntranceProperties getEntrance() {
return entrance; return entrance;
} }
@@ -38,7 +25,6 @@ public class AlerterProperties {
this.entrance = entrance; this.entrance = entrance;
} }
/** /**
* 数据入口配置属性 * 数据入口配置属性
* 入口可以是从kafka rabbitmq rocketmq等消息中间件获取数据 * 入口可以是从kafka rabbitmq rocketmq等消息中间件获取数据
@@ -112,5 +98,4 @@ public class AlerterProperties {
} }
} }

View File

@@ -22,7 +22,9 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
/** /**
* todo 字段默认值 * todo 字段默认值
* Monitoring parameter definitions
* 监控参数定义 * 监控参数定义
*
* @author tomsun28 * @author tomsun28
* @date 2021/11/13 21:49 * @date 2021/11/13 21:49
*/ */
@@ -32,57 +34,68 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@ApiModel(description = "参数结构定义实体") @ApiModel(description = "en: Parameter structure definition entity,zh: 参数结构定义实体")
public class ParamDefine { public class ParamDefine {
/**
* Parameter Structure ID
*/
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@ApiModelProperty(value = "参数结构ID", example = "87584674384", accessMode = READ_ONLY, position = 0) @ApiModelProperty(value = "参数结构ID", example = "87584674384", accessMode = READ_ONLY, position = 0)
private Long id; private Long id;
/** /**
* Monitoring application type name
* 监控应用类型名称 * 监控应用类型名称
*/ */
@ApiModelProperty(value = "监控类型", example = "TanCloud", accessMode = READ_WRITE, position = 1) @ApiModelProperty(value = "监控类型", example = "TanCloud", accessMode = READ_WRITE, position = 1)
private String app; private String app;
/** /**
* Parameter field external display name
* 参数字段对外显示名称 * 参数字段对外显示名称
*/ */
@ApiModelProperty(value = "参数字段显示名称", example = "端口", accessMode = READ_WRITE, position = 2) @ApiModelProperty(value = "参数字段显示名称", example = "端口", accessMode = READ_WRITE, position = 2)
private String name; private String name;
/** /**
* Parameter Field Identifier
* 参数字段标识符 * 参数字段标识符
*/ */
@ApiModelProperty(value = "参数字段标识符", example = "port", accessMode = READ_WRITE, position = 3) @ApiModelProperty(value = "参数字段标识符", example = "port", accessMode = READ_WRITE, position = 3)
private String field; private String field;
/** /**
* Field type, style (mostly map the input tag type attribute)
* 字段类型,样式(大部分映射input标签type属性) * 字段类型,样式(大部分映射input标签type属性)
*/ */
@ApiModelProperty(value = "字段类型,样式(大部分映射input标签type属性)", example = "number", accessMode = READ_WRITE, position = 4) @ApiModelProperty(value = "字段类型,样式(大部分映射input标签type属性)", example = "number", accessMode = READ_WRITE, position = 4)
private String type; private String type;
/** /**
* Is it mandatory true-required false-optional
* 是否是必输项 true-必填 false-可选 * 是否是必输项 true-必填 false-可选
*/ */
@ApiModelProperty(value = "是否是必输项 true-必填 false-可选", example = "true", accessMode = READ_WRITE, position = 5) @ApiModelProperty(value = "是否是必输项 true-必填 false-可选", example = "true", accessMode = READ_WRITE, position = 5)
private boolean required = false; private boolean required = false;
/** /**
* Parameter Default Value
* 参数默认值 * 参数默认值
*/ */
@ApiModelProperty(value = "参数默认值", example = "12", accessMode = READ_WRITE, position = 6) @ApiModelProperty(value = "参数默认值", example = "12", accessMode = READ_WRITE, position = 6)
private String defaultValue; private String defaultValue;
/** /**
* Parameter input box prompt information
* 参数输入框提示信息 * 参数输入框提示信息
*/ */
@ApiModelProperty(value = "参数输入框提示信息", example = "请输入密码", accessMode = READ_WRITE, position = 7) @ApiModelProperty(value = "参数输入框提示信息", example = "请输入密码", accessMode = READ_WRITE, position = 7)
private String placeholder; private String placeholder;
/** /**
* When type is number, use range to represent the range eg: 0-233
* 当type为number时,用range表示范围 eg: 0-233 * 当type为number时,用range表示范围 eg: 0-233
*/ */
@ApiModelProperty(value = "当type为number时,用range区间表示范围", example = "[0,233]", accessMode = READ_WRITE, position = 6) @ApiModelProperty(value = "当type为number时,用range区间表示范围", example = "[0,233]", accessMode = READ_WRITE, position = 6)
@@ -90,6 +103,7 @@ public class ParamDefine {
private String range; private String range;
/** /**
* When type is text, use limit to indicate the limit size of the string. The maximum is 255
* 当type为text时,用limit表示字符串限制大小.最大255 * 当type为text时,用limit表示字符串限制大小.最大255
*/ */
@ApiModelProperty(value = "当type为text时,用limit表示字符串限制大小.最大255", example = "30", accessMode = READ_WRITE, position = 7) @ApiModelProperty(value = "当type为text时,用limit表示字符串限制大小.最大255", example = "30", accessMode = READ_WRITE, position = 7)
@@ -97,6 +111,7 @@ public class ParamDefine {
private Short limit; private Short limit;
/** /**
* When the type is radio radio box, checkbox checkbox, options represents a list of optional values
* 当type为radio单选框,checkbox复选框时,options表示可选项值列表 * 当type为radio单选框,checkbox复选框时,options表示可选项值列表
* eg: { * eg: {
* "key1":"value1", * "key1":"value1",
@@ -111,36 +126,42 @@ public class ParamDefine {
private List<Option> options; private List<Option> options;
/** /**
* Valid when type is key-value, indicating the alias description of the key
* 当type为key-value时有效,表示key的别名描述 * 当type为key-value时有效,表示key的别名描述
*/ */
@ApiModelProperty(value = "当type为key-value时有效,表示key的别名描述", example = "Name", accessMode = READ_WRITE, position = 9) @ApiModelProperty(value = "当type为key-value时有效,表示key的别名描述", example = "Name", accessMode = READ_WRITE, position = 9)
private String keyAlias; private String keyAlias;
/** /**
* Valid when type is key-value, indicating the alias description of value type
* 当type为key-value时有效,表示value的别名描述 * 当type为key-value时有效,表示value的别名描述
*/ */
@ApiModelProperty(value = "当type为key-value时有效,表示value的别名描述", example = "Value", accessMode = READ_WRITE, position = 10) @ApiModelProperty(value = "当type为key-value时有效,表示value的别名描述", example = "Value", accessMode = READ_WRITE, position = 10)
private String valueAlias; private String valueAlias;
/** /**
* Is it an advanced hidden parameter true-yes false-no
* 是否是高级隐藏参数 true-是 false-否 * 是否是高级隐藏参数 true-是 false-否
*/ */
@ApiModelProperty(value = "是否是高级隐藏参数 true-是 false-否", example = "true", accessMode = READ_WRITE, position = 11) @ApiModelProperty(value = "是否是高级隐藏参数 true-是 false-否", example = "true", accessMode = READ_WRITE, position = 11)
private boolean hide = false; private boolean hide = false;
/** /**
* The creator of this record
* 此条记录创建者 * 此条记录创建者
*/ */
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11) @ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11)
private String creator; private String creator;
/** /**
* This record was last modified by
* 此条记录最新修改者 * 此条记录最新修改者
*/ */
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12) @ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12)
private String modifier; private String modifier;
/** /**
* record creation time
* 记录创建时间 * 记录创建时间
*/ */
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13) @ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13)
@@ -148,6 +169,7 @@ public class ParamDefine {
private LocalDateTime gmtCreate; private LocalDateTime gmtCreate;
/** /**
* Record the latest modification time
* 记录最新修改时间 * 记录最新修改时间
*/ */
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14) @ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14)
@@ -159,10 +181,12 @@ public class ParamDefine {
@NoArgsConstructor @NoArgsConstructor
public static final class Option { public static final class Option {
/** /**
* value display label
* 值显示标签 * 值显示标签
*/ */
private String label; private String label;
/** /**
* optional value
* 可选值 * 可选值
*/ */
private String value; private String value;

View File

@@ -1,18 +0,0 @@
---
id: alert_console
title: 告警模板中自定义的控制台地址
sidebar_label: 告警模板登录台地址
---
> 阈值触发后发送告警信息,通过钉钉/企业微信/飞书机器人通知或者使用邮箱通知的时候,告警内容中有登录控制台的详情链接
### 自定义设置
在我们的启动配置文件application.yml中找到下面的配置
```yml
alerter:
console-url: #这里就是我们的自定义控制台地址
```
默认值是赫兹跳动的官方控制台地址

View File

@@ -6,8 +6,6 @@ sidebar_label: Docker方式部署
> 推荐使用docker部署HertzBeat > 推荐使用docker部署HertzBeat
安装部署视频教程: [HertzBeat安装部署-BiliBili](https://www.bilibili.com/video/BV1GY41177YL)
1. 下载安装Docker环境 1. 下载安装Docker环境
Docker 工具自身的下载请参考 [Docker官网文档](https://docs.docker.com/get-docker/)。 Docker 工具自身的下载请参考 [Docker官网文档](https://docs.docker.com/get-docker/)。
安装完毕后终端查看Docker版本是否正常输出。 安装完毕后终端查看Docker版本是否正常输出。
@@ -50,39 +48,13 @@ sidebar_label: Docker方式部署
```yaml ```yaml
resourceRole: resourceRole:
- /account/auth/refresh===post===[admin,user,guest] - /account/auth/refresh===post===[role1,role2,role3,role4]
- /apps/**===get===[admin,user,guest]
- /monitor/**===get===[admin,user,guest]
- /monitor/**===post===[admin,user]
- /monitor/**===put===[admin,user]
- /monitor/**===delete==[admin]
- /monitors/**===get===[admin,user,guest]
- /monitors/**===post===[admin,user]
- /monitors/**===put===[admin,user]
- /monitors/**===delete===[admin]
- /alert/**===get===[admin,user,guest]
- /alert/**===post===[admin,user]
- /alert/**===put===[admin,user]
- /alert/**===delete===[admin]
- /alerts/**===get===[admin,user,guest]
- /alerts/**===post===[admin,user]
- /alerts/**===put===[admin,user]
- /alerts/**===delete===[admin]
- /notice/**===get===[admin,user,guest]
- /notice/**===post===[admin,user]
- /notice/**===put===[admin,user]
- /notice/**===delete===[admin]
- /summary/**===get===[admin,user,guest]
- /summary/**===post===[admin,user]
- /summary/**===put===[admin,user]
- /summary/**===delete===[admin]
excludedResource: excludedResource:
- /account/auth/**===* - /account/auth/**===*
- /===get - /===get
- /i18n/**===get - /i18n/**===get
- /apps/hierarchy===get - /apps/hierarchy===get
# web ui 静态资源
- /console/**===get - /console/**===get
- /**/*.html===get - /**/*.html===get
- /**/*.js===get - /**/*.js===get
@@ -92,29 +64,29 @@ excludedResource:
- /**/*.png===get - /**/*.png===get
- /**/*.gif===get - /**/*.gif===get
- /**/*.png===* - /**/*.png===*
# swagger ui 资源
- /swagger-resources/**===get - /swagger-resources/**===get
- /v2/api-docs===get - /v2/api-docs===get
- /v3/api-docs===get - /v3/api-docs===get
# 用户账户信息
# 下面有 admin tom lili 三个账户
# eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account: account:
- appId: admin - appId: admin
credential: admin credential: admin
role: [admin,user] role: [role1,role2]
- appId: tom - appId: tom
credential: tom@123 credential: tom@123
role: [user] role: [role1,role2,role3]
- appId: guest
credential: guest
role: [guest]
- appId: lili - appId: lili
# 注意 Digest认证不支持加盐加密的密码账户 # 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算 # 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili # 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289 credential: 1A676730B0C7F54654B0E09184448289
salt: 123 salt: 123
role: [guest] role: [role1,role2]
``` ```
修改sureness.yml的如下**部分参数****[注意⚠sureness配置的其它默认参数需保留]** 修改sureness.yml的如下**部分参数****[注意⚠sureness配置的其它默认参数需保留]**
@@ -123,27 +95,23 @@ account:
# 用户账户信息 # 用户账户信息
# 下面有 admin tom lili 三个账户 # 下面有 admin tom lili 三个账户
# eg: admin 拥有[admin,user]角色,密码为admin # eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[user],密码为tom@123 # eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[guest],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289 # eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account: account:
- appId: admin - appId: admin
credential: admin credential: admin
role: [admin,user] role: [role1,role2]
- appId: tom - appId: tom
credential: tom@123 credential: tom@123
role: [user] role: [role1,role2,role3]
- appId: guest
credential: guest
role: [guest]
- appId: lili - appId: lili
# 注意 Digest认证不支持加盐加密的密码账户 # 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算 # 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili # 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289 credential: 1A676730B0C7F54654B0E09184448289
salt: 123 salt: 123
role: [guest] role: [role1,role2]
``` ```
6. 启动HertzBeat Docker容器 6. 启动HertzBeat Docker容器

View File

@@ -5,8 +5,6 @@ sidebar_label: MYSQL安装初始化
--- ---
MYSQL是一款值得信赖的关系型数据库HertzBeat使用其存储监控信息告警信息配置信息等结构化关系数据。 MYSQL是一款值得信赖的关系型数据库HertzBeat使用其存储监控信息告警信息配置信息等结构化关系数据。
安装部署视频教程: [HertzBeat安装部署-BiliBili](https://www.bilibili.com/video/BV1GY41177YL)
> 如果您已有MYSQL环境可直接跳到SQL脚本执行那一步。 > 如果您已有MYSQL环境可直接跳到SQL脚本执行那一步。
### 通过Docker方式安装MYSQL ### 通过Docker方式安装MYSQL

View File

@@ -3,9 +3,7 @@ id: package-deploy
title: 通过安装包安装HertzBeat title: 通过安装包安装HertzBeat
sidebar_label: 安装包方式部署 sidebar_label: 安装包方式部署
--- ---
> HertzBeat支持在Linux Windows Mac系统安装运行CPU支持X86/ARM64。由于安装包自身不包含JAVA运行环境需您提前准备JAVA运行环境。 > HertzBeat支持在Linux Windows Mac系统安装运行CPU支持X64/ARM64。由于安装包自身不包含JAVA运行环境需您提前准备JAVA运行环境。
安装部署视频教程: [HertzBeat安装部署-BiliBili](https://www.bilibili.com/video/BV1GY41177YL)
1. 安装JAVA运行环境-可参考[官方网站](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 1. 安装JAVA运行环境-可参考[官方网站](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
要求JDK8+(已验证JDK8) 要求JDK8+(已验证JDK8)
@@ -51,30 +49,25 @@ sidebar_label: 安装包方式部署
修改sureness.yml的如下**部分参数****[注意⚠sureness配置的其它默认参数需保留]** 修改sureness.yml的如下**部分参数****[注意⚠sureness配置的其它默认参数需保留]**
```yaml ```yaml
# 用户账户信息 # 用户账户信息
# 下面有 admin tom lili 三个账户 # 下面有 admin tom lili 三个账户
# eg: admin 拥有[admin,user]角色,密码为admin # eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[user],密码为tom@123 # eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[guest],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289 # eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account: account:
- appId: admin - appId: admin
credential: admin credential: admin
role: [admin,user] role: [role1,role2]
- appId: tom - appId: tom
credential: tom@123 credential: tom@123
role: [user] role: [role1,role2,role3]
- appId: guest
credential: guest
role: [guest]
- appId: lili - appId: lili
# 注意 Digest认证不支持加盐加密的密码账户 # 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算 # 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili # 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289 credential: 1A676730B0C7F54654B0E09184448289
salt: 123 salt: 123
role: [guest] role: [role1,role2]
``` ```
5. 部署启动 5. 部署启动

View File

@@ -9,8 +9,6 @@ sidebar_label: 快速开始
- 如果您不想部署而是直接使用我们提供SAAS监控云-[TanCloud探云](https://console.tancloud.cn),即刻[登录注册](https://console.tancloud.cn)免费使用。 - 如果您不想部署而是直接使用我们提供SAAS监控云-[TanCloud探云](https://console.tancloud.cn),即刻[登录注册](https://console.tancloud.cn)免费使用。
- 如果您是想将HertzBeat部署到内网环境搭建监控系统请参考下面的部署文档进行操作。 - 如果您是想将HertzBeat部署到内网环境搭建监控系统请参考下面的部署文档进行操作。
安装部署视频教程: [HertzBeat安装部署-BiliBili](https://www.bilibili.com/video/BV1GY41177YL)
### 🐵 依赖服务部署 ### 🐵 依赖服务部署
> HertzBeat最少依赖于 关系型数据库[MYSQL5+](https://www.mysql.com/) 和 时序性数据库[TDengine2+](https://www.taosdata.com/getting-started) > HertzBeat最少依赖于 关系型数据库[MYSQL5+](https://www.mysql.com/) 和 时序性数据库[TDengine2+](https://www.taosdata.com/getting-started)

View File

@@ -5,11 +5,8 @@ sidebar_label: TDengine安装初始化
--- ---
TDengine是一款国产的开源物联网时序型数据库我们使用其替换了InfluxDb来存储采集到的监控指标数据。 TDengine是一款国产的开源物联网时序型数据库我们使用其替换了InfluxDb来存储采集到的监控指标数据。
安装部署视频教程: [HertzBeat安装部署-BiliBili](https://www.bilibili.com/video/BV1GY41177YL)
> 如果您已有TDengine环境可直接跳到创建数据库实例那一步。 > 如果您已有TDengine环境可直接跳到创建数据库实例那一步。
### 通过Docker方式安装TDengine ### 通过Docker方式安装TDengine
> 可参考官方网站[安装教程](https://www.taosdata.com/docs/cn/v2.0/getting-started/docker) > 可参考官方网站[安装教程](https://www.taosdata.com/docs/cn/v2.0/getting-started/docker)
1. 下载安装Docker环境 1. 下载安装Docker环境

View File

@@ -1,14 +0,0 @@
{
"title": {
"message": "Blog",
"description": "The title for the blog used in SEO"
},
"description": {
"message": "Blog",
"description": "The description for the blog used in SEO"
},
"sidebar.title": {
"message": "Recent posts",
"description": "The label for the left sidebar"
}
}

View File

@@ -1,7 +1,6 @@
package com.usthe.manager.component.alerter; package com.usthe.manager.component.alerter;
import com.usthe.alert.AlerterDataQueue; import com.usthe.alert.AlerterDataQueue;
import com.usthe.alert.AlerterProperties;
import com.usthe.alert.AlerterWorkerPool; import com.usthe.alert.AlerterWorkerPool;
import com.usthe.common.util.CommonUtil; import com.usthe.common.util.CommonUtil;
import com.usthe.common.entity.alerter.Alert; import com.usthe.common.entity.alerter.Alert;
@@ -25,7 +24,6 @@ import org.springframework.stereotype.Component;
import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@@ -50,8 +48,6 @@ public class DispatchAlarm {
private JavaMailSender javaMailSender; private JavaMailSender javaMailSender;
private RestTemplate restTemplate; private RestTemplate restTemplate;
private MailService mailService; private MailService mailService;
@Resource
private AlerterProperties alerterProperties;
@Value("${spring.mail.username}") @Value("${spring.mail.username}")
private String emailFromUser; private String emailFromUser;
@@ -181,13 +177,13 @@ public class DispatchAlarm {
"\n所属监控ID :" + alert.getMonitorId() + "\n所属监控ID :" + alert.getMonitorId() +
"\n所属监控名称 :" + alert.getMonitorName() + "\n所属监控名称 :" + alert.getMonitorName() +
"\n告警级别 :" + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n告警级别 :" + CommonUtil.transferAlertPriority(alert.getPriority()) +
"\n内容详情 : " + alert.getContent() + "\n"; "\n内容详情 : " + alert.getContent();
flyBookContent.setText(text); flyBookContent.setText(text);
contents1.add(flyBookContent); contents1.add(flyBookContent);
FlyBookWebHookDto.FlyBookContent bookContent = new FlyBookWebHookDto.FlyBookContent(); FlyBookWebHookDto.FlyBookContent bookContent = new FlyBookWebHookDto.FlyBookContent();
bookContent.setTag("a"); bookContent.setTag("a");
bookContent.setText("登入控制台"); bookContent.setText("登入控制台");
bookContent.setHref(alerterProperties.getConsoleUrl()); bookContent.setHref("https://www.tancloud.cn");
contents1.add(bookContent); contents1.add(bookContent);
contents.add(contents1); contents.add(contents1);
zhCn.setTitle("[TanCloud探云告警通知]"); zhCn.setTitle("[TanCloud探云告警通知]");
@@ -218,16 +214,14 @@ public class DispatchAlarm {
private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) { private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) {
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto(); DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
DingTalkWebHookDto.MarkdownDTO markdownDTO = new DingTalkWebHookDto.MarkdownDTO(); DingTalkWebHookDto.MarkdownDTO markdownDTO = new DingTalkWebHookDto.MarkdownDTO();
StringBuilder content = new StringBuilder(); String content = "#### [TanCloud探云告警通知]\n##### **告警目标对象** : " +
content.append("#### [TanCloud探云告警通知]\n##### **告警目标对象** : " +
alert.getTarget() + "\n " + alert.getTarget() + "\n " +
"##### **所属监控ID** : " + alert.getMonitorId() + "\n " + "##### **所属监控ID** : " + alert.getMonitorId() + "\n " +
"##### **所属监控名称** : " + alert.getMonitorName() + "\n " + "##### **所属监控名称** : " + alert.getMonitorName() + "\n " +
"##### **告警级别** : " + "##### **告警级别** : " +
CommonUtil.transferAlertPriority(alert.getPriority()) + "\n " + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n " +
"##### **内容详情** : " + alert.getContent()); "##### **内容详情** : " + alert.getContent();
content.append("[点击跳转查看详情](" + alerterProperties.getConsoleUrl() + ")"); markdownDTO.setText(content);
markdownDTO.setText(content.toString());
markdownDTO.setTitle("TanCloud探云告警通知"); markdownDTO.setTitle("TanCloud探云告警通知");
dingTalkWebHookDto.setMarkdown(markdownDTO); dingTalkWebHookDto.setMarkdown(markdownDTO);
String webHookUrl = DingTalkWebHookDto.WEBHOOK_URL + receiver.getAccessToken(); String webHookUrl = DingTalkWebHookDto.WEBHOOK_URL + receiver.getAccessToken();
@@ -267,10 +261,8 @@ public class DispatchAlarm {
content.append("告警级别 : <font color=\"comment\">") content.append("告警级别 : <font color=\"comment\">")
.append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n"); .append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n");
} }
content.append("内容详情 : ").append(alert.getContent() + "\n"); content.append("内容详情 : ").append(alert.getContent());
content.append("[点击跳转查看详情](" + alerterProperties.getConsoleUrl() + ")");
markdownDTO.setContent(content.toString()); markdownDTO.setContent(content.toString());
//TODO 增加控制台地址登录可控制
weWorkWebHookDTO.setMarkdown(markdownDTO); weWorkWebHookDTO.setMarkdown(markdownDTO);
String webHookUrl = WeWorkWebHookDto.WEBHOOK_URL + receiver.getWechatId(); String webHookUrl = WeWorkWebHookDto.WEBHOOK_URL + receiver.getWechatId();
try { try {

View File

@@ -29,17 +29,20 @@ import static com.usthe.common.util.CommonConstants.MONITOR_LOGIN_FAILED_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/** /**
* Authentication registration TOKEN management API
* 认证注册TOKEN管理API * 认证注册TOKEN管理API
*
* @author tomsun28 * @author tomsun28
* @date 13:11 2019-05-26 * @date 13:11 2019-05-26
*/ */
@Api(tags = "认证注册TOKEN管理API") @Api(tags = "en: Authentication registration TOKEN management API,zh: 认证注册TOKEN管理API")
@RestController() @RestController()
@RequestMapping(value = "/account/auth", produces = {APPLICATION_JSON_VALUE}) @RequestMapping(value = "/account/auth", produces = {APPLICATION_JSON_VALUE})
@Slf4j @Slf4j
public class AccountController { public class AccountController {
/** /**
* Token validity time in seconds
* TOKEN有效期时间 单位秒 * TOKEN有效期时间 单位秒
*/ */
private static final long PERIOD_TIME = 3600L; private static final long PERIOD_TIME = 3600L;
@@ -50,7 +53,7 @@ public class AccountController {
private SurenessAccountProvider accountProvider = new DocumentAccountProvider(); private SurenessAccountProvider accountProvider = new DocumentAccountProvider();
@PostMapping("/form") @PostMapping("/form")
@ApiOperation(value = "账户登录", notes = "账户密码登录获取关联用户信息") @ApiOperation(value = "Account password login to obtain associated user information", notes = "账户密码登录获取关联用户信息")
public ResponseEntity<Message<Map<String, String>>> authGetToken(@RequestBody LoginDto loginDto) { public ResponseEntity<Message<Map<String, String>>> authGetToken(@RequestBody LoginDto loginDto) {
SurenessAccount account = accountProvider.loadAccount(loginDto.getIdentifier()); SurenessAccount account = accountProvider.loadAccount(loginDto.getIdentifier());
@@ -76,7 +79,7 @@ public class AccountController {
} }
// Get the roles the user has - rbac // Get the roles the user has - rbac
List<String> roles = account.getOwnRoles(); List<String> roles = account.getOwnRoles();
// 签发TOKEN // Issue TOKEN 签发TOKEN
String issueToken = JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME, roles); String issueToken = JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME, roles);
Map<String, Object> customClaimMap = new HashMap<>(1); Map<String, Object> customClaimMap = new HashMap<>(1);
customClaimMap.put("refresh", true); customClaimMap.put("refresh", true);
@@ -88,9 +91,9 @@ public class AccountController {
} }
@GetMapping("/refresh/{refreshToken}") @GetMapping("/refresh/{refreshToken}")
@ApiOperation(value = "TOKEN刷新", notes = "使用刷新TOKEN重新获取TOKEN") @ApiOperation(value = "Use refresh TOKEN to re-acquire TOKEN", notes = "使用刷新TOKEN重新获取TOKEN")
public ResponseEntity<Message<Map<String, String>>> refreshToken( public ResponseEntity<Message<Map<String, String>>> refreshToken(
@ApiParam(value = "刷新TOKEN", example = "xxx") @ApiParam(value = "en: Refresh TOKEN,zh: 刷新TOKEN", example = "xxx")
@PathVariable("refreshToken") @NotNull final String refreshToken) { @PathVariable("refreshToken") @NotNull final String refreshToken) {
String userId; String userId;
boolean isRefresh; boolean isRefresh;
@@ -116,7 +119,7 @@ public class AccountController {
return ResponseEntity.ok(message); return ResponseEntity.ok(message);
} }
List<String> roles = account.getOwnRoles(); List<String> roles = account.getOwnRoles();
// 签发TOKEN // Issue TOKEN 签发TOKEN
String issueToken = JsonWebTokenUtil.issueJwt(userId, PERIOD_TIME, roles); String issueToken = JsonWebTokenUtil.issueJwt(userId, PERIOD_TIME, roles);
Map<String, Object> customClaimMap = new HashMap<>(1); Map<String, Object> customClaimMap = new HashMap<>(1);
customClaimMap.put("refresh", true); customClaimMap.put("refresh", true);

View File

@@ -21,11 +21,13 @@ import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/** /**
* Monitoring Type Management API
* 监控类型管理API * 监控类型管理API
*
* @author tomsun28 * @author tomsun28
* @date 2021/11/14 16:47 * @date 2021/11/14 16:47
*/ */
@Api(tags = "监控类型管理API") @Api(tags = "en: Monitoring Type Management API,zh: 监控类型管理API")
@RestController @RestController
@RequestMapping(path = "/apps", produces = {APPLICATION_JSON_VALUE}) @RequestMapping(path = "/apps", produces = {APPLICATION_JSON_VALUE})
public class AppController { public class AppController {
@@ -34,25 +36,26 @@ public class AppController {
private AppService appService; private AppService appService;
@GetMapping(path = "/{app}/params") @GetMapping(path = "/{app}/params")
@ApiOperation(value = "查询监控类型的参数结构", notes = "根据app查询指定监控类型的需要输入参数的结构") @ApiOperation(value = "The structure of the input parameters required to specify the monitoring type according to the app query", notes = "根据app查询指定监控类型的需要输入参数的结构")
public ResponseEntity<Message<List<ParamDefine>>> queryAppParamDefines( public ResponseEntity<Message<List<ParamDefine>>> queryAppParamDefines(
@ApiParam(value = "监控类型名称", example = "api") @PathVariable("app") final String app) { @ApiParam(value = "en: Monitoring type name,zh: 监控类型名称", example = "api") @PathVariable("app") final String app) {
List<ParamDefine> paramDefines = appService.getAppParamDefines(app.toLowerCase()); List<ParamDefine> paramDefines = appService.getAppParamDefines(app.toLowerCase());
return ResponseEntity.ok(new Message<>(paramDefines)); return ResponseEntity.ok(new Message<>(paramDefines));
} }
@GetMapping(path = "/{app}/define") @GetMapping(path = "/{app}/define")
@ApiOperation(value = "查询监控类型的结构定义", notes = "根据app查询指定监控类型的定义结构") @ApiOperation(value = "The definition structure of the specified monitoring type according to the app query", notes = "根据app查询指定监控类型的定义结构")
public ResponseEntity<Message<Job>> queryAppDefine( public ResponseEntity<Message<Job>> queryAppDefine(
@ApiParam(value = "监控类型名称", example = "api") @PathVariable("app") final String app) { @ApiParam(value = "en: Monitoring type name,zh: 监控类型名称", example = "api") @PathVariable("app") final String app) {
Job define = appService.getAppDefine(app.toLowerCase()); Job define = appService.getAppDefine(app.toLowerCase());
return ResponseEntity.ok(new Message<>(define)); return ResponseEntity.ok(new Message<>(define));
} }
@GetMapping(path = "/hierarchy") @GetMapping(path = "/hierarchy")
@ApiOperation(value = "查询全部监控指标层级", notes = "查询所有监控的类型-指标组-指标层级,以层级结构输出") @ApiOperation(value = "Query all monitored types-indicator group-indicator level, output in a hierarchical structure", notes = "查询所有监控的类型-指标组-指标层级,以层级结构输出")
public ResponseEntity<Message<List<Hierarchy>>> queryAppsHierarchy( public ResponseEntity<Message<List<Hierarchy>>> queryAppsHierarchy(
@ApiParam(value = "语言类型", example = "zh-CN", defaultValue = "zh-CN") @ApiParam(value = "en: language type,zh: 语言类型",
example = "zh-CN", defaultValue = "zh-CN")
@RequestParam(name = "lang", required = false) String lang) { @RequestParam(name = "lang", required = false) String lang) {
if (lang == null || "".equals(lang)) { if (lang == null || "".equals(lang)) {
lang = "zh-CN"; lang = "zh-CN";

View File

@@ -6,16 +6,20 @@ import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List; import java.util.List;
/** /**
* Param Define Database Operations
* ParamDefine数据库操作 * ParamDefine数据库操作
*
* @author tomsun28 * @author tomsun28
* @date 2021/11/14 11:27 * @date 2021/11/14 11:27
*/ */
public interface ParamDefineDao extends JpaRepository<ParamDefine, Long> { public interface ParamDefineDao extends JpaRepository<ParamDefine, Long> {
/** /**
* Query the parameter definitions under it according to the monitoring type
* 根据监控类型查询其下的参数定义 * 根据监控类型查询其下的参数定义
* @param app 监控类型 *
* @return 参数定义列表 * @param app Monitoring type 监控类型
* @return parameter definition list 参数定义列表
*/ */
List<ParamDefine> findParamDefinesByApp(String app); List<ParamDefine> findParamDefinesByApp(String app);
} }

View File

@@ -11,8 +11,11 @@ import java.util.List;
import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE; import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
/** /**
* Hierarchical structure
* 层级关系结构 * 层级关系结构
* eg: Monitoring Type Indicator Group Indicator Information Hierarchy Relationship
* eg: 监控类型指标组指标信息层级关系 * eg: 监控类型指标组指标信息层级关系
*
* @author tom * @author tom
* @date 2021/12/12 16:23 * @date 2021/12/12 16:23
*/ */
@@ -21,18 +24,33 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
@Data @Data
public class Hierarchy { public class Hierarchy {
/**
* Category value
*/
@ApiModelProperty(value = "类别值", example = "os", accessMode = READ_WRITE, position = 0) @ApiModelProperty(value = "类别值", example = "os", accessMode = READ_WRITE, position = 0)
String category; String category;
/**
* Attribute value
*/
@ApiModelProperty(value = "属性值", example = "linux", accessMode = READ_WRITE, position = 1) @ApiModelProperty(value = "属性值", example = "linux", accessMode = READ_WRITE, position = 1)
String value; String value;
/**
* Attribute internationalization tag
*/
@ApiModelProperty(value = "属性国际化标签", example = "Linux系统", accessMode = READ_WRITE, position = 2) @ApiModelProperty(value = "属性国际化标签", example = "Linux系统", accessMode = READ_WRITE, position = 2)
String label; String label;
/**
* Is it a leaf node
*/
@ApiModelProperty(value = "是否是叶子节点", example = "true", accessMode = READ_WRITE, position = 3) @ApiModelProperty(value = "是否是叶子节点", example = "true", accessMode = READ_WRITE, position = 3)
Boolean isLeaf = false; Boolean isLeaf = false;
/**
* Next level of association
*/
@ApiModelProperty(value = "下一关联层级", accessMode = READ_WRITE, position = 4) @ApiModelProperty(value = "下一关联层级", accessMode = READ_WRITE, position = 4)
private List<Hierarchy> children; private List<Hierarchy> children;
} }

View File

@@ -13,7 +13,9 @@ import javax.validation.constraints.NotBlank;
import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY; import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY;
/** /**
* Login registered account information transfer body username phone email
* 登录注册账户信息传输体 username phone email * 登录注册账户信息传输体 username phone email
*
* @author tomsun28 * @author tomsun28
* @date 20:36 2019-08-01 * @date 20:36 2019-08-01
*/ */
@@ -21,17 +23,27 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY;
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@ApiModel(description = "账户信息传输体") @ApiModel(description = "en: Account information transfer body,zh: 账户信息传输体")
public class LoginDto { public class LoginDto {
/**
* type
* 1. Account (email username and mobile phone number) password login 2. github login 3. WeChat login
*/
@ApiModelProperty(value = "类型", example = "1", accessMode = READ_ONLY, position = 0) @ApiModelProperty(value = "类型", example = "1", accessMode = READ_ONLY, position = 0)
@Range(min = 0, max = 4, message = "1.账户(邮箱用户名手机号)密码登录 2.github登录 3.微信登录") @Range(min = 0, max = 4, message = "1.账户(邮箱用户名手机号)密码登录 2.github登录 3.微信登录")
private Byte type; private Byte type;
/**
* User ID
*/
@ApiModelProperty(value = "用户标识", example = "1", accessMode = READ_ONLY, position = 0) @ApiModelProperty(value = "用户标识", example = "1", accessMode = READ_ONLY, position = 0)
@NotBlank(message = "Identifier can not null") @NotBlank(message = "Identifier can not null")
private String identifier; private String identifier;
/**
* key
*/
@ApiModelProperty(value = "密钥", example = "1", accessMode = READ_ONLY, position = 0) @ApiModelProperty(value = "密钥", example = "1", accessMode = READ_ONLY, position = 0)
@NotBlank(message = "Credential can not null") @NotBlank(message = "Credential can not null")
private String credential; private String credential;

View File

@@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Monitoring Type Management Interface
* 监控类型管理接口 * 监控类型管理接口
* *
* @author tomsun28 * @author tomsun28
@@ -16,10 +17,11 @@ import java.util.Map;
public interface AppService { public interface AppService {
/** /**
* Query the defined parameter structure based on the monitoring type
* 根据监控类型查询定义的参数结构 * 根据监控类型查询定义的参数结构
* *
* @param app 监控类型 * @param app Monitoring type 监控类型
* @return 参数结构列表 * @return list of parameter structures 参数结构列表
*/ */
List<ParamDefine> getAppParamDefines(String app); List<ParamDefine> getAppParamDefines(String app);
@@ -35,18 +37,20 @@ public interface AppService {
Job getAppDefine(String app) throws IllegalArgumentException; Job getAppDefine(String app) throws IllegalArgumentException;
/** /**
* Get defined monitoring I 18 N resources
* 获取定义的监控I18N资源 * 获取定义的监控I18N资源
* *
* @param lang 语言类型 * @param lang Language type 语言类型
* @return I18N资源 * @return I18N Resources I18N资源
*/ */
Map<String, String> getI18nResources(String lang); Map<String, String> getI18nResources(String lang);
/** /**
* Query all types of monitoring - indicator group - indicator level
* 查询所有监控的类型-指标组-指标层级 * 查询所有监控的类型-指标组-指标层级
* *
* @param lang 语言 * @param lang language 语言
* @return 层级信息 * @return level information 层级信息
*/ */
List<Hierarchy> getAllAppHierarchy(String lang); List<Hierarchy> getAllAppHierarchy(String lang);

View File

@@ -1,6 +1,5 @@
package com.usthe.manager.service.impl; package com.usthe.manager.service.impl;
import com.usthe.alert.AlerterProperties;
import com.usthe.common.entity.alerter.Alert; import com.usthe.common.entity.alerter.Alert;
import com.usthe.common.util.CommonUtil; import com.usthe.common.util.CommonUtil;
import com.usthe.manager.service.MailService; import com.usthe.manager.service.MailService;
@@ -12,7 +11,6 @@ import org.thymeleaf.context.Context;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* Mailbox sending service interface implementation class
* 邮箱发送服务接口实现类 * 邮箱发送服务接口实现类
* *
* @author 花城 * @author 花城
@@ -25,12 +23,9 @@ public class MailServiceImpl implements MailService {
@Resource @Resource
private TemplateEngine templateEngine; private TemplateEngine templateEngine;
@Resource
private AlerterProperties alerterProperties;
@Override @Override
public String buildAlertHtmlTemplate(final Alert alert) { public String buildAlertHtmlTemplate(final Alert alert) {
// Introduce thymeleaf context parameters to render pages
// 引入thymeleaf上下文参数渲染页面 // 引入thymeleaf上下文参数渲染页面
Context context = new Context(); Context context = new Context();
context.setVariable("target",alert.getTarget()); context.setVariable("target",alert.getTarget());
@@ -38,7 +33,6 @@ public class MailServiceImpl implements MailService {
context.setVariable("monitorName",alert.getMonitorName()); context.setVariable("monitorName",alert.getMonitorName());
context.setVariable("priority", CommonUtil.transferAlertPriority(alert.getPriority())); context.setVariable("priority", CommonUtil.transferAlertPriority(alert.getPriority()));
context.setVariable("content",alert.getContent()); context.setVariable("content",alert.getContent());
context.setVariable("consoleUrl", alerterProperties.getConsoleUrl());
return templateEngine.process("mailAlarm", context); return templateEngine.process("mailAlarm", context);
} }
} }

View File

@@ -69,8 +69,3 @@ warehouse:
url: jdbc:TAOS-RS://localhost:6041/hertzbeat url: jdbc:TAOS-RS://localhost:6041/hertzbeat
username: root username: root
password: taosdata password: taosdata
#自定义告警控制台地址
alerter:
#这里就是我们的自定义控制台地址
console-url: https://console.tancloud.cn

View File

@@ -2,35 +2,10 @@
# 加载到匹配字典的资源,也就是需要被保护的,设置了所支持角色访问的资源 # 加载到匹配字典的资源,也就是需要被保护的,设置了所支持角色访问的资源
# 没有配置的资源也默认被认证保护,但不鉴权 # 没有配置的资源也默认被认证保护,但不鉴权
# eg: /api/v1/source1===get===[admin] 表示 /api/v2/host===post 这条资源支持 admin 这一种角色访问 # eg: /api/v1/source1===get===[role2] 表示 /api/v2/host===post 这条资源支持 role2 这一种角色访问
# eg: /api/v1/source2===get===[] 表示 /api/v1/source2===get 这条资源不支持任何角色访问 # eg: /api/v1/source2===get===[] 表示 /api/v1/source2===get 这条资源不支持任何角色访问
resourceRole: resourceRole:
- /account/auth/refresh===post===[admin,user,guest] - /account/auth/refresh===post===[role1,role2,role3,role4]
- /apps/**===get===[admin,user,guest]
- /monitor/**===get===[admin,user,guest]
- /monitor/**===post===[admin,user]
- /monitor/**===put===[admin,user]
- /monitor/**===delete==[admin]
- /monitors/**===get===[admin,user,guest]
- /monitors/**===post===[admin,user]
- /monitors/**===put===[admin,user]
- /monitors/**===delete===[admin]
- /alert/**===get===[admin,user,guest]
- /alert/**===post===[admin,user]
- /alert/**===put===[admin,user]
- /alert/**===delete===[admin]
- /alerts/**===get===[admin,user,guest]
- /alerts/**===post===[admin,user]
- /alerts/**===put===[admin,user]
- /alerts/**===delete===[admin]
- /notice/**===get===[admin,user,guest]
- /notice/**===post===[admin,user]
- /notice/**===put===[admin,user]
- /notice/**===delete===[admin]
- /summary/**===get===[admin,user,guest]
- /summary/**===post===[admin,user]
- /summary/**===put===[admin,user]
- /summary/**===delete===[admin]
# 需要被过滤保护的资源,不认证鉴权直接访问 # 需要被过滤保护的资源,不认证鉴权直接访问
# /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权 # /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权
@@ -56,23 +31,20 @@ excludedResource:
# 用户账户信息 # 用户账户信息
# 下面有 admin tom lili 三个账户 # 下面有 admin tom lili 三个账户
# eg: admin 拥有[admin,user]角色,密码为admin # eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[user],密码为tom@123 # eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[guest],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289 # eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account: account:
- appId: admin - appId: admin
credential: admin credential: admin
role: [admin,user] role: [role1,role2]
- appId: tom - appId: tom
credential: tom@123 credential: tom@123
role: [user] role: [role1,role2,role3]
- appId: guest
credential: guest
role: [guest]
- appId: lili - appId: lili
# 注意 Digest认证不支持加盐加密的密码账户 # 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算 # 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili # 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289 credential: 1A676730B0C7F54654B0E09184448289
salt: 123 salt: 123
role: [guest] role: [role1,role2]

View File

@@ -700,7 +700,7 @@
<span style="font-family:Arial, Verdana; font-size:14px;color:#FFFFFF;"><a <span style="font-family:Arial, Verdana; font-size:14px;color:#FFFFFF;"><a
target="_blank" target="_blank"
style="color:#FFFFFF;text-decoration:none;" style="color:#FFFFFF;text-decoration:none;"
th:href="${consoleUrl}" href="https://console.tancloud.cn"
data-link-type="web">登入控制台</a></span> data-link-type="web">登入控制台</a></span>
</td> </td>
</tr> </tr>

View File

@@ -2,35 +2,10 @@
# 加载到匹配字典的资源,也就是需要被保护的,设置了所支持角色访问的资源 # 加载到匹配字典的资源,也就是需要被保护的,设置了所支持角色访问的资源
# 没有配置的资源也默认被认证保护,但不鉴权 # 没有配置的资源也默认被认证保护,但不鉴权
# eg: /api/v1/source1===get===[admin] 表示 /api/v2/host===post 这条资源支持 admin 这一种角色访问 # eg: /api/v1/source1===get===[role2] 表示 /api/v2/host===post 这条资源支持 role2 这一种角色访问
# eg: /api/v1/source2===get===[] 表示 /api/v1/source2===get 这条资源不支持任何角色访问 # eg: /api/v1/source2===get===[] 表示 /api/v1/source2===get 这条资源不支持任何角色访问
resourceRole: resourceRole:
- /account/auth/refresh===post===[admin,user,guest] - /account/auth/refresh===post===[role1,role2,role3,role4]
- /apps/**===get===[admin,user,guest]
- /monitor/**===get===[admin,user,guest]
- /monitor/**===post===[admin,user]
- /monitor/**===put===[admin,user]
- /monitor/**===delete==[admin]
- /monitors/**===get===[admin,user,guest]
- /monitors/**===post===[admin,user]
- /monitors/**===put===[admin,user]
- /monitors/**===delete===[admin]
- /alert/**===get===[admin,user,guest]
- /alert/**===post===[admin,user]
- /alert/**===put===[admin,user]
- /alert/**===delete===[admin]
- /alerts/**===get===[admin,user,guest]
- /alerts/**===post===[admin,user]
- /alerts/**===put===[admin,user]
- /alerts/**===delete===[admin]
- /notice/**===get===[admin,user,guest]
- /notice/**===post===[admin,user]
- /notice/**===put===[admin,user]
- /notice/**===delete===[admin]
- /summary/**===get===[admin,user,guest]
- /summary/**===post===[admin,user]
- /summary/**===put===[admin,user]
- /summary/**===delete===[admin]
# 需要被过滤保护的资源,不认证鉴权直接访问 # 需要被过滤保护的资源,不认证鉴权直接访问
# /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权 # /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权
@@ -56,23 +31,20 @@ excludedResource:
# 用户账户信息 # 用户账户信息
# 下面有 admin tom lili 三个账户 # 下面有 admin tom lili 三个账户
# eg: admin 拥有[admin,user]角色,密码为admin # eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[user],密码为tom@123 # eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[guest],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289 # eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account: account:
- appId: admin - appId: admin
credential: admin credential: admin
role: [admin,user] role: [role1,role2]
- appId: tom - appId: tom
credential: tom@123 credential: tom
role: [user] role: [role1,role2,role3]
- appId: guest
credential: guest
role: [guest]
- appId: lili - appId: lili
# 注意 Digest认证不支持加盐加密的密码账户 # 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算 # 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili # 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289 credential: 1A676730B0C7F54654B0E09194448289
salt: 123 salt: 123
role: [guest] role: [role1,role2]

View File

@@ -26,8 +26,6 @@ services:
container_name: tdengine container_name: tdengine
hostname: tdengine hostname: tdengine
restart: always restart: always
environment:
TZ: Asia/Shanghai
ports: ports:
- "6030-6049:6030-6049" - "6030-6049:6030-6049"
- "6030-6049:6030-6049/udp" - "6030-6049:6030-6049/udp"

View File

@@ -2,35 +2,10 @@
# 加载到匹配字典的资源,也就是需要被保护的,设置了所支持角色访问的资源 # 加载到匹配字典的资源,也就是需要被保护的,设置了所支持角色访问的资源
# 没有配置的资源也默认被认证保护,但不鉴权 # 没有配置的资源也默认被认证保护,但不鉴权
# eg: /api/v1/source1===get===[admin] 表示 /api/v2/host===post 这条资源支持 admin 这一种角色访问 # eg: /api/v1/source1===get===[role2] 表示 /api/v2/host===post 这条资源支持 role2 这一种角色访问
# eg: /api/v1/source2===get===[] 表示 /api/v1/source2===get 这条资源不支持任何角色访问 # eg: /api/v1/source2===get===[] 表示 /api/v1/source2===get 这条资源不支持任何角色访问
resourceRole: resourceRole:
- /account/auth/refresh===post===[admin,user,guest] - /account/auth/refresh===post===[role1,role2,role3,role4]
- /apps/**===get===[admin,user,guest]
- /monitor/**===get===[admin,user,guest]
- /monitor/**===post===[admin,user]
- /monitor/**===put===[admin,user]
- /monitor/**===delete==[admin]
- /monitors/**===get===[admin,user,guest]
- /monitors/**===post===[admin,user]
- /monitors/**===put===[admin,user]
- /monitors/**===delete===[admin]
- /alert/**===get===[admin,user,guest]
- /alert/**===post===[admin,user]
- /alert/**===put===[admin,user]
- /alert/**===delete===[admin]
- /alerts/**===get===[admin,user,guest]
- /alerts/**===post===[admin,user]
- /alerts/**===put===[admin,user]
- /alerts/**===delete===[admin]
- /notice/**===get===[admin,user,guest]
- /notice/**===post===[admin,user]
- /notice/**===put===[admin,user]
- /notice/**===delete===[admin]
- /summary/**===get===[admin,user,guest]
- /summary/**===post===[admin,user]
- /summary/**===put===[admin,user]
- /summary/**===delete===[admin]
# 需要被过滤保护的资源,不认证鉴权直接访问 # 需要被过滤保护的资源,不认证鉴权直接访问
# /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权 # /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权
@@ -56,23 +31,20 @@ excludedResource:
# 用户账户信息 # 用户账户信息
# 下面有 admin tom lili 三个账户 # 下面有 admin tom lili 三个账户
# eg: admin 拥有[admin,user]角色,密码为admin # eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[user],密码为tom@123 # eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[guest],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289 # eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account: account:
- appId: admin - appId: admin
credential: admin credential: admin
role: [admin,user] role: [role1,role2]
- appId: tom - appId: tom
credential: tom@123 credential: tom@123
role: [user] role: [role1,role2,role3]
- appId: guest
credential: guest
role: [guest]
- appId: lili - appId: lili
# 注意 Digest认证不支持加盐加密的密码账户 # 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算 # 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili # 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289 credential: 1A676730B0C7F54654B0E09184448289
salt: 123 salt: 123
role: [guest] role: [role1,role2]

View File

@@ -26,8 +26,8 @@ const CODE_MESSAGE: { [key: number]: string } = {
202: '一个请求已经进入后台排队(异步任务)。', 202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。', 204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。', 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户认证信息异常。', 401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户无此操作权限。', 403: '用户无权限访问此资源。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。', 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。', 406: '请求的格式不可得。',
409: '请求与服务器端目标资源的当前状态相冲突', 409: '请求与服务器端目标资源的当前状态相冲突',
@@ -65,12 +65,8 @@ export class DefaultInterceptor implements HttpInterceptor {
private checkStatus(ev: HttpResponseBase): void { private checkStatus(ev: HttpResponseBase): void {
const errorText = CODE_MESSAGE[ev.status] || ev.statusText; const errorText = CODE_MESSAGE[ev.status] || ev.statusText;
console.warn(` ${ev.status}: ${ev.url}`, errorText); console.warn(` ${ev.status}: ${ev.url}`, errorText);
if (ev.status == 403) {
this.notification.error(` ${ev.status}: ${errorText}`, '');
} else {
this.notification.error(` ${ev.status}: ${ev.url}`, errorText); this.notification.error(` ${ev.status}: ${ev.url}`, errorText);
} }
}
/** /**
* 刷新 Token 请求 * 刷新 Token 请求

View File

@@ -54,7 +54,7 @@ export class HeaderNotifyComponent implements OnInit {
return; return;
} }
this.loading = true; this.loading = true;
let loadAlerts$ = this.alertSvc.loadAlerts(0, undefined, undefined, 0, 5).subscribe( let loadAlerts$ = this.alertSvc.searchAlerts(0, undefined, undefined, 0, 5).subscribe(
message => { message => {
loadAlerts$.unsubscribe(); loadAlerts$.unsubscribe();
if (message.code === 0) { if (message.code === 0) {

View File

@@ -30,7 +30,7 @@
<i nz-icon nzType="sync" nzTheme="outline"></i> <i nz-icon nzType="sync" nzTheme="outline"></i>
</button> </button>
<button style="margin-right: 25px; float: right" nz-button nzType="primary" (click)="loadAlertsTable()"> <button style="margin-right: 25px; float: right" nz-button nzType="primary" (click)="onFilterSearchAlerts()">
{{ 'common.search' | i18n }} {{ 'common.search' | i18n }}
</button> </button>
<input <input
@@ -39,7 +39,7 @@
type="text" type="text"
[placeholder]="'alert.center.search' | i18n" [placeholder]="'alert.center.search' | i18n"
nzSize="default" nzSize="default"
(keyup.enter)="loadAlertsTable()" (keyup.enter)="onFilterSearchAlerts()"
[(ngModel)]="filterContent" [(ngModel)]="filterContent"
/> />
<nz-select <nz-select

View File

@@ -36,15 +36,40 @@ export class AlertCenterComponent implements OnInit {
this.loadAlertsTable(); this.loadAlertsTable();
} }
onFilterSearchAlerts() {
this.tableLoading = true;
let filterAlerts$ = this.alertSvc
.searchAlerts(this.filterStatus, this.filterPriority, this.filterContent, this.pageIndex - 1, this.pageSize)
.subscribe(
message => {
filterAlerts$.unsubscribe();
this.tableLoading = false;
this.checkedAll = false;
this.checkedAlertIds.clear();
if (message.code === 0) {
let page = message.data;
this.alerts = page.content;
this.pageIndex = page.number + 1;
this.total = page.totalElements;
} else {
console.warn(message.msg);
}
},
error => {
this.tableLoading = false;
filterAlerts$.unsubscribe();
console.error(error.msg);
}
);
}
sync() { sync() {
this.loadAlertsTable(); this.loadAlertsTable();
} }
loadAlertsTable() { loadAlertsTable() {
this.tableLoading = true; this.tableLoading = true;
let alertsInit$ = this.alertSvc let alertsInit$ = this.alertSvc.getAlerts(this.pageIndex - 1, this.pageSize).subscribe(
.loadAlerts(this.filterStatus, this.filterPriority, this.filterContent, this.pageIndex - 1, this.pageSize)
.subscribe(
message => { message => {
this.tableLoading = false; this.tableLoading = false;
this.checkedAll = false; this.checkedAll = false;

View File

@@ -347,7 +347,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
alertsDealLoading: boolean = true; alertsDealLoading: boolean = true;
refreshAlertContentList(): void { refreshAlertContentList(): void {
let alertsInit$ = this.alertSvc.loadAlerts(undefined, undefined, undefined, 0, 4).subscribe( let alertsInit$ = this.alertSvc.getAlerts(0, 4).subscribe(
message => { message => {
if (message.code === 0) { if (message.code === 0) {
let page = message.data; let page = message.data;

View File

@@ -16,7 +16,22 @@ const alerts_status_uri = '/alerts/status';
export class AlertService { export class AlertService {
constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
public loadAlerts( public getAlerts(pageIndex: number, pageSize: number): Observable<Message<Page<Alert>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// 注意HttpParams是不可变对象 需要保存set后返回的对象为最新对象
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'id',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
const options = { params: httpParams };
return this.http.get<Message<Page<Alert>>>(alerts_uri, options);
}
public searchAlerts(
status: number | undefined, status: number | undefined,
priority: number | undefined, priority: number | undefined,
content: string | undefined, content: string | undefined,