Compare commits

...

134 Commits

Author SHA1 Message Date
刘祥超
6a9045ba44 提交SQL 2022-07-18 09:13:16 +08:00
刘祥超
bc7ee19962 优化代码 2022-07-17 17:08:28 +08:00
刘祥超
2484cd4ae6 可以通过ID查找服务 2022-07-17 11:43:23 +08:00
刘祥超
57b8a96c6d 增加用户身份认证相关接口 2022-07-17 11:00:14 +08:00
刘祥超
6c8ab7cb94 集群DNS设置增加允许通过CNAME访问网站服务选项 2022-07-14 09:49:09 +08:00
刘祥超
b2c2bd247b 更新SQL 2022-07-12 14:22:20 +08:00
刘祥超
29d9e6db81 域名解析支持DNS.COM(商业版) 2022-07-11 11:51:49 +08:00
刘祥超
24fcb48c75 删除节点的时候同时也删除相关的运行日志 2022-07-07 20:31:12 +08:00
刘祥超
4911198fe7 安全设置中增加禁止搜索引擎、禁止爬虫、允许访问的域名等选项 2022-07-07 19:58:50 +08:00
刘祥超
c2af796992 服务看板增加峰值带宽数据 2022-07-07 17:11:49 +08:00
刘祥超
51c8572e53 用户界面设置中增加流量、带宽相关设置 2022-07-07 12:40:05 +08:00
刘祥超
c15cc6d75c 增加按用户统计带宽/修改其他相关代码 2022-07-07 09:18:08 +08:00
刘祥超
c0a99a4ba3 升级Go版本为1.18 2022-07-06 16:13:52 +08:00
刘祥超
62e26bed5a 增加服务带宽统计 2022-07-05 20:08:58 +08:00
刘祥超
9e68a2915c 增加UAM(5秒盾)集群设置 2022-07-03 22:10:46 +08:00
刘祥超
5b809fda1f 反向代理设置中增加移除回源主机名端口功能 2022-06-30 12:12:41 +08:00
刘祥超
88b782940a 提交SQL 2022-06-29 22:17:32 +08:00
刘祥超
85c596644d 实现源站端口跟随功能 2022-06-29 21:55:57 +08:00
刘祥超
ffa2d884bd 移除386、mips等不常用节点安装文件 2022-06-29 17:11:13 +08:00
刘祥超
813ed18610 优化编译脚本 2022-06-29 16:57:46 +08:00
刘祥超
564b11eae7 优化编译脚本 2022-06-29 14:52:11 +08:00
刘祥超
d2af0307b9 将DNS版本改为0.2.4 2022-06-28 20:31:59 +08:00
刘祥超
4fa6b03238 对于小内存(不大于2G),缩短服务统计导入数据库的时间 2022-06-25 20:57:03 +08:00
刘祥超
4bda78aa8c 限制节点自动升级时的速度和并发数 2022-06-25 20:36:31 +08:00
刘祥超
6002cc96d9 增加修改服务所在分组API 2022-06-25 19:21:46 +08:00
刘祥超
56c09f5be7 指标数据写入改成队列执行 2022-06-22 21:51:44 +08:00
刘祥超
e1fb8e4c74 删除某个IP时更新版本 2022-06-22 18:59:27 +08:00
刘祥超
14f055ce7c fix typo 2022-06-22 14:00:56 +08:00
刘祥超
7b7f2b0a00 修改版本号为v0.4.9 2022-06-20 16:00:27 +08:00
刘祥超
75662586fa 修改相关节点版本 2022-06-20 09:34:40 +08:00
刘祥超
c024331fa0 增加统计服务某日、某月流量API 2022-06-18 14:26:43 +08:00
刘祥超
b01ea79c5c 升级IP名单权限判断逻辑 2022-06-15 19:22:33 +08:00
刘祥超
d59f80b3ec 优化缓存任务Key状态增加执行中状态 2022-06-15 15:18:18 +08:00
刘祥超
b87e48c1f9 城市API增加省份信息 2022-06-14 17:37:42 +08:00
刘祥超
0e7a7f168f 访问日志查询增加requestPath:/hello、proto:HTTP/1.1、scheme:http等语法 2022-06-12 20:30:28 +08:00
刘祥超
2bbc09d3af 优化syslog提示、优化其他代码 2022-06-08 19:55:06 +08:00
刘祥超
97b50fab28 删除EdgePlus 2022-06-08 15:14:30 +08:00
刘祥超
83c867cb65 API节点启动失败后记录相关问题和处理建议 2022-06-08 15:13:24 +08:00
刘祥超
3c4b7ca57b 节点状态中增加时间戳字段 2022-06-06 19:39:08 +08:00
刘祥超
a2f98d2f25 可以设置用户每天执行缓存任务的额度 2022-06-05 21:15:28 +08:00
刘祥超
71677a8638 增加刷新、预热缓存任务管理 2022-06-05 17:13:56 +08:00
刘祥超
95a2187f95 优化API/修改用户集群不影响套餐服务 2022-05-25 11:44:18 +08:00
刘祥超
86bec813bf fix typo 2022-05-22 11:48:31 +08:00
刘祥超
0d7bd6f04e 增加LICENSE和README 2022-05-22 11:36:54 +08:00
刘祥超
d7117209b2 删除不过期IP时不立即删除,以等待节点完成同步 2022-05-21 22:06:04 +08:00
刘祥超
7a340ac68b 新创建WAF时增加默认选项 2022-05-21 18:58:03 +08:00
刘祥超
353b1b4ad1 WAF策略中增加验证码相关定制设置 2022-05-20 22:07:23 +08:00
刘祥超
fdac8beb40 健康检查增加是否记录访问日志选项 2022-05-19 17:14:32 +08:00
刘祥超
f098723a41 实现基础的DDoS防护 2022-05-18 21:02:53 +08:00
刘祥超
6ded627903 增加通过IP删除IP名单中IP参数 2022-05-10 15:11:48 +08:00
刘祥超
ed2d5ee5cc fix typo 2022-05-08 19:33:17 +08:00
刘祥超
c677368482 集群节点列表可以使用“未分组”筛选 2022-05-08 19:33:10 +08:00
刘祥超
51ccd614a7 忽略部分MySQL 1213错误 2022-05-08 00:24:22 +08:00
刘祥超
9be7f61b8c 阿里云DNS增加区域ID 2022-05-07 21:00:07 +08:00
刘祥超
14ad97c937 DNS服务商增加厂家筛选 2022-05-07 20:41:53 +08:00
刘祥超
94609d8ef4 EdgeUser版本升级为0.3.4 2022-05-05 18:56:35 +08:00
刘祥超
e34e38bcb2 Update sql.go 2022-05-04 20:35:38 +08:00
刘祥超
b10d9fe842 路由规则可以单独设置UAM(仅企业版可用) 2022-05-04 20:32:34 +08:00
刘祥超
992e725378 节点增加DNS解析库类型设置 2022-05-04 16:40:34 +08:00
刘祥超
346de7ca7a 版本修改为0.4.8 2022-04-25 11:11:43 +08:00
刘祥超
b212e124c2 统计看板中合并相同Key的指标数据 2022-04-24 15:24:40 +08:00
刘祥超
ee2781fe65 优化代码 2022-04-23 13:26:15 +08:00
刘祥超
89c1edc9ee 多个API节点时选择一个作为主节点/优化任务相关代码 2022-04-23 12:32:30 +08:00
刘祥超
773f3e1a7e 修复无法使用倒序分表查询日志的问题 2022-04-22 22:23:07 +08:00
刘祥超
e6f6f4dcc2 集群概要信息中增加系统服务状态 2022-04-22 22:04:29 +08:00
刘祥超
174946aa4d 修复集群健康检查无法自动上下线IP地址的Bug 2022-04-22 21:53:38 +08:00
刘祥超
93c594a785 更新SQL 2022-04-22 17:16:19 +08:00
刘祥超
2aea527dff 访问日志策略增加只记录WAF相关访问日志选项 2022-04-22 17:13:59 +08:00
刘祥超
fa30015ca5 增加WAF策略日志设置 2022-04-21 20:00:56 +08:00
刘祥超
d06c8cebf5 IP列表增加名单类型筛选 2022-04-21 15:09:18 +08:00
刘祥超
e4ef2e8253 WAF策略增加日志配置(暂未开放) /修复通过IP可能无法查询到访问日志的Bug 2022-04-21 09:41:04 +08:00
刘祥超
665aa06cc7 优化代码 2022-04-19 19:48:37 +08:00
刘祥超
88dfda82d6 Linux下自动添加端口到Firewalld 2022-04-19 19:35:50 +08:00
刘祥超
243463df83 优化代码 2022-04-19 12:58:00 +08:00
刘祥超
2dc1bfcb55 创建和修改证书的时候检查时间 2022-04-19 11:09:42 +08:00
刘祥超
e6f7cafe7e 当修改集群主域名和DNS子域名时,自动删除旧的相关域名 2022-04-18 21:00:40 +08:00
刘祥超
26fe3558f4 如果服务变更集群前后域名ID一致,则不执行删除操作 2022-04-18 18:35:57 +08:00
刘祥超
ea09ef3d91 服务切换集群后,直接删除老的域名记录 2022-04-18 18:21:29 +08:00
刘祥超
c4ca2521ee 单个服务切换集群时可以选择是否保留配置 2022-04-18 17:18:00 +08:00
刘祥超
db5cdd2957 修复没有日志数据库时无法进行分区查询的Bug 2022-04-17 16:50:38 +08:00
刘祥超
0f483b98ec 删除一处调试信息 2022-04-17 16:24:27 +08:00
刘祥超
0fe51abeb1 访问日志可以使用分表查询 2022-04-17 16:18:53 +08:00
刘祥超
db6b7f57bb 修复看板中统计数据可能不显示的问题 2022-04-16 22:22:05 +08:00
刘祥超
663ead19e4 优化节点排序 2022-04-16 14:45:54 +08:00
刘祥超
bc8adb663a 服务列表增加下行带宽 2022-04-15 12:14:59 +08:00
刘祥超
08b5dd7531 判断节点数量时增加集群状态检查 2022-04-14 22:00:47 +08:00
刘祥超
8177f3d7e4 可以通过groupId=-1查询到未分组的服务 2022-04-14 16:58:21 +08:00
刘祥超
bb5252caf6 edgeServers增加plainServerNames字段 2022-04-14 16:44:00 +08:00
刘祥超
bd4a47d2a1 服务列表中分组信息中增加UserId字段 2022-04-13 15:01:45 +08:00
刘祥超
300be4e936 预估同时间流量的时候刻度改为10分钟 2022-04-10 21:57:26 +08:00
刘祥超
c9dbfb79a7 按天统计流量接口可以预估某日同时间流量 2022-04-10 21:25:24 +08:00
刘祥超
589ae124f1 修复访问日志可能显示重复的问题 2022-04-10 18:21:52 +08:00
刘祥超
d72b440406 修改DNS版本为0.2.2 2022-04-10 16:02:21 +08:00
刘祥超
63e4e7cf9f 优化本地日志 2022-04-10 15:57:36 +08:00
刘祥超
ad416dddec 增加两个数据库相关调试命令 2022-04-08 15:09:33 +08:00
刘祥超
4e18129c6c 更新TeaGo 2022-04-08 14:57:20 +08:00
刘祥超
c03d9f1880 优化数据库相关代码 2022-04-08 14:15:45 +08:00
刘祥超
fe448e6556 增加当日统计接口 2022-04-07 19:46:50 +08:00
刘祥超
adcb33fce4 优化节点列表 2022-04-07 18:31:38 +08:00
刘祥超
e58c3774b6 优化代码 2022-04-05 19:32:35 +08:00
刘祥超
cd7e01c2f0 商业版支持L2节点 2022-04-04 12:08:08 +08:00
刘祥超
d884777a55 增加单元测试 2022-04-02 11:52:42 +08:00
刘祥超
c48aba1c99 更新TeaGo 2022-04-02 11:52:11 +08:00
刘祥超
8cc0faf1d7 集群可以单独设置WebP策略 2022-04-01 16:42:23 +08:00
刘祥超
9851b1a146 集群可以设置WebP策略 2022-04-01 16:18:54 +08:00
刘祥超
36162c603d 看板:只有指标数据不为空时才缓存 2022-04-01 10:00:10 +08:00
刘祥超
cc2782584e 自定义页面支持用户操作 2022-03-31 15:30:04 +08:00
刘祥超
1c1e82ee38 指标统计数据分表 2022-03-30 15:35:42 +08:00
刘祥超
4b3a9cedfa 可以用域名搜索DNS账号 2022-03-30 11:15:38 +08:00
刘祥超
e9497ee65d DNSPod支持国际站 2022-03-30 10:56:22 +08:00
刘祥超
29fae55dc6 IP列表可以使用级别筛选 2022-03-30 09:39:43 +08:00
刘祥超
54fdf3b762 支持DNSPod国际版(需要测试) 2022-03-30 09:12:42 +08:00
刘祥超
f609008984 商业版增加UAM功能 2022-03-29 21:24:31 +08:00
刘祥超
f9b6838dc6 写入指标统计数据时忽略MySQL 1213错误 2022-03-29 20:01:49 +08:00
刘祥超
6d2ecb9af3 对统计指标进行分表 2022-03-28 16:25:16 +08:00
刘祥超
7c4a01137b 数据库管理中列出更多可手动清理的数据表 2022-03-28 11:19:50 +08:00
刘祥超
418c15f79f 数据库管理中列出更多可手动清理的数据表 2022-03-28 11:12:49 +08:00
刘祥超
d13176b8a5 可以自行设定指标数据保留时间 2022-03-28 09:37:28 +08:00
刘祥超
b2752ddd5a 优化看板打开速度 2022-03-27 16:39:54 +08:00
刘祥超
7aea2fd48c 访问日志关键词支持完整的URL/优化Like语句 2022-03-27 12:22:47 +08:00
刘祥超
803f11659c 优化代码 2022-03-26 22:04:16 +08:00
刘祥超
073926ff67 修改用户平台版本为0.3.3 2022-03-26 22:04:10 +08:00
刘祥超
65b4832c94 增加脚本相关表 2022-03-25 14:11:17 +08:00
刘祥超
5f793f1f76 IP找不到不再提示错误 2022-03-24 21:41:14 +08:00
刘祥超
0ce1df25bc 可以修复单页或者全部服务日志 2022-03-23 17:31:26 +08:00
刘祥超
06ad9cc63b 版本号改为0.4.7 2022-03-23 14:45:37 +08:00
刘祥超
57247d0f5b 修复访问日志可能无法写入当天数据表的Bug 2022-03-23 10:58:54 +08:00
刘祥超
813267c50f 修复访问日志表可能无法自动创建的Bug 2022-03-23 10:05:42 +08:00
刘祥超
b8078e73b2 更改版本为v0.4.6 2022-03-23 10:03:57 +08:00
刘祥超
f958c57984 优化代码 2022-03-22 22:11:32 +08:00
刘祥超
30bfbdc01e 优化代码 2022-03-22 21:45:07 +08:00
刘祥超
314362c24d 优化代码 2022-03-22 19:30:30 +08:00
刘祥超
8582715be7 字段中的blob和JSON类型映射为[]byte和dbs.JSON 2022-03-21 21:39:36 +08:00
刘祥超
74e585263c 升级TeaGo 2022-03-21 19:46:14 +08:00
411 changed files with 12238 additions and 3974 deletions

29
LICENSE Normal file
View File

@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2020, LiuXiangChao
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

1
README.md Normal file
View File

@@ -0,0 +1 @@
GoEdge API节点源码

View File

@@ -1,76 +1,76 @@
#!/usr/bin/env bash
function build() {
ROOT=$(dirname $0)
ROOT=$(dirname "$0")
NAME="edge-api"
DIST=$ROOT/"../dist/${NAME}"
OS=${1}
ARCH=${2}
TAG=${3}
NODE_ARCHITECTS=("amd64" "386" "arm64" "mips64" "mips64le")
NODE_ARCHITECTS=("amd64" "arm64")
if [ -z $OS ]; then
if [ -z "$OS" ]; then
echo "usage: build.sh OS ARCH"
exit
fi
if [ -z $ARCH ]; then
if [ -z "$ARCH" ]; then
echo "usage: build.sh OS ARCH"
exit
fi
if [ -z $TAG ]; then
if [ -z "$TAG" ]; then
TAG="community"
fi
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
VERSION=$(lookup-version "$ROOT"/../internal/const/const.go)
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
# build edge-node
NodeVersion=$(lookup-version $ROOT"/../../EdgeNode/internal/const/const.go")
NodeVersion=$(lookup-version "$ROOT""/../../EdgeNode/internal/const/const.go")
echo "building edge-node v${NodeVersion} ..."
EDGE_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeNode/build/build.sh"
if [ ! -f $EDGE_NODE_BUILD_SCRIPT ]; then
if [ ! -f "$EDGE_NODE_BUILD_SCRIPT" ]; then
echo "unable to find edge-node build script 'EdgeNode/build/build.sh'"
exit
fi
cd $ROOT"/../../EdgeNode/build"
cd "$ROOT""/../../EdgeNode/build" || exit
echo "=============================="
for arch in "${NODE_ARCHITECTS[@]}"; do
if [ ! -f $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
./build.sh linux $arch $TAG
if [ ! -f "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
./build.sh linux "$arch" $TAG
else
echo "use built node linux/$arch/v${NodeVersion}"
fi
done
echo "=============================="
cd -
cd - || exit
rm -f $ROOT/deploy/*.zip
rm -f "$ROOT"/deploy/*.zip
for arch in "${NODE_ARCHITECTS[@]}"; do
cp $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" $ROOT/deploy/edge-node-linux-${arch}-v${NodeVersion}.zip
cp "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" "$ROOT"/deploy/edge-node-linux-"${arch}"-v"${NodeVersion}".zip
done
# build edge-dns
if [ "$TAG" = "plus" ]; then
DNS_ROOT=$ROOT"/../../EdgeDNS"
if [ -d $DNS_ROOT ]; then
DNSNodeVersion=$(lookup-version $ROOT"/../../EdgeDNS/internal/const/const.go")
if [ -d "$DNS_ROOT" ]; then
DNSNodeVersion=$(lookup-version "$ROOT""/../../EdgeDNS/internal/const/const.go")
echo "building edge-dns ${DNSNodeVersion} ..."
EDGE_DNS_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeDNS/build/build.sh"
if [ ! -f $EDGE_DNS_NODE_BUILD_SCRIPT ]; then
if [ ! -f "$EDGE_DNS_NODE_BUILD_SCRIPT" ]; then
echo "unable to find edge-dns build script 'EdgeDNS/build/build.sh'"
exit
fi
cd $ROOT"/../../EdgeDNS/build"
cd "$ROOT""/../../EdgeDNS/build" || exit
echo "=============================="
architects=("amd64")
architects=("amd64" "arm64")
for arch in "${architects[@]}"; do
./build.sh linux $arch $TAG
./build.sh linux "$arch" $TAG
done
echo "=============================="
cd -
cd - || exit
for arch in "${architects[@]}"; do
cp $ROOT"/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" $ROOT/deploy/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip
cp "$ROOT""/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" "$ROOT"/deploy/edge-dns-linux-"${arch}"-v"${DNSNodeVersion}".zip
done
fi
fi
@@ -78,48 +78,48 @@ function build() {
# build sql
if [ $TAG = "plus" ]; then
echo "building sql ..."
${ROOT}/sql.sh
"${ROOT}"/sql.sh
fi
# copy files
echo "copying ..."
if [ ! -d $DIST ]; then
mkdir $DIST
mkdir $DIST/bin
mkdir $DIST/configs
mkdir $DIST/logs
if [ ! -d "$DIST" ]; then
mkdir "$DIST"
mkdir "$DIST"/bin
mkdir "$DIST"/configs
mkdir "$DIST"/logs
fi
cp $ROOT/configs/api.template.yaml $DIST/configs/
cp $ROOT/configs/db.template.yaml $DIST/configs/
cp -R $ROOT/deploy $DIST/
rm -f $dist/deploy/.gitignore
cp -R $ROOT/installers $DIST/
cp -R $ROOT/resources $DIST/
rm -f $DIST/resources/ipdata/ip2region/global_region.csv
rm -f $DIST/resources/ipdata/ip2region/ip.merge.txt
cp "$ROOT"/configs/api.template.yaml "$DIST"/configs/
cp "$ROOT"/configs/db.template.yaml "$DIST"/configs/
cp -R "$ROOT"/deploy "$DIST/"
rm -f "$DIST"/deploy/.gitignore
cp -R "$ROOT"/installers "$DIST"/
cp -R "$ROOT"/resources "$DIST"/
rm -f "$DIST"/resources/ipdata/ip2region/global_region.csv
rm -f "$DIST"/resources/ipdata/ip2region/ip.merge.txt
# building edge installer
echo "building node installer ..."
architects=("amd64" "386" "arm64")
architects=("amd64" "arm64")
for arch in "${architects[@]}"; do
# TODO support arm, mips ...
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-helper-linux-${arch} $ROOT/../cmd/installer-helper/main.go
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-helper-linux-"${arch}" "$ROOT"/../cmd/installer-helper/main.go
done
# building edge dns installer
echo "building dns node installer ..."
architects=("amd64" "386" "arm64")
architects=("amd64" "arm64")
for arch in "${architects[@]}"; do
# TODO support arm, mips ...
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-dns-helper-linux-${arch} $ROOT/../cmd/installer-dns-helper/main.go
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-dns-helper-linux-"${arch}" "$ROOT"/../cmd/installer-dns-helper/main.go
done
# building api node
env GOOS=$OS GOARCH=$ARCH go build -tags $TAG --ldflags="-s -w" -o $DIST/bin/edge-api $ROOT/../cmd/edge-api/main.go
env GOOS="$OS" GOARCH="$ARCH" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$DIST"/bin/edge-api "$ROOT"/../cmd/edge-api/main.go
# delete hidden files
find $DIST -name ".DS_Store" -delete
find $DIST -name ".gitignore" -delete
find "$DIST" -name ".DS_Store" -delete
find "$DIST" -name ".gitignore" -delete
echo "zip files"
cd "${DIST}/../" || exit
@@ -135,15 +135,15 @@ function build() {
function lookup-version() {
FILE=$1
VERSION_DATA=$(cat $FILE)
VERSION_DATA=$(cat "$FILE")
re="Version[ ]+=[ ]+\"([0-9.]+)\""
if [[ $VERSION_DATA =~ $re ]]; then
VERSION=${BASH_REMATCH[1]}
echo $VERSION
echo "$VERSION"
else
echo "could not match version"
exit
fi
}
build $1 $2 $3
build "$1" "$2" "$3"

View File

@@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/TeaOSLab/EdgeAPI/internal/apps"
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
@@ -11,7 +12,9 @@ import (
"github.com/iwind/TeaGo/Tea"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"github.com/iwind/gosock/pkg/gosock"
"io/ioutil"
"log"
"os"
)
@@ -20,12 +23,12 @@ func main() {
if !Tea.IsTesting() {
Tea.Env = "prod"
}
app := apps.NewAppCmd()
var app = apps.NewAppCmd()
app.Version(teaconst.Version)
app.Product(teaconst.ProductName)
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon]")
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon|issues]")
app.On("setup", func() {
setupCmd := setup.NewSetupFromCmd()
var setupCmd = setup.NewSetupFromCmd()
err := setupCmd.Run()
result := maps.Map{}
if err != nil {
@@ -97,6 +100,68 @@ func main() {
}
}
})
app.On("db.stmt.prepare", func() {
var sock = gosock.NewTmpSock(teaconst.ProcessName)
reply, err := sock.Send(&gosock.Command{Code: "db.stmt.prepare"})
if err != nil {
fmt.Println("[ERROR]" + err.Error())
} else {
var isOn = maps.NewMap(reply.Params).GetBool("isOn")
if isOn {
fmt.Println("show statements: on")
} else {
fmt.Println("show statements: off")
}
}
})
app.On("db.stmt.count", func() {
var sock = gosock.NewTmpSock(teaconst.ProcessName)
reply, err := sock.Send(&gosock.Command{Code: "db.stmt.count"})
if err != nil {
fmt.Println("[ERROR]" + err.Error())
} else {
var count = maps.NewMap(reply.Params).GetInt("count")
fmt.Println("prepared statements count: " + types.String(count))
}
})
app.On("issues", func() {
var flagSet = flag.NewFlagSet("issues", flag.ExitOnError)
var formatJSON = false
flagSet.BoolVar(&formatJSON, "json", false, "")
_ = flagSet.Parse(os.Args[2:])
data, err := ioutil.ReadFile(Tea.LogFile("issues.log"))
if err != nil {
if formatJSON {
fmt.Print("[]")
} else {
fmt.Println("no issues yet")
}
} else {
var issueMaps = []maps.Map{}
err = json.Unmarshal(data, &issueMaps)
if err != nil {
if formatJSON {
fmt.Print("[]")
} else {
fmt.Println("no issues yet")
}
} else {
if formatJSON {
fmt.Print(string(data))
} else {
if len(issueMaps) == 0 {
fmt.Println("no issues yet")
} else {
for i, issue := range issueMaps {
fmt.Println("issue " + types.String(i+1) + ": " + issue.GetString("message"))
}
}
}
}
}
})
app.Run(func() {
nodes.NewAPINode().Start()
})

3
dist/.gitignore vendored
View File

@@ -1 +1,2 @@
*.zip
*.zip
edge-api

30
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/TeaOSLab/EdgeAPI
go 1.15
go 1.18
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
@@ -12,16 +12,36 @@ require (
github.com/go-acme/lego/v4 v4.5.2
github.com/go-sql-driver/mysql v1.5.0
github.com/golang/protobuf v1.5.2
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
github.com/json-iterator/go v1.1.12 // indirect
github.com/mozillazg/go-pinyin v0.18.0
github.com/pkg/sftp v1.12.0
github.com/shirou/gopsutil/v3 v3.22.2 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
github.com/shirou/gopsutil/v3 v3.22.2
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
require (
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/miekg/dns v1.1.43 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
)

21
go.sum
View File

@@ -66,7 +66,6 @@ github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7F
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -176,7 +175,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
@@ -238,8 +236,9 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475 h1:EseyfFaQOjWanGiby9KMw7PjDBMg/95tLDgIw/ns0Cw=
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570 h1:zqz2FiMMkSHXWO1EsTRJDPTwX9xQ4uuyD5GAE4JGlhM=
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
@@ -283,6 +282,7 @@ github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@@ -371,6 +371,7 @@ github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -398,8 +399,6 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@@ -440,12 +439,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -561,7 +556,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -627,7 +621,6 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -635,8 +628,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -735,8 +726,6 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc h1:fb/ViRpv3ln/LvbqZtTpoOd1YQDNH12gaGZreoSFovE=
google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -750,8 +739,6 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=

View File

@@ -12,8 +12,9 @@ import (
)
type BaseStorage struct {
isOk bool
version int
isOk bool
version int
firewallOnly bool
}
func (this *BaseStorage) SetVersion(version int) {
@@ -32,6 +33,10 @@ func (this *BaseStorage) SetOk(isOk bool) {
this.isOk = isOk
}
func (this *BaseStorage) SetFirewallOnly(firewallOnly bool) {
this.firewallOnly = firewallOnly
}
// Marshal 对日志进行编码
func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
return json.Marshal(accessLog)
@@ -39,7 +44,7 @@ func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
// FormatVariables 格式化字符串中的变量
func (this *BaseStorage) FormatVariables(s string) string {
now := time.Now()
var now = time.Now()
return configutils.ParseVariables(s, func(varName string) (value string) {
switch varName {
case "year":

View File

@@ -61,6 +61,10 @@ func (this *CommandStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
return err
}
for _, accessLog := range accessLogs {
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
continue
}
data, err := this.Marshal(accessLog)
if err != nil {
logs.Error(err)

View File

@@ -59,6 +59,10 @@ func (this *ESStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
indexName := this.FormatVariables(this.config.Index)
typeName := this.FormatVariables(this.config.MappingType)
for _, accessLog := range accessLogs {
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
continue
}
if len(accessLog.RequestId) == 0 {
continue
}

View File

@@ -57,6 +57,9 @@ func (this *FileStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
defer this.writeLocker.Unlock()
for _, accessLog := range accessLogs {
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
continue
}
data, err := this.Marshal(accessLog)
if err != nil {
logs.Error(err)

View File

@@ -12,6 +12,9 @@ type StorageInterface interface {
// SetVersion 设置版本
SetVersion(version int)
// SetFirewallOnly 设置是否只处理防火墙相关的访问日志
SetFirewallOnly(firewallOnly bool)
IsOk() bool
SetOk(ok bool)

View File

@@ -58,7 +58,7 @@ func (this *StorageManager) Loop() error {
}
var policyIds = []int64{}
for _, policy := range policies {
if policy.IsOn == 1 {
if policy.IsOn {
policyIds = append(policyIds, int64(policy.Id))
}
}
@@ -92,7 +92,7 @@ func (this *StorageManager) Loop() error {
}
if len(policy.Options) > 0 {
err = json.Unmarshal([]byte(policy.Options), storage.Config())
err = json.Unmarshal(policy.Options, storage.Config())
if err != nil {
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "unmarshal policy '"+types.String(policyId)+"' config failed: "+err.Error())
storage.SetOk(false)
@@ -101,6 +101,7 @@ func (this *StorageManager) Loop() error {
}
storage.SetVersion(types.Int(policy.Version))
storage.SetFirewallOnly(policy.FirewallOnly == 1)
err := storage.Start()
if err != nil {
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "start policy '"+types.String(policyId)+"' failed: "+err.Error())
@@ -110,12 +111,13 @@ func (this *StorageManager) Loop() error {
remotelogs.Println("ACCESS_LOG_STORAGE_MANAGER", "restart policy '"+types.String(policyId)+"'")
}
} else {
storage, err := this.createStorage(policy.Type, []byte(policy.Options))
storage, err := this.createStorage(policy.Type, policy.Options)
if err != nil {
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "create policy '"+types.String(policyId)+"' failed: "+err.Error())
continue
}
storage.SetVersion(types.Int(policy.Version))
storage.SetFirewallOnly(policy.FirewallOnly == 1)
this.storageMap[policyId] = storage
err = storage.Start()
if err != nil {

View File

@@ -1,7 +1,9 @@
package accesslogs
import (
"bytes"
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/logs"
@@ -95,7 +97,10 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
args = append(args, "-S", "10240")
cmd := exec.Command(this.exe, args...)
var cmd = exec.Command(this.exe, args...)
var stderrBuffer = &bytes.Buffer{}
cmd.Stderr = stderrBuffer
w, err := cmd.StdinPipe()
if err != nil {
return err
@@ -106,9 +111,12 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
}
for _, accessLog := range accessLogs {
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
continue
}
data, err := this.Marshal(accessLog)
if err != nil {
logs.Error(err)
remotelogs.Error("ACCESS_LOG_POLICY_SYSLOG", "marshal accesslog failed: "+err.Error())
continue
}
_, err = w.Write(data)
@@ -118,14 +126,15 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
_, err = w.Write([]byte("\n"))
if err != nil {
logs.Error(err)
remotelogs.Error("ACCESS_LOG_POLICY_SYSLOG", "write accesslog failed: "+err.Error())
}
}
_ = w.Close()
err = cmd.Wait()
if err != nil {
return err
return errors.New("send syslog failed: " + err.Error() + ", stderr: " + stderrBuffer.String())
}
return nil

View File

@@ -60,6 +60,9 @@ func (this *TCPStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
defer this.writeLocker.Unlock()
for _, accessLog := range accessLogs {
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
continue
}
data, err := this.Marshal(accessLog)
if err != nil {
logs.Error(err)

View File

@@ -1,51 +1,108 @@
package apps
import (
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/files"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/utils/time"
timeutil "github.com/iwind/TeaGo/utils/time"
"log"
"os"
"runtime"
"strconv"
"strings"
)
type LogWriter struct {
fileAppender *files.Appender
fp *os.File
c chan string
}
func (this *LogWriter) Init() {
// 创建目录
dir := files.NewFile(Tea.LogDir())
var dir = files.NewFile(Tea.LogDir())
if !dir.Exists() {
err := dir.Mkdir()
if err != nil {
log.Println("[error]" + err.Error())
log.Println("[LOG]create log dir failed: " + err.Error())
}
}
logFile := files.NewFile(Tea.LogFile("run.log"))
// 打开要写入的日志文件
appender, err := logFile.Appender()
var logPath = Tea.LogFile("run.log")
fp, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
logs.Error(err)
log.Println("[LOG]open log file failed: " + err.Error())
} else {
this.fileAppender = appender
this.fp = fp
}
this.c = make(chan string, 1024)
// 异步写入文件
var maxFileSize = 2 * sizes.G // 文件最大尺寸,超出此尺寸则清空
if fp != nil {
goman.New(func() {
var totalSize int64 = 0
stat, err := fp.Stat()
if err == nil {
totalSize = stat.Size()
}
for message := range this.c {
totalSize += int64(len(message))
_, err := fp.WriteString(timeutil.Format("Y/m/d H:i:s ") + message + "\n")
if err != nil {
log.Println("[LOG]write log failed: " + err.Error())
} else {
// 如果太大则Truncate
if totalSize > maxFileSize {
_ = fp.Truncate(0)
totalSize = 0
}
}
}
})
}
}
func (this *LogWriter) Write(message string) {
log.Println(message)
backgroundEnv, _ := os.LookupEnv("EdgeBackground")
if backgroundEnv != "on" {
// 文件和行号
var file string
var line int
if Tea.IsTesting() {
var callDepth = 3
var ok bool
_, file, line, ok = runtime.Caller(callDepth)
if ok {
file = this.packagePath(file)
}
}
if this.fileAppender != nil {
_, err := this.fileAppender.AppendString(timeutil.Format("Y/m/d H:i:s ") + message + "\n")
if err != nil {
log.Println("[error]" + err.Error())
if len(file) > 0 {
log.Println(message + " (" + file + ":" + strconv.Itoa(line) + ")")
} else {
log.Println(message)
}
}
this.c <- message
}
func (this *LogWriter) Close() {
if this.fileAppender != nil {
_ = this.fileAppender.Close()
if this.fp != nil {
_ = this.fp.Close()
}
close(this.c)
}
func (this *LogWriter) packagePath(path string) string {
var pieces = strings.Split(path, "/")
if len(pieces) >= 2 {
return strings.Join(pieces[len(pieces)-2:], "/")
}
return path
}

View File

@@ -1,7 +1,7 @@
package teaconst
const (
Version = "0.4.5"
Version = "0.4.9"
ProductName = "Edge API"
ProcessName = "edge-api"
@@ -18,13 +18,13 @@ const (
// 其他节点版本号,用来检测是否有需要升级的节点
NodeVersion = "0.4.5"
UserNodeVersion = "0.3.2"
NodeVersion = "0.4.9"
UserNodeVersion = "0.3.5"
AuthorityNodeVersion = "0.0.2"
MonitorNodeVersion = "0.0.3"
DNSNodeVersion = "0.2.1"
ReportNodeVersion = "0.1.0"
MonitorNodeVersion = "0.0.4"
DNSNodeVersion = "0.2.4"
ReportNodeVersion = "0.1.1"
// SQLVersion SQL版本号
SQLVersion = "5"
SQLVersion = "2"
)

View File

@@ -3,6 +3,7 @@ package db
import (
"database/sql"
"database/sql/driver"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
_ "github.com/iwind/TeaGo/bootstrap"
@@ -42,3 +43,13 @@ func TestDB_Instance(t *testing.T) {
}
time.Sleep(100 * time.Second)
}
func TestDB_Reuse(t *testing.T) {
var dao = models.NewVersionDAO()
for i := 0; i < 20_000; i++ {
_, _, err := dao.Query(nil).Attr("version", i).Reuse(true).FindOne()
if err != nil {
t.Fatal(err)
}
}
}

View File

@@ -2,6 +2,7 @@ package accounts
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
_ "github.com/go-sql-driver/mysql"
@@ -79,7 +80,7 @@ func (this *UserAccountLogDAO) CountAccountLogs(tx *dbs.Tx, userId int64, accoun
}
if len(keyword) > 0 {
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
query.Param("keyword", "%"+keyword+"%")
query.Param("keyword", dbutils.QuoteLike(keyword))
}
if len(eventType) > 0 {
query.Attr("eventType", eventType)
@@ -98,7 +99,7 @@ func (this *UserAccountLogDAO) ListAccountLogs(tx *dbs.Tx, userId int64, account
}
if len(keyword) > 0 {
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
query.Param("keyword", "%"+keyword+"%")
query.Param("keyword", dbutils.QuoteLike(keyword))
}
if len(eventType) > 0 {
query.Attr("eventType", eventType)

View File

@@ -1,19 +1,21 @@
package accounts
import "github.com/iwind/TeaGo/dbs"
// UserAccountLog 用户账户日志
type UserAccountLog struct {
Id uint64 `field:"id"` // ID
UserId uint64 `field:"userId"` // 用户ID
AccountId uint64 `field:"accountId"` // 账户ID
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
Total float64 `field:"total"` // 操作后余额
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
EventType string `field:"eventType"` // 类型
Description string `field:"description"` // 描述文字
Day string `field:"day"` // YYYYMMDD
CreatedAt uint64 `field:"createdAt"` // 时间
Params string `field:"params"` // 参数
Id uint64 `field:"id"` // ID
UserId uint64 `field:"userId"` // 用户ID
AccountId uint64 `field:"accountId"` // 账户ID
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
Total float64 `field:"total"` // 操作后余额
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
EventType string `field:"eventType"` // 类型
Description string `field:"description"` // 描述文字
Day string `field:"day"` // YYYYMMDD
CreatedAt uint64 `field:"createdAt"` // 时间
Params dbs.JSON `field:"params"` // 参数
}
type UserAccountLogOperator struct {

View File

@@ -3,7 +3,7 @@ package acme
// ACMEProviderAccount ACME提供商
type ACMEProviderAccount struct {
Id uint64 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
ProviderCode string `field:"providerCode"` // 代号
Error string `field:"error"` // 最后一条错误信息

View File

@@ -125,11 +125,11 @@ func (this *ACMETaskDAO) CountAllEnabledACMETasks(tx *dbs.Tx, adminId int64, use
if len(keyword) > 0 {
query.Where("(domains LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
if len(keyword) > 0 {
query.Where("domains LIKE :keyword").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
return query.State(ACMETaskStateEnabled).
@@ -155,7 +155,7 @@ func (this *ACMETaskDAO) ListEnabledACMETasks(tx *dbs.Tx, adminId int64, userId
}
if len(keyword) > 0 {
query.Where("(domains LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
_, err = query.
State(ACMETaskStateEnabled).
@@ -271,7 +271,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
errMsg = "找不到要执行的任务"
return
}
if task.IsOn != 1 {
if !task.IsOn {
errMsg = "任务没有启用"
return
}
@@ -330,7 +330,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
})
if len(user.Registration) > 0 {
err = remoteUser.SetRegistration([]byte(user.Registration))
err = remoteUser.SetRegistration(user.Registration)
if err != nil {
errMsg = "设置注册信息时出错:" + err.Error()
return
@@ -453,7 +453,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
return
}
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn == 1, cert.Name, cert.Description, cert.ServerName, cert.IsCA == 1, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn, cert.Name, cert.Description, cert.ServerName, cert.IsCA, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
if err != nil {
errMsg = "证书生成成功,但是修改数据库中的证书信息时出错:" + err.Error()
return

View File

@@ -1,10 +1,10 @@
package acme
// ACME任务运行日志
// ACMETaskLog ACME任务运行日志
type ACMETaskLog struct {
Id uint64 `field:"id"` // ID
TaskId uint64 `field:"taskId"` // 任务ID
IsOk uint8 `field:"isOk"` // 是否成功
IsOk bool `field:"isOk"` // 是否成功
Error string `field:"error"` // 错误信息
CreatedAt uint64 `field:"createdAt"` // 运行时间
}

View File

@@ -1,21 +1,23 @@
package acme
import "github.com/iwind/TeaGo/dbs"
// ACMETask ACME任务
type ACMETask struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
DnsDomain string `field:"dnsDomain"` // DNS主域名
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
Domains string `field:"domains"` // 证书域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
CertId uint64 `field:"certId"` // 生成的证书ID
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
AuthType string `field:"authType"` // 认证类型
AuthURL string `field:"authURL"` // 认证URL
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
DnsDomain string `field:"dnsDomain"` // DNS主域名
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
Domains dbs.JSON `field:"domains"` // 证书域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
CertId uint64 `field:"certId"` // 生成的证书ID
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
AuthType string `field:"authType"` // 认证类型
AuthURL string `field:"authURL"` // 认证URL
}
type ACMETaskOperator struct {

View File

@@ -5,13 +5,13 @@ import (
"github.com/iwind/TeaGo/logs"
)
// 将域名解析成字符串数组
// DecodeDomains 将域名解析成字符串数组
func (this *ACMETask) DecodeDomains() []string {
if len(this.Domains) == 0 || this.Domains == "null" {
if len(this.Domains) == 0 {
return nil
}
result := []string{}
err := json.Unmarshal([]byte(this.Domains), &result)
err := json.Unmarshal(this.Domains, &result)
if err != nil {
logs.Error(err)
return nil

View File

@@ -1,18 +1,20 @@
package acme
import "github.com/iwind/TeaGo/dbs"
// ACMEUser ACME用户
type ACMEUser struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
PrivateKey string `field:"privateKey"` // 私钥
Email string `field:"email"` // E-mail
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 备注介绍
Registration string `field:"registration"` // 注册信息
ProviderCode string `field:"providerCode"` // 服务商代号
AccountId uint64 `field:"accountId"` // 提供商ID
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
PrivateKey string `field:"privateKey"` // 私钥
Email string `field:"email"` // E-mail
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 备注介绍
Registration dbs.JSON `field:"registration"` // 注册信息
ProviderCode string `field:"providerCode"` // 服务商代号
AccountId uint64 `field:"accountId"` // 提供商ID
}
type ACMEUserOperator struct {

View File

@@ -1,19 +1,21 @@
package models
import "github.com/iwind/TeaGo/dbs"
// Admin 管理员
type Admin struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Username string `field:"username"` // 用户名
Password string `field:"password"` // 密码
Fullname string `field:"fullname"` // 全名
IsSuper uint8 `field:"isSuper"` // 是否为超级管理员
CreatedAt uint64 `field:"createdAt"` // 创建时间
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
State uint8 `field:"state"` // 状态
Modules string `field:"modules"` // 允许的模块
CanLogin uint8 `field:"canLogin"` // 是否可以登录
Theme string `field:"theme"` // 模板设置
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Username string `field:"username"` // 用户名
Password string `field:"password"` // 密码
Fullname string `field:"fullname"` // 全名
IsSuper bool `field:"isSuper"` // 是否为超级管理员
CreatedAt uint64 `field:"createdAt"` // 创建时间
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
State uint8 `field:"state"` // 状态
Modules dbs.JSON `field:"modules"` // 允许的模块
CanLogin uint8 `field:"canLogin"` // 是否可以登录
Theme string `field:"theme"` // 模板设置
}
type AdminOperator struct {

View File

@@ -3,6 +3,8 @@ package models
import (
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/configs"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
_ "github.com/go-sql-driver/mysql"
@@ -49,16 +51,29 @@ func (this *APINodeDAO) EnableAPINode(tx *dbs.Tx, id int64) error {
Pk(id).
Set("state", APINodeStateEnabled).
Update()
return err
if err != nil {
return err
}
return this.NotifyUpdate(tx, id)
}
// DisableAPINode 禁用条目
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, nodeId int64) error {
_, err := this.Query(tx).
Pk(id).
Pk(nodeId).
Set("state", APINodeStateDisabled).
Update()
return err
if err != nil {
return err
}
err = this.NotifyUpdate(tx, nodeId)
if err != nil {
return err
}
// 删除运行日志
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleAPI, nodeId)
}
// FindEnabledAPINode 查找启用中的条目
@@ -149,16 +164,33 @@ func (this *APINodeDAO) CreateAPINode(tx *dbs.Tx, name string, description strin
return
}
err = this.NotifyUpdate(tx, types.Int64(op.Id))
if err != nil {
remotelogs.Error("API_NODE_DAO", err.Error())
}
return types.Int64(op.Id), nil
}
// UpdateAPINode 修改API节点
func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, description string, httpJSON []byte, httpsJSON []byte, restIsOn bool, restHTTPJSON []byte, restHTTPSJSON []byte, accessAddrsJSON []byte, isOn bool) error {
func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, description string, httpJSON []byte, httpsJSON []byte, restIsOn bool, restHTTPJSON []byte, restHTTPSJSON []byte, accessAddrsJSON []byte, isOn bool, isPrimary bool) error {
if nodeId <= 0 {
return errors.New("invalid nodeId")
}
op := NewAPINodeOperator()
// 取消别的Primary
if isPrimary {
err := this.Query(tx).
Neq("id", nodeId).
Attr("isPrimary", true).
Set("isPrimary", false).
UpdateQuickly()
if err != nil {
return err
}
}
var op = NewAPINodeOperator()
op.Id = nodeId
op.Name = name
op.Description = description
@@ -191,8 +223,13 @@ func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, des
op.AccessAddrs = "[]"
}
op.IsPrimary = isPrimary
err := this.Save(tx, op)
return err
if err != nil {
return err
}
return this.NotifyUpdate(tx, nodeId)
}
// FindAllEnabledAPINodes 列出所有可用API节点
@@ -294,23 +331,6 @@ func (this *APINodeDAO) UpdateAPINodeStatus(tx *dbs.Tx, apiNodeId int64, statusJ
return err
}
// 生成唯一ID
func (this *APINodeDAO) genUniqueId(tx *dbs.Tx) (string, error) {
for {
uniqueId := rands.HexString(32)
ok, err := this.Query(tx).
Attr("uniqueId", uniqueId).
Exist()
if err != nil {
return "", err
}
if ok {
continue
}
return uniqueId, nil
}
}
// CountAllLowerVersionNodes 计算所有节点中低于某个版本的节点数量
func (this *APINodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
@@ -384,3 +404,114 @@ func (this *APINodeDAO) FindAllEnabledAPIAccessIPs(tx *dbs.Tx, cacheMap *utils.C
return result, nil
}
// CheckAPINodeIsPrimary 检查当前节点是否为Primary节点
func (this *APINodeDAO) CheckAPINodeIsPrimary(tx *dbs.Tx) (bool, error) {
config, err := configs.SharedAPIConfig()
if err != nil {
return false, err
}
isPrimary, err := this.Query(tx).
State(APINodeStateEnabled).
Attr("uniqueId", config.NodeId).
Attr("isPrimary", true).
Exist()
if err != nil {
return false, err
}
if isPrimary {
return true, nil
}
// 检查是否有别的Primary节点
count, err := this.Query(tx).
State(APINodeStateEnabled).
Attr("isOn", true).
Attr("isPrimary", true).
Count()
if err != nil {
return false, err
}
if count == 0 {
err = this.ResetPrimaryAPINode(tx)
if err != nil {
return false, err
}
return true, nil
}
return false, nil
}
// CheckAPINodeIsPrimaryWithoutErr 检查当前节点是否为Primary节点并忽略错误
func (this *APINodeDAO) CheckAPINodeIsPrimaryWithoutErr() bool {
b, err := this.CheckAPINodeIsPrimary(nil)
return b && err == nil
}
// ResetPrimaryAPINode 重置Primary节点
func (this *APINodeDAO) ResetPrimaryAPINode(tx *dbs.Tx) error {
// 当前是否有Primary节点
apiNode, err := this.Query(tx).
State(APINodeStateEnabled).
Attr("isOn", true).
Attr("isPrimary", true).
Find()
if err != nil {
return err
}
if apiNode == nil {
// 选择一个作为Primary
// TODO 将来需要考虑API节点离线的情况
apiNodeId, err := this.Query(tx).
State(APINodeStateEnabled).
Attr("isOn", true).
ResultPk().
FindInt64Col(0)
if err != nil {
return err
}
if apiNodeId > 0 {
err = this.Query(tx).
Pk(apiNodeId).
Set("isPrimary", true).
UpdateQuickly()
if err != nil {
return err
}
}
}
return nil
}
// NotifyUpdate 通知变更
func (this *APINodeDAO) NotifyUpdate(tx *dbs.Tx, apiNodeId int64) error {
// suppress IDE warning
_ = apiNodeId
err := this.ResetPrimaryAPINode(tx)
if err != nil {
return err
}
return nil
}
// 生成唯一ID
func (this *APINodeDAO) genUniqueId(tx *dbs.Tx) (string, error) {
for {
uniqueId := rands.HexString(32)
ok, err := this.Query(tx).
Attr("uniqueId", uniqueId).
Exist()
if err != nil {
return "", err
}
if ok {
continue
}
return uniqueId, nil
}
}

View File

@@ -34,6 +34,16 @@ func TestAPINodeDAO_FindAllEnabledAPIAccessIPs(t *testing.T) {
t.Log(NewAPINodeDAO().FindAllEnabledAPIAccessIPs(nil, cacheMap))
}
func TestAPINodeDAO_CheckAPINodeIsPrimary(t *testing.T) {
var dao = NewAPINodeDAO()
t.Log(dao.CheckAPINodeIsPrimary(nil))
}
func TestAPINodeDAO_ResetPrimaryAPINode(t *testing.T) {
var dao = NewAPINodeDAO()
t.Log(dao.ResetPrimaryAPINode(nil))
}
func BenchmarkAPINodeDAO_New(b *testing.B) {
runtime.GOMAXPROCS(1)
for i := 0; i < b.N; i++ {

View File

@@ -1,26 +1,29 @@
package models
// API节点
import "github.com/iwind/TeaGo/dbs"
// APINode API节点
type APINode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
ClusterId uint32 `field:"clusterId"` // 专用集群ID
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Http string `field:"http"` // 监听的HTTP配置
Https string `field:"https"` // 监听的HTTPS配置
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
RestHTTP string `field:"restHTTP"` // REST HTTP配置
RestHTTPS string `field:"restHTTPS"` // REST HTTPS配置
AccessAddrs string `field:"accessAddrs"` // 外部访问地址
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status string `field:"status"` // 运行状态
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
ClusterId uint32 `field:"clusterId"` // 专用集群ID
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Http dbs.JSON `field:"http"` // 监听的HTTP配置
Https dbs.JSON `field:"https"` // 监听的HTTPS配置
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
RestHTTP dbs.JSON `field:"restHTTP"` // REST HTTP配置
RestHTTPS dbs.JSON `field:"restHTTPS"` // REST HTTPS配置
AccessAddrs dbs.JSON `field:"accessAddrs"` // 外部访问地址
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status dbs.JSON `field:"status"` // 运行状态
IsPrimary bool `field:"isPrimary"` // 是否为主API节点
}
type APINodeOperator struct {
@@ -43,6 +46,7 @@ type APINodeOperator struct {
AdminId interface{} // 管理员ID
Weight interface{} // 权重
Status interface{} // 运行状态
IsPrimary interface{} // 是否为主API节点
}
func NewAPINodeOperator() *APINodeOperator {

View File

@@ -13,7 +13,7 @@ func (this *APINode) DecodeHTTP() (*serverconfigs.HTTPProtocolConfig, error) {
return nil, nil
}
config := &serverconfigs.HTTPProtocolConfig{}
err := json.Unmarshal([]byte(this.Http), config)
err := json.Unmarshal(this.Http, config)
if err != nil {
return nil, err
}
@@ -32,7 +32,7 @@ func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverc
return nil, nil
}
config := &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal([]byte(this.Https), config)
err := json.Unmarshal(this.Https, config)
if err != nil {
return nil, err
}
@@ -70,7 +70,7 @@ func (this *APINode) DecodeAccessAddrs() ([]*serverconfigs.NetworkAddressConfig,
}
addrConfigs := []*serverconfigs.NetworkAddressConfig{}
err := json.Unmarshal([]byte(this.AccessAddrs), &addrConfigs)
err := json.Unmarshal(this.AccessAddrs, &addrConfigs)
if err != nil {
return nil, err
}
@@ -105,7 +105,7 @@ func (this *APINode) DecodeRestHTTP() (*serverconfigs.HTTPProtocolConfig, error)
return nil, nil
}
config := &serverconfigs.HTTPProtocolConfig{}
err := json.Unmarshal([]byte(this.RestHTTP), config)
err := json.Unmarshal(this.RestHTTP, config)
if err != nil {
return nil, err
}
@@ -130,7 +130,7 @@ func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*ser
return nil, nil
}
config := &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal([]byte(this.RestHTTPS), config)
err := json.Unmarshal(this.RestHTTPS, config)
if err != nil {
return nil, err
}

View File

@@ -1,15 +1,17 @@
package authority
import "github.com/iwind/TeaGo/dbs"
// AuthorityKey 企业版认证信息
type AuthorityKey struct {
Id uint32 `field:"id"` // ID
Value string `field:"value"` // Key值
DayFrom string `field:"dayFrom"` // 开始日期
DayTo string `field:"dayTo"` // 结束日期
Hostname string `field:"hostname"` // Hostname
MacAddresses string `field:"macAddresses"` // MAC地址
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
Company string `field:"company"` // 公司组织
Id uint32 `field:"id"` // ID
Value string `field:"value"` // Key值
DayFrom string `field:"dayFrom"` // 开始日期
DayTo string `field:"dayTo"` // 结束日期
Hostname string `field:"hostname"` // Hostname
MacAddresses dbs.JSON `field:"macAddresses"` // MAC地址
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
Company string `field:"company"` // 公司组织
}
type AuthorityKeyOperator struct {

View File

@@ -1,6 +1,7 @@
package authority
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
@@ -188,13 +189,19 @@ func (this *AuthorityNodeDAO) GenUniqueId(tx *dbs.Tx) (string, error) {
}
// UpdateNodeStatus 更改节点状态
func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
if statusJSON == nil {
func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *nodeconfigs.NodeStatus) error {
if nodeStatus == nil {
return nil
}
_, err := this.Query(tx).
nodeStatusJSON, err := json.Marshal(nodeStatus)
if err != nil {
return err
}
_, err = this.Query(tx).
Pk(nodeId).
Set("status", string(statusJSON)).
Set("status", nodeStatusJSON).
Update()
return err
}

View File

@@ -1,19 +1,21 @@
package authority
import "github.com/iwind/TeaGo/dbs"
// AuthorityNode 监控节点
type AuthorityNode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status string `field:"status"` // 运行状态
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status dbs.JSON `field:"status"` // 运行状态
}
type AuthorityNodeOperator struct {

View File

@@ -1,11 +1,13 @@
package models
// 终端浏览器信息
import "github.com/iwind/TeaGo/dbs"
// ClientBrowser 终端浏览器信息
type ClientBrowser struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 浏览器名称
Codes string `field:"codes"` // 代号
State uint8 `field:"state"` // 状态
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 浏览器名称
Codes dbs.JSON `field:"codes"` // 代号
State uint8 `field:"state"` // 状态
}
type ClientBrowserOperator struct {

View File

@@ -1,11 +1,13 @@
package models
// 终端操作系统信息
import "github.com/iwind/TeaGo/dbs"
// ClientSystem 终端操作系统信息
type ClientSystem struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 系统名称
Codes string `field:"codes"` // 代号
State uint8 `field:"state"` //
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 系统名称
Codes dbs.JSON `field:"codes"` // 代号
State uint8 `field:"state"` //
}
type ClientSystemOperator struct {

View File

@@ -4,6 +4,7 @@ import (
"encoding/base64"
"github.com/TeaOSLab/EdgeAPI/internal/encrypt"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
@@ -49,12 +50,17 @@ func (this *DBNodeDAO) EnableDBNode(tx *dbs.Tx, id int64) error {
}
// DisableDBNode 禁用条目
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, id int64) error {
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, nodeId int64) error {
_, err := this.Query(tx).
Pk(id).
Pk(nodeId).
Set("state", DBNodeStateDisabled).
Update()
return err
if err != nil {
return err
}
// 删除运行日志
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleDatabase, nodeId)
}
// FindEnabledDBNode 查找启用中的条目

View File

@@ -56,6 +56,25 @@ func init() {
})
}
func AllAccessLogDBs() []*dbs.DB {
accessLogLocker.Lock()
defer accessLogLocker.Unlock()
var result = []*dbs.DB{}
for _, db := range accessLogDBMapping {
result = append(result, db)
}
if len(result) == 0 {
db, _ := dbs.Default()
if db != nil {
result = append(result, db)
}
}
return result
}
// 获取获取DAO
func randomHTTPAccessLogDAO() (dao *HTTPAccessLogDAOWrapper) {
accessLogLocker.RLock()
@@ -237,7 +256,7 @@ func (this *DBNodeInitializer) loop() error {
}
if db == nil {
config := &dbs.DBConfig{
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: dsn,
Prefix: "edge",
@@ -251,7 +270,7 @@ func (this *DBNodeInitializer) loop() error {
// 检查表是否存在
// httpAccessLog
{
tableDef, err := SharedHTTPAccessLogManager.FindTable(db, timeutil.Format("Ymd"), true)
tableDef, err := SharedHTTPAccessLogManager.FindLastTable(db, timeutil.Format("Ymd"), true)
if err != nil {
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())

View File

@@ -1,9 +1,9 @@
package models
// 数据库节点
// DBNode 数据库节点
type DBNode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
Role string `field:"role"` // 数据库角色
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述

View File

@@ -1,22 +1,24 @@
package dns
import "github.com/iwind/TeaGo/dbs"
// DNSDomain 管理的域名
type DNSDomain struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ProviderId uint32 `field:"providerId"` // 服务商ID
IsOn uint8 `field:"isOn"` // 是否可用
Name string `field:"name"` // 域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
DataError string `field:"dataError"` // 数据更新错误
Data string `field:"data"` // 原始数据信息
Records string `field:"records"` // 所有解析记录
Routes string `field:"routes"` // 线路数据
IsUp uint8 `field:"isUp"` // 是否在线
State uint8 `field:"state"` // 状态
IsDeleted uint8 `field:"isDeleted"` // 是否已删除
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ProviderId uint32 `field:"providerId"` // 服务商ID
IsOn bool `field:"isOn"` // 是否可用
Name string `field:"name"` // 域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
DataError string `field:"dataError"` // 数据更新错误
Data string `field:"data"` // 原始数据信息
Records dbs.JSON `field:"records"` // 所有解析记录
Routes dbs.JSON `field:"routes"` // 线路数据
IsUp bool `field:"isUp"` // 是否在线
State uint8 `field:"state"` // 状态
IsDeleted bool `field:"isDeleted"` // 是否已删除
}
type DNSDomainOperator struct {

View File

@@ -7,11 +7,11 @@ import (
// DecodeRoutes 获取所有的线路
func (this *DNSDomain) DecodeRoutes() ([]*dnstypes.Route, error) {
if len(this.Routes) == 0 || this.Routes == "null" {
if len(this.Routes) == 0 {
return nil, nil
}
result := []*dnstypes.Route{}
err := json.Unmarshal([]byte(this.Routes), &result)
err := json.Unmarshal(this.Routes, &result)
if err != nil {
return nil, err
}
@@ -35,11 +35,11 @@ func (this *DNSDomain) ContainsRouteCode(route string) (bool, error) {
// DecodeRecords 获取所有的记录
func (this *DNSDomain) DecodeRecords() ([]*dnstypes.Record, error) {
records := this.Records
if len(records) == 0 || records == "null" {
if len(records) == 0 {
return nil, nil
}
result := []*dnstypes.Record{}
err := json.Unmarshal([]byte(records), &result)
err := json.Unmarshal(records, &result)
if err != nil {
return nil, err
}

View File

@@ -107,22 +107,39 @@ func (this *DNSProviderDAO) UpdateDNSProvider(tx *dbs.Tx, dnsProviderId int64, n
}
// CountAllEnabledDNSProviders 计算服务商数量
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string) (int64, error) {
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, providerType string) (int64, error) {
var query = dbutils.NewQuery(tx, this, adminId, userId)
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
if len(domain) > 0 {
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
query.Param("domain", domain)
}
if len(providerType) > 0 {
query.Attr("type", providerType)
}
return query.State(DNSProviderStateEnabled).
Count()
}
// ListEnabledDNSProviders 列出单页服务商
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, offset int64, size int64) (result []*DNSProvider, err error) {
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, providerType string, offset int64, size int64) (result []*DNSProvider, err error) {
var query = dbutils.NewQuery(tx, this, adminId, userId)
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
if len(domain) > 0 {
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
query.Param("domain", domain)
}
if len(providerType) > 0 {
query.Attr("type", providerType)
}
_, err = query.
State(DNSProviderStateEnabled).

View File

@@ -1,16 +1,18 @@
package dns
// DNS服务商
import "github.com/iwind/TeaGo/dbs"
// DNSProvider DNS服务商
type DNSProvider struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Type string `field:"type"` // 供应商类型
ApiParams string `field:"apiParams"` // API参数
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Type string `field:"type"` // 供应商类型
ApiParams dbs.JSON `field:"apiParams"` // API参数
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
}
type DNSProviderOperator struct {

View File

@@ -5,12 +5,12 @@ import (
"github.com/iwind/TeaGo/maps"
)
// 获取API参数
// DecodeAPIParams 获取API参数
func (this *DNSProvider) DecodeAPIParams() (maps.Map, error) {
if len(this.ApiParams) == 0 || this.ApiParams == "null" {
if len(this.ApiParams) == 0 {
return maps.Map{}, nil
}
result := maps.Map{}
err := json.Unmarshal([]byte(this.ApiParams), &result)
err := json.Unmarshal(this.ApiParams, &result)
return result, err
}

View File

@@ -12,10 +12,11 @@ import (
type DNSTaskType = string
const (
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
DNSTaskTypeServerChange DNSTaskType = "serverChange"
DNSTaskTypeDomainChange DNSTaskType = "domainChange"
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
DNSTaskTypeClusterRemoveDomain DNSTaskType = "clusterRemoveDomain" // 从集群中移除域名
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
DNSTaskTypeServerChange DNSTaskType = "serverChange"
DNSTaskTypeDomainChange DNSTaskType = "domainChange"
)
type DNSTaskDAO dbs.DAO
@@ -40,20 +41,21 @@ func init() {
}
// CreateDNSTask 生成任务
func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int64, nodeId int64, domainId int64, taskType string) error {
func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int64, nodeId int64, domainId int64, recordName string, taskType string) error {
if clusterId <= 0 && serverId <= 0 && nodeId <= 0 && domainId <= 0 {
return nil
}
err := this.Query(tx).InsertOrUpdateQuickly(maps.Map{
"clusterId": clusterId,
"serverId": serverId,
"nodeId": nodeId,
"domainId": domainId,
"updatedAt": time.Now().Unix(),
"type": taskType,
"isDone": false,
"isOk": false,
"error": "",
"clusterId": clusterId,
"serverId": serverId,
"nodeId": nodeId,
"domainId": domainId,
"recordName": recordName,
"updatedAt": time.Now().Unix(),
"type": taskType,
"isDone": false,
"isOk": false,
"error": "",
}, maps.Map{
"updatedAt": time.Now().Unix(),
"isDone": false,
@@ -63,24 +65,29 @@ func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int6
return err
}
// CreateClusterTask 生成集群任务
// CreateClusterTask 生成集群变更任务
func (this *DNSTaskDAO) CreateClusterTask(tx *dbs.Tx, clusterId int64, taskType DNSTaskType) error {
return this.CreateDNSTask(tx, clusterId, 0, 0, 0, taskType)
return this.CreateDNSTask(tx, clusterId, 0, 0, 0, "", taskType)
}
// CreateClusterRemoveTask 生成集群删除域名任务
func (this *DNSTaskDAO) CreateClusterRemoveTask(tx *dbs.Tx, clusterId int64, domainId int64, recordName string) error {
return this.CreateDNSTask(tx, clusterId, 0, 0, domainId, recordName, DNSTaskTypeClusterRemoveDomain)
}
// CreateNodeTask 生成节点任务
func (this *DNSTaskDAO) CreateNodeTask(tx *dbs.Tx, nodeId int64, taskType DNSTaskType) error {
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, taskType)
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, "", taskType)
}
// CreateServerTask 生成服务任务
func (this *DNSTaskDAO) CreateServerTask(tx *dbs.Tx, serverId int64, taskType DNSTaskType) error {
return this.CreateDNSTask(tx, 0, serverId, 0, 0, taskType)
func (this *DNSTaskDAO) CreateServerTask(tx *dbs.Tx, clusterId int64, serverId int64, taskType DNSTaskType) error {
return this.CreateDNSTask(tx, clusterId, serverId, 0, 0, "", taskType)
}
// CreateDomainTask 生成域名更新任务
func (this *DNSTaskDAO) CreateDomainTask(tx *dbs.Tx, domainId int64, taskType DNSTaskType) error {
return this.CreateDNSTask(tx, 0, 0, 0, domainId, taskType)
return this.CreateDNSTask(tx, 0, 0, 0, domainId, "", taskType)
}
// FindAllDoingTasks 查找所有正在执行的任务
@@ -101,6 +108,7 @@ func (this *DNSTaskDAO) FindAllDoingOrErrorTasks(tx *dbs.Tx, nodeClusterId int64
}
_, err = query.
Where("(isDone=0 OR (isDone=1 AND isOk=0))").
Asc("updatedAt").
AscPk().
Slice(&result).
FindAll()

View File

@@ -1,30 +1,32 @@
package dns
// DNS更新任务
// DNSTask DNS更新任务
type DNSTask struct {
Id uint64 `field:"id"` // ID
ClusterId uint32 `field:"clusterId"` // 集群ID
ServerId uint32 `field:"serverId"` // 服务ID
NodeId uint32 `field:"nodeId"` // 节点ID
DomainId uint32 `field:"domainId"` // 域名ID
Type string `field:"type"` // 任务类型
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
IsDone uint8 `field:"isDone"` // 是否已完成
IsOk uint8 `field:"isOk"` // 是否成
Error string `field:"error"` // 错误信息
Id uint64 `field:"id"` // ID
ClusterId uint32 `field:"clusterId"` // 集群ID
ServerId uint32 `field:"serverId"` // 服务ID
NodeId uint32 `field:"nodeId"` // 节点ID
DomainId uint32 `field:"domainId"` // 域名ID
RecordName string `field:"recordName"` // 记录名
Type string `field:"type"` // 任务类型
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
IsDone bool `field:"isDone"` // 是否已完
IsOk bool `field:"isOk"` // 是否成功
Error string `field:"error"` // 错误信息
}
type DNSTaskOperator struct {
Id interface{} // ID
ClusterId interface{} // 集群ID
ServerId interface{} // 服务ID
NodeId interface{} // 节点ID
DomainId interface{} // 域名ID
Type interface{} // 任务类型
UpdatedAt interface{} // 更新时间
IsDone interface{} // 是否已完成
IsOk interface{} // 是否成
Error interface{} // 错误信息
Id interface{} // ID
ClusterId interface{} // 集群ID
ServerId interface{} // 服务ID
NodeId interface{} // 节点ID
DomainId interface{} // 域名ID
RecordName interface{} // 记录名
Type interface{} // 任务类型
UpdatedAt interface{} // 更新时间
IsDone interface{} // 是否已完
IsOk interface{} // 是否成功
Error interface{} // 错误信息
}
func NewDNSTaskOperator() *DNSTaskOperator {

View File

@@ -153,7 +153,7 @@ func CheckClusterDNS(tx *dbs.Tx, cluster *models.NodeCluster) (issues []*pb.DNSI
}
// 检查IP地址
ipAddr, _, err := models.SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddress(tx, nodeId, nodeconfigs.NodeRoleNode)
ipAddr, _, err := models.SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddress(tx, nodeId, true, nodeconfigs.NodeRoleNode)
if err != nil {
return nil, err
}

View File

@@ -4,7 +4,7 @@ package models
type FileChunk struct {
Id uint32 `field:"id"` // ID
FileId uint32 `field:"fileId"` // 文件ID
Data string `field:"data"` // 分块内容
Data []byte `field:"data"` // 分块内容
}
type FileChunkOperator struct {

View File

@@ -1,6 +1,7 @@
package models
import (
"github.com/TeaOSLab/EdgeAPI/internal/utils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
@@ -33,7 +34,7 @@ func init() {
})
}
// 启用条目
// EnableFile 启用条目
func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
@@ -42,7 +43,7 @@ func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
return err
}
// 禁用条目
// DisableFile 禁用条目
func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
@@ -51,7 +52,7 @@ func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
return err
}
// 查找启用中的条目
// FindEnabledFile 查找启用中的条目
func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
result, err := this.Query(tx).
Pk(id).
@@ -63,9 +64,9 @@ func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
return result.(*File), err
}
// 创建文件
// CreateFile 创建文件
func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, businessType, description string, filename string, size int64, isPublic bool) (int64, error) {
op := NewFileOperator()
var op = NewFileOperator()
op.AdminId = adminId
op.UserId = userId
op.Type = businessType
@@ -74,6 +75,7 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
op.Size = size
op.Filename = filename
op.IsPublic = isPublic
op.Code = utils.Sha1RandomString()
err := this.Save(tx, op)
if err != nil {
return 0, err
@@ -82,7 +84,7 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
return types.Int64(op.Id), nil
}
// 将文件置为已完成
// UpdateFileIsFinished 将文件置为已完成
func (this *FileDAO) UpdateFileIsFinished(tx *dbs.Tx, fileId int64) error {
_, err := this.Query(tx).
Pk(fileId).

View File

@@ -1,9 +1,10 @@
package models
// 文件管理
// File 文件管理
type File struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
Code string `field:"code"` // 代号
UserId uint32 `field:"userId"` // 用户ID
Description string `field:"description"` // 文件描述
Filename string `field:"filename"` // 文件名
@@ -12,13 +13,14 @@ type File struct {
Order uint32 `field:"order"` // 排序
Type string `field:"type"` // 类型
State uint8 `field:"state"` // 状态
IsFinished uint8 `field:"isFinished"` // 是否已完成上传
IsPublic uint8 `field:"isPublic"` // 是否可以公开访问
IsFinished bool `field:"isFinished"` // 是否已完成上传
IsPublic bool `field:"isPublic"` // 是否可以公开访问
}
type FileOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
Code interface{} // 代号
UserId interface{} // 用户ID
Description interface{} // 文件描述
Filename interface{} // 文件名

View File

@@ -3,6 +3,7 @@ package models
import (
"bytes"
"encoding/json"
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
@@ -22,6 +23,7 @@ import (
timeutil "github.com/iwind/TeaGo/utils/time"
"net"
"net/http"
"net/url"
"regexp"
"sort"
"strings"
@@ -180,8 +182,8 @@ Loop:
// CreateHTTPAccessLog 写入单条访问日志
func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLogDAO, accessLog *pb.HTTPAccessLog) error {
var day = timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
tableDef, err := SharedHTTPAccessLogManager.FindTable(dao.Instance, day, true)
var day = timeutil.FormatTime("Ymd", accessLog.Timestamp)
tableDef, err := SharedHTTPAccessLogManager.FindLastTable(dao.Instance, day, true)
if err != nil {
return err
}
@@ -221,10 +223,26 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
Sets(fields).
Insert()
if err != nil {
return err
// 错误重试
if CheckSQLErrCode(err, 1146) { // Error 1146: Table 'xxx' doesn't exist
err = SharedHTTPAccessLogManager.CreateTable(dao.Instance, tableDef.Name)
if err != nil {
return err
}
// 重新尝试
lastId, err = dao.Query(tx).
Table(tableDef.Name).
Sets(fields).
Insert()
}
if err != nil {
return err
}
}
if accessLogEnableAutoPartial && accessLogRowsPerTable > 0 && lastId%accessLogRowsPerTable == 0 {
if accessLogEnableAutoPartial && accessLogRowsPerTable > 0 && lastId >= accessLogRowsPerTable {
SharedHTTPAccessLogManager.ResetTable(dao.Instance, day)
}
@@ -232,7 +250,9 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
}
// ListAccessLogs 读取往前的 单页访问日志
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx,
partition int32,
lastRequestId string,
size int64,
day string,
hourFrom string,
@@ -259,18 +279,19 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
size = 1000
}
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
result, nextLastRequestId, err = this.listAccessLogs(tx, partition, lastRequestId, size, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
if err != nil || int64(len(result)) < size {
return
}
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
moreResult, _, _ := this.listAccessLogs(tx, partition, nextLastRequestId, 1, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
hasMore = len(moreResult) > 0
return
}
// 读取往前的单页访问日志
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
partition int32,
lastRequestId string,
size int64,
day string,
@@ -293,7 +314,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
return nil, lastRequestId, nil
}
serverIds := []int64{}
var serverIds = []int64{}
if userId > 0 {
serverIds, err = SharedServerDAO.FindAllEnabledServerIdsWithUserId(tx, userId)
if err != nil {
@@ -305,7 +326,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
}
accessLogLocker.RLock()
daoList := []*HTTPAccessLogDAOWrapper{}
var daoList = []*HTTPAccessLogDAOWrapper{}
for _, daoWrapper := range httpAccessLogDAOMapping {
daoList = append(daoList, daoWrapper)
}
@@ -323,7 +344,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
if clusterId > 0 {
nodeIds, err = SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
if err != nil {
remotelogs.Error("DBNODE", err.Error())
remotelogs.Error("DB_NODE", err.Error())
return
}
sort.Slice(nodeIds, func(i, j int) bool {
@@ -333,32 +354,61 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
// 准备查询
var tableQueries = []*accessLogTableQuery{}
var maxTableName = ""
for _, daoWrapper := range daoList {
var instance = daoWrapper.DAO.Instance
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
def, err := SharedHTTPAccessLogManager.FindPartitionTable(instance, day, partition)
if err != nil {
return nil, "", err
}
for _, def := range tableDefs {
tableQueries = append(tableQueries, &accessLogTableQuery{
daoWrapper: daoWrapper,
name: def.Name,
hasRemoteAddrField: def.HasRemoteAddr,
hasDomainField: def.HasDomain,
})
if !def.Exists {
continue
}
if len(maxTableName) == 0 || def.Name > maxTableName {
maxTableName = def.Name
}
tableQueries = append(tableQueries, &accessLogTableQuery{
daoWrapper: daoWrapper,
name: def.Name,
hasRemoteAddrField: def.HasRemoteAddr,
hasDomainField: def.HasDomain,
})
}
// 检查各个分表是否一致
if partition < 0 {
var newTableQueries = []*accessLogTableQuery{}
for _, tableQuery := range tableQueries {
if tableQuery.name != maxTableName {
continue
}
newTableQueries = append(newTableQueries, tableQuery)
}
tableQueries = newTableQueries
}
if len(tableQueries) == 0 {
return nil, "", nil
}
var locker = sync.Mutex{}
// 这里正则表达式中的括号不能轻易变更,因为后面有引用
// TODO 支持多个查询条件的组合,比如 status:200 proto:HTTP/1.1
var statusPrefixReg = regexp.MustCompile(`status:\s*(\d{3})\b`)
var statusRangeReg = regexp.MustCompile(`status:\s*(\d{3})-(\d{3})\b`)
var urlReg = regexp.MustCompile(`^(http|https)://`)
var requestPathReg = regexp.MustCompile(`requestPath:(\S+)`)
var protoReg = regexp.MustCompile(`proto:(\S+)`)
var schemeReg = regexp.MustCompile(`scheme:(\S+)`)
var count = len(tableQueries)
var wg = &sync.WaitGroup{}
wg.Add(count)
for _, tableQuery := range tableQueries {
go func(tableQuery *accessLogTableQuery) {
go func(tableQuery *accessLogTableQuery, keyword string) {
defer wg.Done()
var dao = tableQuery.daoWrapper.DAO
@@ -446,27 +496,53 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
}
if len(keyword) > 0 {
// remoteAddr
if tableQuery.hasRemoteAddrField && net.ParseIP(keyword) != nil {
var isSpecialKeyword = false
if tableQuery.hasRemoteAddrField && net.ParseIP(keyword) != nil { // ip
isSpecialKeyword = true
query.Attr("remoteAddr", keyword)
} else if tableQuery.hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
} else if tableQuery.hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) { // ip:x.x.x.x
isSpecialKeyword = true
keyword = keyword[3:]
pieces := strings.SplitN(keyword, ",", 2)
if len(pieces) == 1 || len(pieces[1]) == 0 {
if len(pieces) == 1 || len(pieces[1]) == 0 || pieces[0] == pieces[1] {
query.Attr("remoteAddr", pieces[0])
} else {
query.Between("INET_ATON(remoteAddr)", utils.IP2Long(pieces[0]), utils.IP2Long(pieces[1]))
}
} else if statusRangeReg.MatchString(keyword) {
} else if statusRangeReg.MatchString(keyword) { // status:200-400
isSpecialKeyword = true
var matches = statusRangeReg.FindStringSubmatch(keyword)
query.Between("status", types.Int(matches[1]), types.Int(matches[2]))
// TODO 处理剩余的关键词
} else if statusPrefixReg.MatchString(keyword) {
} else if statusPrefixReg.MatchString(keyword) { // status:200
isSpecialKeyword = true
var matches = statusPrefixReg.FindStringSubmatch(keyword)
query.Attr("status", matches[1])
// TODO 处理剩余的关键词
} else {
} else if requestPathReg.MatchString(keyword) {
isSpecialKeyword = true
var matches = requestPathReg.FindStringSubmatch(keyword)
query.Where("JSON_EXTRACT(content, '$.requestPath')=:keyword").
Param("keyword", matches[1])
} else if protoReg.MatchString(keyword) {
isSpecialKeyword = true
var matches = protoReg.FindStringSubmatch(keyword)
query.Where("JSON_EXTRACT(content, '$.proto')=:keyword").
Param("keyword", strings.ToUpper(matches[1]))
} else if schemeReg.MatchString(keyword) {
isSpecialKeyword = true
var matches = schemeReg.FindStringSubmatch(keyword)
query.Where("JSON_EXTRACT(content, '$.scheme')=:keyword").
Param("keyword", strings.ToLower(matches[1]))
} else if urlReg.MatchString(keyword) { // https://xxx/yyy
u, err := url.Parse(keyword)
if err == nil {
isSpecialKeyword = true
query.Attr("domain", u.Host)
query.Where("JSON_EXTRACT(content, '$.requestURI') LIKE :keyword").
Param("keyword", dbutils.QuoteLikePrefix("\""+u.RequestURI()))
}
}
if !isSpecialKeyword {
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
keyword = keyword[3:]
}
@@ -514,7 +590,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
}
query.Where("("+where+")").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
if useOriginKeyword {
query.Param("originKeyword", keyword)
}
@@ -558,17 +634,17 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
Limit(size).
FindAll()
if err != nil {
logs.Println("[DB_NODE]" + err.Error())
remotelogs.Println("DB_NODE", err.Error())
return
}
locker.Lock()
for _, one := range ones {
accessLog := one.(*HTTPAccessLog)
var accessLog = one.(*HTTPAccessLog)
result = append(result, accessLog)
}
locker.Unlock()
}(tableQuery)
}(tableQuery, keyword)
}
wg.Wait()

View File

@@ -1,6 +1,7 @@
package models
import (
"encoding/json"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
@@ -53,7 +54,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
t.Fatal(err)
}
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, "", 10, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
if err != nil {
t.Fatal(err)
}
@@ -80,7 +81,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page(t *testing.T) {
times := 0 // 防止循环次数太多
for {
before := time.Now()
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, lastRequestId, 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
cost := time.Since(before).Seconds()
if err != nil {
t.Fatal(err)
@@ -111,7 +112,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
}
before := time.Now()
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
cost := time.Since(before).Seconds()
if err != nil {
t.Fatal(err)
@@ -136,7 +137,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
times := 0 // 防止循环次数太多
for {
before := time.Now()
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
cost := time.Since(before).Seconds()
if err != nil {
t.Fatal(err)
@@ -157,3 +158,13 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
}
}
}
func BenchmarkHTTPAccessLogDAO_JSONEncode(b *testing.B) {
var accessLog = &pb.HTTPAccessLog{
RequestPath: "/hello/world",
}
for i := 0; i < b.N; i++ {
_, _ = json.Marshal(accessLog)
}
}

View File

@@ -5,7 +5,6 @@ package models
import (
"fmt"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
@@ -16,6 +15,7 @@ import (
)
// 访问日志的两个表格形式
// 括号位置需要固定,会用来读取日期和分区
var accessLogTableMainReg = regexp.MustCompile(`_(\d{8})$`)
var accessLogTablePartialReg = regexp.MustCompile(`_(\d{8})_(\d{4})$`)
@@ -39,7 +39,7 @@ func (this *HTTPAccessLogManager) FindTableNames(db *dbs.DB, day string) ([]stri
// 需要防止用户设置了表名自动小写
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
ones, columnNames, err := db.FindOnes(`SHOW TABLES LIKE '` + prefix + `'`)
ones, columnNames, err := db.FindPreparedOnes(`SHOW TABLES LIKE '` + prefix + `'`)
if err != nil {
return nil, errors.New("query table names error: " + err.Error())
}
@@ -60,7 +60,15 @@ func (this *HTTPAccessLogManager) FindTableNames(db *dbs.DB, day string) ([]stri
}
// 排序
sort.Strings(results)
// 这里不能直接使用sort.Strings(),因为表名里面可能大小写混合
sort.Slice(results, func(i, j int) bool {
var name1 = results[i]
var name2 = results[j]
if len(name1) < len(name2) {
return true
}
return strings.ToLower(name1) < strings.ToLower(name2)
})
return results, nil
}
@@ -70,9 +78,15 @@ func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAcc
var results = []*httpAccessLogDefinition{}
var tableNames = []string{}
config, err := db.Config()
if err != nil {
return nil, err
}
var cachePrefix = config.Dsn
// 需要防止用户设置了表名自动小写
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
ones, columnNames, err := db.FindOnes(`SHOW TABLES LIKE '` + prefix + `'`)
ones, columnNames, err := db.FindPreparedOnes(`SHOW TABLES LIKE '` + prefix + `'`)
if err != nil {
return nil, errors.New("query table names error: " + err.Error())
}
@@ -89,17 +103,32 @@ func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAcc
if accessLogTableMainReg.MatchString(tableName) {
tableNames = append(tableNames, tableName)
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, tableName)
if err != nil {
return nil, err
}
// 查找已有的表格信息避免SHOW FIELDS
var tableDay = tableName[strings.LastIndex(tableName, "_")+1:]
var cacheKey = this.composeTableCacheKey(cachePrefix, tableDay)
this.locker.Lock()
currentTableDef, ok := this.currentTableMapping[cacheKey]
this.locker.Unlock()
if ok {
results = append(results, &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: currentTableDef.HasRemoteAddr,
HasDomain: currentTableDef.HasDomain,
Exists: true,
})
} else {
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, tableName)
if err != nil {
return nil, err
}
results = append(results, &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: hasRemoteAddrField,
HasDomain: hasDomainField,
Exists: true,
})
results = append(results, &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: hasRemoteAddrField,
HasDomain: hasDomainField,
Exists: true,
})
}
} else if accessLogTablePartialReg.MatchString(tableName) {
tableNames = append(tableNames, tableName)
@@ -121,11 +150,55 @@ func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAcc
return results, nil
}
// FindTable 根据日期获取表名
func (this *HTTPAccessLogManager) FindPartitionTable(db *dbs.DB, day string, partition int32) (*httpAccessLogDefinition, error) {
var tableNames []string
if partition < 0 {
tableList, err := this.FindTables(db, day)
if err != nil {
return nil, err
}
if len(tableList) > 0 {
return tableList[len(tableList)-1], nil
}
return &httpAccessLogDefinition{
Name: "",
HasRemoteAddr: false,
HasDomain: false,
Exists: false,
}, nil
} else if partition == 0 {
tableNames = []string{"edgeHTTPAccessLogs_" + day, "edgehttpaccesslogs_" + day}
} else {
tableNames = []string{"edgeHTTPAccessLogs_" + day + "_" + fmt.Sprintf("%04d", partition), "edgehttpaccesslogs_" + day + "_" + fmt.Sprintf("%04d", partition)}
}
for _, tableName := range tableNames {
hasRemoteField, hasDomainField, err := this.checkTableFields(db, tableName)
if err != nil {
continue
}
return &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: hasRemoteField,
HasDomain: hasDomainField,
Exists: true,
}, nil
}
return &httpAccessLogDefinition{
Name: "",
HasRemoteAddr: false,
HasDomain: false,
Exists: false,
}, nil
}
// FindLastTable 根据日期获取上一个可以使用的表名
// 表名组成
// - PREFIX_DAY
// - PREFIX_DAY_0001
func (this *HTTPAccessLogManager) FindTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
func (this *HTTPAccessLogManager) FindLastTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
this.locker.Lock()
defer this.locker.Unlock()
@@ -133,7 +206,8 @@ func (this *HTTPAccessLogManager) FindTable(db *dbs.DB, day string, force bool)
if err != nil {
return nil, err
}
var cacheKey = config.Dsn
var cachePrefix = config.Dsn
var cacheKey = this.composeTableCacheKey(cachePrefix, day)
def, ok := this.currentTableMapping[cacheKey]
if ok {
return def, nil
@@ -144,7 +218,22 @@ func (this *HTTPAccessLogManager) FindTable(db *dbs.DB, day string, force bool)
return nil, err
}
this.currentTableMapping[cacheKey] = def
// 只有存在的表格才缓存
if def != nil && def.Exists {
this.currentTableMapping[cacheKey] = def
// 清除过时缓存
for oldCacheKey := range this.currentTableMapping {
var dayIndex = strings.LastIndex(oldCacheKey, "_")
if dayIndex > 0 {
var oldPrefix = oldCacheKey[:dayIndex]
var oldDay = oldCacheKey[dayIndex+1:]
if oldPrefix == cachePrefix && oldDay < day {
delete(this.currentTableMapping, oldCacheKey)
}
}
}
}
return def, nil
}
@@ -152,14 +241,7 @@ func (this *HTTPAccessLogManager) FindTable(db *dbs.DB, day string, force bool)
func (this *HTTPAccessLogManager) CreateTable(db *dbs.DB, tableName string) error {
_, err := db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
if err != nil {
// 快速判断错误方法
mysqlErr, ok := err.(*mysql.MySQLError)
if ok && mysqlErr.Number == 1050 { // Error 1050: Table 'xxx' already exists
return nil
}
// 防止二次包装过程中错误丢失的保底错误判断方法
if strings.Contains(err.Error(), "Error 1050") {
if CheckSQLErrCode(err, 1050) { // Error 1050: Table 'xxx' already exists
return nil
}
@@ -178,7 +260,61 @@ func (this *HTTPAccessLogManager) ResetTable(db *dbs.DB, day string) {
if err != nil {
return
}
delete(this.currentTableMapping, config.Dsn)
delete(this.currentTableMapping, this.composeTableCacheKey(config.Dsn, day))
}
// TablePartition 从表名中获取分区
func (this *HTTPAccessLogManager) TablePartition(tableName string) (partition int32) {
if accessLogTablePartialReg.MatchString(tableName) {
return types.Int32(accessLogTablePartialReg.FindStringSubmatch(tableName)[2])
}
return 0
}
// FindLatestPartition 读取最后一个分区
func (this *HTTPAccessLogManager) FindLatestPartition(day string) (int32, error) {
var dbList = AllAccessLogDBs()
if len(dbList) == 0 {
return 0, errors.New("no valid database")
}
var partitions = []int32{}
var locker sync.Mutex
var wg = sync.WaitGroup{}
wg.Add(len(dbList))
var lastErr error
for _, db := range dbList {
go func(db *dbs.DB) {
defer wg.Done()
names, err := this.FindTableNames(db, day)
if err != nil {
lastErr = err
}
for _, name := range names {
var partition = this.TablePartition(name)
locker.Lock()
if !lists.Contains(partitions, partition) {
partitions = append(partitions, partition)
}
locker.Unlock()
}
}(db)
}
wg.Wait()
if lastErr != nil {
return 0, lastErr
}
if len(partitions) == 0 {
return 0, nil
}
return partitions[len(partitions)-1], nil
}
// 查找某个表格
@@ -280,7 +416,7 @@ func (this *HTTPAccessLogManager) findTableWithoutCache(db *dbs.DB, day string,
// TODO 考虑缓存检查结果
func (this *HTTPAccessLogManager) checkTableFields(db *dbs.DB, tableName string) (hasRemoteAddrField bool, hasDomainField bool, err error) {
fields, _, err := db.FindOnes("SHOW FIELDS FROM " + tableName)
fields, _, err := db.FindPreparedOnes("SHOW FIELDS FROM " + tableName)
if err != nil {
return false, false, err
}
@@ -295,3 +431,9 @@ func (this *HTTPAccessLogManager) checkTableFields(db *dbs.DB, tableName string)
}
return
}
// 组合表格的缓存Key
func (this *HTTPAccessLogManager) composeTableCacheKey(dsn string, day string) string {
// 注意:格式一定要固定,下面清除缓存的时候需要用到
return dsn + "_" + day
}

View File

@@ -6,6 +6,7 @@ import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/iwind/TeaGo/dbs"
timeutil "github.com/iwind/TeaGo/utils/time"
"testing"
"time"
)
@@ -30,6 +31,9 @@ func TestNewHTTPAccessLogManager(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer func() {
_ = db.Close()
}()
var manager = models.SharedHTTPAccessLogManager
err = manager.CreateTable(db, "accessLog_1")
@@ -58,6 +62,9 @@ func TestHTTPAccessLogManager_FindTableNames(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer func() {
_ = db.Close()
}()
for i := 0; i < 3; i++ {
var before = time.Now()
@@ -74,7 +81,6 @@ func TestHTTPAccessLogManager_FindTableNames(t *testing.T) {
}
}
func TestHTTPAccessLogManager_FindTables(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
@@ -95,6 +101,9 @@ func TestHTTPAccessLogManager_FindTables(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer func() {
_ = db.Close()
}()
for i := 0; i < 3; i++ {
var before = time.Now()
@@ -111,7 +120,7 @@ func TestHTTPAccessLogManager_FindTables(t *testing.T) {
}
}
func TestHTTPAccessLogManager_FindTable(t *testing.T) {
func TestHTTPAccessLogManager_FindLastTable(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
@@ -131,10 +140,13 @@ func TestHTTPAccessLogManager_FindTable(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer func() {
_ = db.Close()
}()
for i := 0; i < 3; i++ {
var before = time.Now()
tableDef, err := models.SharedHTTPAccessLogManager.FindTable(db, "20220306", false)
tableDef, err := models.SharedHTTPAccessLogManager.FindLastTable(db, "20220306", false)
if err != nil {
t.Fatal(err)
}
@@ -146,3 +158,32 @@ func TestHTTPAccessLogManager_FindTable(t *testing.T) {
t.Log(time.Since(before).Seconds()*1000, "ms")
}
}
func TestHTTPAccessLogManager_FindPartitionTable(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
Prefix: "edge",
Connections: struct {
Pool int `yaml:"pool"`
Max int `yaml:"max"`
Life string `yaml:"life"`
LifeDuration time.Duration `yaml:",omitempty"`
}{},
Models: struct {
Package string `yaml:"package"`
}{},
}
db, err := dbs.NewInstanceFromConfig(config)
if err != nil {
t.Fatal(err)
}
defer func() {
_ = db.Close()
}()
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), -1))
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), 0))
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), 1))
}

View File

@@ -1,22 +1,24 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPAccessLog 访问日志
type HTTPAccessLog struct {
Id uint64 `field:"id"` // ID
ServerId uint32 `field:"serverId"` // 服务ID
NodeId uint32 `field:"nodeId"` // 节点ID
Status uint32 `field:"status"` // 状态码
CreatedAt uint64 `field:"createdAt"` // 创建时间
Content string `field:"content"` // 日志内容
RequestId string `field:"requestId"` // 请求ID
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
RemoteAddr string `field:"remoteAddr"` // IP地址
Domain string `field:"domain"` // 域名
RequestBody string `field:"requestBody"` // 请求内容
ResponseBody string `field:"responseBody"` // 响应内容
Id uint64 `field:"id"` // ID
ServerId uint32 `field:"serverId"` // 服务ID
NodeId uint32 `field:"nodeId"` // 节点ID
Status uint32 `field:"status"` // 状态码
CreatedAt uint64 `field:"createdAt"` // 创建时间
Content dbs.JSON `field:"content"` // 日志内容
RequestId string `field:"requestId"` // 请求ID
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
RemoteAddr string `field:"remoteAddr"` // IP地址
Domain string `field:"domain"` // 域名
RequestBody []byte `field:"requestBody"` // 请求内容
ResponseBody []byte `field:"responseBody"` // 响应内容
}
type HTTPAccessLogOperator struct {

View File

@@ -8,11 +8,11 @@ import (
// ToPB 转换成PB对象
func (this *HTTPAccessLog) ToPB() (*pb.HTTPAccessLog, error) {
p := &pb.HTTPAccessLog{}
err := json.Unmarshal([]byte(this.Content), p)
err := json.Unmarshal(this.Content, p)
if err != nil {
return nil, err
}
p.RequestId = this.RequestId
p.RequestBody = []byte(this.RequestBody)
p.RequestBody = this.RequestBody
return p, nil
}

View File

@@ -1,13 +1,10 @@
package models
import (
"bytes"
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
)
const (
@@ -109,7 +106,7 @@ func (this *HTTPAccessLogPolicyDAO) FindAllEnabledAndOnPolicies(tx *dbs.Tx) (res
}
// CreatePolicy 创建策略
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool) (policyId int64, err error) {
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool, firewallOnly bool) (policyId int64, err error) {
var op = NewHTTPAccessLogPolicyOperator()
op.Name = name
op.Type = policyType
@@ -121,12 +118,13 @@ func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policy
}
op.IsPublic = isPublic
op.IsOn = true
op.FirewallOnly = firewallOnly
op.State = HTTPAccessLogPolicyStateEnabled
return this.SaveInt64(tx, op)
}
// UpdatePolicy 修改策略
func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, name string, optionsJSON []byte, condsJSON []byte, isPublic bool, isOn bool) error {
func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, name string, optionsJSON []byte, condsJSON []byte, isPublic bool, firewallOnly bool, isOn bool) error {
if policyId <= 0 {
return errors.New("invalid policyId")
}
@@ -140,7 +138,6 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
if oldOne == nil {
return nil
}
var oldPolicy = oldOne.(*HTTPAccessLogPolicy)
var op = NewHTTPAccessLogPolicyOperator()
op.Id = policyId
@@ -156,22 +153,11 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
op.Conds = "{}"
}
// 版本号
if len(oldPolicy.Options) == 0 || len(optionsJSON) == 0 {
op.Version = dbs.SQL("version+1")
} else {
var m1 = maps.Map{}
_ = json.Unmarshal([]byte(oldPolicy.Options), &m1)
var m2 = maps.Map{}
_ = json.Unmarshal(optionsJSON, &m2)
if bytes.Compare(m1.AsJSON(), m2.AsJSON()) != 0 {
op.Version = dbs.SQL("version+1")
}
}
// 版本号总是加1
op.Version = dbs.SQL("version+1")
op.IsPublic = isPublic
op.FirewallOnly = firewallOnly
op.IsOn = isOn
return this.Save(tx, op)
}

View File

@@ -1,36 +1,40 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPAccessLogPolicy 访问日志策略
type HTTPAccessLogPolicy struct {
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Name string `field:"name"` // 名称
IsOn uint8 `field:"isOn"` // 是否启用
Type string `field:"type"` // 存储类型
Options string `field:"options"` // 存储选项
Conds string `field:"conds"` // 请求条件
IsPublic uint8 `field:"isPublic"` // 是否为公用
Version uint32 `field:"version"` // 版本号
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Name string `field:"name"` // 名称
IsOn bool `field:"isOn"` // 是否启用
Type string `field:"type"` // 存储类型
Options dbs.JSON `field:"options"` // 存储选项
Conds dbs.JSON `field:"conds"` // 请求条件
IsPublic bool `field:"isPublic"` // 是否为公用
FirewallOnly uint8 `field:"firewallOnly"` // 是否只记录防火墙相关
Version uint32 `field:"version"` // 版本号
}
type HTTPAccessLogPolicyOperator struct {
Id interface{} // ID
TemplateId interface{} // 模版ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
State interface{} // 状态
CreatedAt interface{} // 创建时间
Name interface{} // 名称
IsOn interface{} // 是否启用
Type interface{} // 存储类型
Options interface{} // 存储选项
Conds interface{} // 请求条件
IsPublic interface{} // 是否为公用
Version interface{} // 版本号
Id interface{} // ID
TemplateId interface{} // 模版ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
State interface{} // 状态
CreatedAt interface{} // 创建时间
Name interface{} // 名称
IsOn interface{} // 是否启用
Type interface{} // 存储类型
Options interface{} // 存储选项
Conds interface{} // 请求条件
IsPublic interface{} // 是否为公用
FirewallOnly interface{} // 是否只记录防火墙相关
Version interface{} // 版本号
}
func NewHTTPAccessLogPolicyOperator() *HTTPAccessLogPolicyOperator {

View File

@@ -116,13 +116,13 @@ func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, c
var config = &serverconfigs.HTTPAuthPolicy{
Id: int64(policy.Id),
Name: policy.Name,
IsOn: policy.IsOn == 1,
IsOn: policy.IsOn,
Type: policy.Type,
}
var params map[string]interface{}
if IsNotNull(policy.Params) {
err = json.Unmarshal([]byte(policy.Params), &params)
err = json.Unmarshal(policy.Params, &params)
if err != nil {
return nil, err
}

View File

@@ -1,15 +1,17 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPAuthPolicy HTTP认证策略
type HTTPAuthPolicy struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Type string `field:"type"` // 类型
Params string `field:"params"` // 参数
State uint8 `field:"state"` // 状态
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Type string `field:"type"` // 类型
Params dbs.JSON `field:"params"` // 参数
State uint8 `field:"state"` // 状态
}
type HTTPAuthPolicyOperator struct {

View File

@@ -80,10 +80,10 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
config := &serverconfigs.HTTPBrotliCompressionConfig{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
if IsNotNull(policy.MinLength) {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
err = json.Unmarshal(policy.MinLength, minLengthConfig)
if err != nil {
return nil, err
}
@@ -91,7 +91,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
}
if IsNotNull(policy.MaxLength) {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
if err != nil {
return nil, err
}
@@ -101,7 +101,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
if IsNotNull(policy.Conds) {
condsConfig := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
err = json.Unmarshal(policy.Conds, condsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,17 +1,19 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPBrotliPolicy Gzip配置
type HTTPBrotliPolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds string `field:"conds"` // 条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds dbs.JSON `field:"conds"` // 条件
}
type HTTPBrotliPolicyOperator struct {

View File

@@ -2,6 +2,7 @@ package models
import (
"encoding/json"
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
@@ -252,7 +253,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
}
config := &serverconfigs.HTTPCachePolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
config.Name = policy.Name
config.Description = policy.Description
config.SyncCompressionCache = policy.SyncCompressionCache == 1
@@ -260,7 +261,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// capacity
if IsNotNull(policy.Capacity) {
capacityConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.Capacity), capacityConfig)
err = json.Unmarshal(policy.Capacity, capacityConfig)
if err != nil {
return nil, err
}
@@ -272,7 +273,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// max size
if IsNotNull(policy.MaxSize) {
maxSizeConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MaxSize), maxSizeConfig)
err = json.Unmarshal(policy.MaxSize, maxSizeConfig)
if err != nil {
return nil, err
}
@@ -284,7 +285,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// options
if IsNotNull(policy.Options) {
m := map[string]interface{}{}
err = json.Unmarshal([]byte(policy.Options), &m)
err = json.Unmarshal(policy.Options, &m)
if err != nil {
return nil, errors.Wrap(err)
}
@@ -294,7 +295,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// refs
if IsNotNull(policy.Refs) {
refs := []*serverconfigs.HTTPCacheRef{}
err = json.Unmarshal([]byte(policy.Refs), &refs)
err = json.Unmarshal(policy.Refs, &refs)
if err != nil {
return nil, err
}
@@ -318,7 +319,7 @@ func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clu
}
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
if len(storageType) > 0 {
query.Attr("type", storageType)
@@ -336,7 +337,7 @@ func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, cluster
}
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
if len(storageType) > 0 {
query.Attr("type", storageType)

View File

@@ -1,23 +1,25 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPCachePolicy HTTP缓存策略
type HTTPCachePolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Capacity string `field:"capacity"` // 容量数据
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
MaxSize string `field:"maxSize"` // 最大缓存内容尺寸
Type string `field:"type"` // 存储类型
Options string `field:"options"` // 存储选项
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 描述
Refs string `field:"refs"` // 默认的缓存设置
SyncCompressionCache uint8 `field:"syncCompressionCache"` // 是否同步写入压缩缓存
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Capacity dbs.JSON `field:"capacity"` // 容量数据
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
MaxSize dbs.JSON `field:"maxSize"` // 最大缓存内容尺寸
Type string `field:"type"` // 存储类型
Options dbs.JSON `field:"options"` // 存储选项
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 描述
Refs dbs.JSON `field:"refs"` // 默认的缓存设置
SyncCompressionCache uint8 `field:"syncCompressionCache"` // 是否同步写入压缩缓存
}
type HTTPCachePolicyOperator struct {

View File

@@ -0,0 +1,254 @@
package models
import (
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/rands"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
const (
HTTPCacheTaskStateEnabled = 1 // 已启用
HTTPCacheTaskStateDisabled = 0 // 已禁用
)
type HTTPCacheTaskType = string
const (
HTTPCacheTaskTypePurge HTTPCacheTaskType = "purge"
HTTPCacheTaskTypeFetch HTTPCacheTaskType = "fetch"
)
type HTTPCacheTaskDAO dbs.DAO
func init() {
dbs.OnReadyDone(func() {
// 清理数据任务
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedHTTPCacheTaskDAO.Clean(nil, 30) // 只保留N天
if err != nil {
remotelogs.Error("HTTPCacheTaskDAO", "clean expired data failed: "+err.Error())
}
}
})
})
}
func NewHTTPCacheTaskDAO() *HTTPCacheTaskDAO {
return dbs.NewDAO(&HTTPCacheTaskDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeHTTPCacheTasks",
Model: new(HTTPCacheTask),
PkName: "id",
},
}).(*HTTPCacheTaskDAO)
}
var SharedHTTPCacheTaskDAO *HTTPCacheTaskDAO
func init() {
dbs.OnReady(func() {
SharedHTTPCacheTaskDAO = NewHTTPCacheTaskDAO()
})
}
// EnableHTTPCacheTask 启用条目
func (this *HTTPCacheTaskDAO) EnableHTTPCacheTask(tx *dbs.Tx, taskId int64) error {
_, err := this.Query(tx).
Pk(taskId).
Set("state", HTTPCacheTaskStateEnabled).
Update()
return err
}
// DisableHTTPCacheTask 禁用条目
func (this *HTTPCacheTaskDAO) DisableHTTPCacheTask(tx *dbs.Tx, taskId int64) error {
_, err := this.Query(tx).
Pk(taskId).
Set("state", HTTPCacheTaskStateDisabled).
Update()
if err != nil {
return err
}
return this.NotifyChange(tx, taskId)
}
// FindEnabledHTTPCacheTask 查找启用中的条目
func (this *HTTPCacheTaskDAO) FindEnabledHTTPCacheTask(tx *dbs.Tx, taskId int64) (*HTTPCacheTask, error) {
result, err := this.Query(tx).
Pk(taskId).
Attr("state", HTTPCacheTaskStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*HTTPCacheTask), err
}
// CreateTask 创建任务
func (this *HTTPCacheTaskDAO) CreateTask(tx *dbs.Tx, userId int64, taskType HTTPCacheTaskType, keyType string, description string) (int64, error) {
var op = NewHTTPCacheTaskOperator()
op.UserId = userId
op.Type = taskType
op.KeyType = keyType
op.IsOk = false
op.IsDone = false
op.IsReady = false
op.Description = description
op.Day = timeutil.Format("Ymd")
op.State = HTTPCacheTaskStateEnabled
taskId, err := this.SaveInt64(tx, op)
if err != nil {
return 0, err
}
err = this.NotifyChange(tx, taskId)
if err != nil {
return 0, err
}
return taskId, nil
}
// ResetTask 重置服务状态
func (this *HTTPCacheTaskDAO) ResetTask(tx *dbs.Tx, taskId int64) error {
if taskId <= 0 {
return errors.New("invalid 'taskId'")
}
var op = NewHTTPCacheTaskOperator()
op.Id = taskId
op.IsOk = false
op.IsDone = false
op.DoneAt = 0
return this.Save(tx, op)
}
// UpdateTaskReady 设置任务为已准备
func (this *HTTPCacheTaskDAO) UpdateTaskReady(tx *dbs.Tx, taskId int64) error {
return this.Query(tx).
Pk(taskId).
Set("isReady", true).
UpdateQuickly()
}
// CountTasks 查询所有任务数量
func (this *HTTPCacheTaskDAO) CountTasks(tx *dbs.Tx, userId int64) (int64, error) {
var query = this.Query(tx).
State(HTTPCacheTaskStateEnabled).
Attr("isReady", true)
if userId > 0 {
query.Attr("userId", userId)
}
return query.Count()
}
// CountDoingTasks 查询正在执行的任务数量
func (this *HTTPCacheTaskDAO) CountDoingTasks(tx *dbs.Tx, userId int64) (int64, error) {
var query = this.Query(tx).
State(HTTPCacheTaskStateEnabled).
Attr("isReady", true).
Attr("isDone", false)
if userId > 0 {
query.Attr("userId", userId)
}
return query.Count()
}
// ListTasks 列出单页任务
func (this *HTTPCacheTaskDAO) ListTasks(tx *dbs.Tx, userId int64, offset int64, size int64) (result []*HTTPCacheTask, err error) {
var query = this.Query(tx).
State(HTTPCacheTaskStateEnabled).
Attr("isReady", true)
if userId > 0 {
query.Attr("userId", userId)
}
_, err = query.
Offset(offset).
Limit(size).
Slice(&result).
DescPk().
FindAll()
return
}
// ListDoingTasks 列出需要执行的任务
func (this *HTTPCacheTaskDAO) ListDoingTasks(tx *dbs.Tx, size int64) (result []*HTTPCacheTask, err error) {
_, err = this.Query(tx).
State(HTTPCacheTaskStateEnabled).
Attr("isDone", false).
Attr("isReady", true).
Limit(size).
AscPk(). // 按照先创建先执行的原则
Slice(&result).
FindAll()
return
}
// UpdateTaskStatus 标记任务已完成
func (this *HTTPCacheTaskDAO) UpdateTaskStatus(tx *dbs.Tx, taskId int64, isDone bool, isOk bool) error {
if taskId <= 0 {
return errors.New("invalid taskId '" + types.String(taskId) + "'")
}
var op = NewHTTPCacheTaskOperator()
op.Id = taskId
op.IsDone = isDone
op.IsOk = isOk
if isDone {
op.DoneAt = time.Now().Unix()
}
return this.Save(tx, op)
}
// CheckUserTask 检查用户任务
func (this *HTTPCacheTaskDAO) CheckUserTask(tx *dbs.Tx, userId int64, taskId int64) error {
b, err := this.Query(tx).
Pk(taskId).
Attr("userId", userId).
State(HTTPCacheTaskStateEnabled).
Exist()
if err != nil {
return err
}
if !b {
return ErrNotFound
}
return nil
}
// Clean 清理以往的任务
func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
if days <= 0 {
days = 30
}
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
// 删除Key
err := SharedHTTPCacheTaskKeyDAO.Clean(tx, days)
if err != nil {
return err
}
// 删除任务
_, err = this.Query(tx).
Lte("day", day).
Delete()
return err
}
// NotifyChange 发送通知
func (this *HTTPCacheTaskDAO) NotifyChange(tx *dbs.Tx, taskId int64) error {
// TODO
return nil
}

View File

@@ -0,0 +1,19 @@
package models_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/dbs"
"testing"
)
func TestHTTPCacheTaskDAO_Clean(t *testing.T) {
dbs.NotifyReady()
err := models.SharedHTTPCacheTaskDAO.Clean(nil, 30)
if err != nil {
t.Fatal(err)
}
t.Log("ok")
}

View File

@@ -0,0 +1,218 @@
package models
import (
"github.com/TeaOSLab/EdgeAPI/internal/errors"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
type HTTPCacheTaskKeyDAO dbs.DAO
func NewHTTPCacheTaskKeyDAO() *HTTPCacheTaskKeyDAO {
return dbs.NewDAO(&HTTPCacheTaskKeyDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeHTTPCacheTaskKeys",
Model: new(HTTPCacheTaskKey),
PkName: "id",
},
}).(*HTTPCacheTaskKeyDAO)
}
var SharedHTTPCacheTaskKeyDAO *HTTPCacheTaskKeyDAO
func init() {
dbs.OnReady(func() {
SharedHTTPCacheTaskKeyDAO = NewHTTPCacheTaskKeyDAO()
})
}
// CreateKey 创建Key
// 参数:
// - clusterId 集群ID
// - nodeMapJSON 集群下节点映射,格式类似于 `{ "节点1":true, ... }`
func (this *HTTPCacheTaskKeyDAO) CreateKey(tx *dbs.Tx, taskId int64, key string, taskType HTTPCacheTaskType, keyType string, clusterId int64) (int64, error) {
var op = NewHTTPCacheTaskKeyOperator()
op.TaskId = taskId
op.Key = key
op.Type = taskType
op.KeyType = keyType
op.ClusterId = clusterId
op.Nodes = "{}"
op.Errors = "{}"
return this.SaveInt64(tx, op)
}
// UpdateKeyStatus 修改Key状态
func (this *HTTPCacheTaskKeyDAO) UpdateKeyStatus(tx *dbs.Tx, keyId int64, nodeId int64, errString string, nodesJSON []byte) error {
if keyId <= 0 {
return errors.New("invalid 'keyId'")
}
if len(nodesJSON) == 0 {
nodesJSON = []byte("{}")
}
taskId, err := this.Query(tx).
Pk(keyId).
Result("taskId").
FindInt64Col(0)
if err != nil {
return err
}
var jsonPath = "$.\"" + types.String(nodeId) + "\""
var query = this.Query(tx).
Pk(keyId).
Set("nodes", dbs.SQL("JSON_SET(nodes, :jsonPath1, true)")).
Param("jsonPath1", jsonPath)
if len(errString) > 0 {
query.Set("errors", dbs.SQL("JSON_SET(errors, :jsonPath2, :jsonValue2)")).
Param("jsonPath2", jsonPath).
Param("jsonValue2", errString)
} else {
query.Set("errors", dbs.SQL("JSON_REMOVE(errors, :jsonPath2)")).
Param("jsonPath2", jsonPath)
}
err = query.
UpdateQuickly()
if err != nil {
return err
}
// 检查是否已完成
isDone, err := this.Query(tx).
Pk(keyId).
Where("JSON_CONTAINS(nodes, :nodesJSON)").
Param("nodesJSON", nodesJSON).
Exist()
if err != nil {
return err
}
if isDone {
err = this.Query(tx).
Pk(keyId).
Set("isDone", isDone).
UpdateQuickly()
if err != nil {
return err
}
// 检查任务是否已经完成
taskIsNotDone, err := this.Query(tx).
Attr("taskId", taskId).
Attr("isDone", false).
Exist()
if err != nil {
return err
}
var taskIsDone = !taskIsNotDone
var hasErrors = true
if taskIsDone {
// 已经完成,是否有错误
hasErrors, err = this.Query(tx).
Attr("taskId", taskId).
Where("JSON_LENGTH(errors)>0").
Exist()
if err != nil {
return err
}
}
err = SharedHTTPCacheTaskDAO.UpdateTaskStatus(tx, taskId, taskIsDone, !hasErrors)
if err != nil {
return err
}
}
return nil
}
// FindAllTaskKeys 查询某个任务下的所有Key
func (this *HTTPCacheTaskKeyDAO) FindAllTaskKeys(tx *dbs.Tx, taskId int64) (result []*HTTPCacheTaskKey, err error) {
_, err = this.Query(tx).
Attr("taskId", taskId).
AscPk().
Slice(&result).
FindAll()
return
}
// FindDoingTaskKeys 查询要执行的任务
func (this *HTTPCacheTaskKeyDAO) FindDoingTaskKeys(tx *dbs.Tx, nodeId int64, size int64) (result []*HTTPCacheTaskKey, err error) {
// 集群ID
clusterIds, err := SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
if err != nil {
return nil, err
}
if len(clusterIds) == 0 {
return nil, nil
}
_, err = this.Query(tx).
Attr("clusterId", clusterIds).
Attr("isDone", false).
Where("NOT JSON_CONTAINS_PATH(nodes, 'one', :jsonPath1)").
Param("jsonPath1", "$.\""+types.String(nodeId)+"\"").
Where("taskId IN (SELECT id FROM " + SharedHTTPCacheTaskDAO.Table + " WHERE state=1 AND isReady=1 AND isDone=0)").
Limit(size).
AscPk().
Reuse(false).
Slice(&result).
FindAll()
if err != nil {
return nil, err
}
return
}
// ResetCacheKeysWithTaskId 重置任务下的Key状态
func (this *HTTPCacheTaskKeyDAO) ResetCacheKeysWithTaskId(tx *dbs.Tx, taskId int64) error {
return this.Query(tx).
Attr("taskId", taskId).
Set("isDone", false).
Set("nodes", "{}").
Set("errors", "{}").
UpdateQuickly()
}
// CountUserTasksInDay 读取某个用户当前数量
// day YYYYMMDD
func (this *HTTPCacheTaskKeyDAO) CountUserTasksInDay(tx *dbs.Tx, userId int64, day string, taskType HTTPCacheTaskType) (int64, error) {
if userId <= 0 {
return 0, nil
}
// 这里需要包含已删除的
return this.Query(tx).
Where("taskId IN (SELECT id FROM "+SharedHTTPCacheTaskDAO.Table+" WHERE userId=:userId AND day=:day AND type=:type)").
Param("userId", userId).
Param("day", day).
Param("type", taskType).
Count()
}
// Clean 清理以往的任务
func (this *HTTPCacheTaskKeyDAO) Clean(tx *dbs.Tx, days int) error {
if days <= 0 {
days = 30
}
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Where("taskId IN (SELECT id FROM "+SharedHTTPCacheTaskDAO.Table+" WHERE day<=:day)").
Param("day", day).
Delete()
return err
}

View File

@@ -0,0 +1,54 @@
package models_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/dbs"
timeutil "github.com/iwind/TeaGo/utils/time"
"testing"
)
func TestHTTPCacheTaskKeyDAO_CreateKey(t *testing.T) {
var dao = models.NewHTTPCacheTaskKeyDAO()
var tx *dbs.Tx
_, err := dao.CreateKey(tx, 1, "a", "purge", "key", 1)
if err != nil {
t.Fatal(err)
}
t.Log("ok")
}
func TestHTTPCacheTaskKeyDAO_UpdateKeyStatus(t *testing.T) {
dbs.NotifyReady()
var dao = models.NewHTTPCacheTaskKeyDAO()
var tx *dbs.Tx
var errString = "" // "this is error"
err := dao.UpdateKeyStatus(tx, 3, 1, errString, []byte(`{"1":true}`))
if err != nil {
t.Fatal(err)
}
t.Log("ok")
}
func TestHTTPCacheTaskKeyDAO_CountUserTasksInDay(t *testing.T) {
dbs.NotifyReady()
var dao = models.NewHTTPCacheTaskKeyDAO()
var tx *dbs.Tx
{
count, err := dao.CountUserTasksInDay(tx, 1, timeutil.Format("Ymd"), models.HTTPCacheTaskTypePurge)
if err != nil {
t.Fatal(err)
}
t.Log("count:", count)
}
{
count, err := dao.CountUserTasksInDay(tx, 1, timeutil.Format("Ymd"), models.HTTPCacheTaskTypeFetch)
if err != nil {
t.Fatal(err)
}
t.Log("count:", count)
}
}

View File

@@ -0,0 +1,32 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPCacheTaskKey 缓存任务Key
type HTTPCacheTaskKey struct {
Id uint64 `field:"id"` // ID
TaskId uint64 `field:"taskId"` // 任务ID
Key string `field:"key"` // Key
KeyType string `field:"keyType"` // Key类型key|prefix
Type string `field:"type"` // 操作类型
ClusterId uint32 `field:"clusterId"` // 集群ID
Nodes dbs.JSON `field:"nodes"` // 节点
Errors dbs.JSON `field:"errors"` // 错误信息
IsDone bool `field:"isDone"` // 是否已完成
}
type HTTPCacheTaskKeyOperator struct {
Id interface{} // ID
TaskId interface{} // 任务ID
Key interface{} // Key
KeyType interface{} // Key类型key|prefix
Type interface{} // 操作类型
ClusterId interface{} // 集群ID
Nodes interface{} // 节点
Errors interface{} // 错误信息
IsDone interface{} // 是否已完成
}
func NewHTTPCacheTaskKeyOperator() *HTTPCacheTaskKeyOperator {
return &HTTPCacheTaskKeyOperator{}
}

View File

@@ -0,0 +1,20 @@
package models
import "encoding/json"
// DecodeNodes 解析已完成节点信息
func (this *HTTPCacheTaskKey) DecodeNodes() map[string]bool {
var result = map[string]bool{}
var nodesJSON = this.Nodes
if IsNull(nodesJSON) {
return result
}
err := json.Unmarshal(nodesJSON, &result)
if err != nil {
// ignore error
return result
}
return result
}

View File

@@ -0,0 +1,36 @@
package models
// HTTPCacheTask 缓存相关任务
type HTTPCacheTask struct {
Id uint64 `field:"id"` // ID
UserId uint32 `field:"userId"` // 用户ID
Type string `field:"type"` // 任务类型purge|fetch
KeyType string `field:"keyType"` // Key类型
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
DoneAt uint64 `field:"doneAt"` // 完成时间
Day string `field:"day"` // 创建日期YYYYMMDD
IsDone bool `field:"isDone"` // 是否已完成
IsOk bool `field:"isOk"` // 是否完全成功
IsReady uint8 `field:"isReady"` // 是否已准备好
Description string `field:"description"` // 描述
}
type HTTPCacheTaskOperator struct {
Id interface{} // ID
UserId interface{} // 用户ID
Type interface{} // 任务类型purge|fetch
KeyType interface{} // Key类型
State interface{} // 状态
CreatedAt interface{} // 创建时间
DoneAt interface{} // 完成时间
Day interface{} // 创建日期YYYYMMDD
IsDone interface{} // 是否已完成
IsOk interface{} // 是否完全成功
IsReady interface{} // 是否已准备好
Description interface{} // 描述
}
func NewHTTPCacheTaskOperator() *HTTPCacheTaskOperator {
return &HTTPCacheTaskOperator{}
}

View File

@@ -0,0 +1 @@
package models

View File

@@ -80,10 +80,10 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
config := &serverconfigs.HTTPDeflateCompressionConfig{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
if IsNotNull(policy.MinLength) {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
err = json.Unmarshal(policy.MinLength, minLengthConfig)
if err != nil {
return nil, err
}
@@ -91,7 +91,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
}
if IsNotNull(policy.MaxLength) {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
if err != nil {
return nil, err
}
@@ -101,7 +101,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
if IsNotNull(policy.Conds) {
condsConfig := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
err = json.Unmarshal(policy.Conds, condsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,17 +1,19 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPDeflatePolicy Gzip配置
type HTTPDeflatePolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds string `field:"conds"` // 条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds dbs.JSON `field:"conds"` // 条件
}
type HTTPDeflatePolicyOperator struct {

View File

@@ -81,12 +81,12 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
}
config := &serverconfigs.HTTPFastcgiConfig{}
config.Id = int64(fastcgi.Id)
config.IsOn = fastcgi.IsOn == 1
config.IsOn = fastcgi.IsOn
config.Address = fastcgi.Address
if IsNotNull(fastcgi.Params) {
params := []*serverconfigs.HTTPFastcgiParam{}
err = json.Unmarshal([]byte(fastcgi.Params), &params)
err = json.Unmarshal(fastcgi.Params, &params)
if err != nil {
return nil, err
}
@@ -95,7 +95,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
if IsNotNull(fastcgi.ReadTimeout) {
duration := &shared.TimeDuration{}
err = json.Unmarshal([]byte(fastcgi.ReadTimeout), duration)
err = json.Unmarshal(fastcgi.ReadTimeout, duration)
if err != nil {
return nil, err
}
@@ -104,7 +104,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
if IsNotNull(fastcgi.ConnTimeout) {
duration := &shared.TimeDuration{}
err = json.Unmarshal([]byte(fastcgi.ConnTimeout), duration)
err = json.Unmarshal(fastcgi.ConnTimeout, duration)
if err != nil {
return nil, err
}

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFastcgi Fastcgi设置
type HTTPFastcgi struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Address string `field:"address"` // 地址
Params string `field:"params"` // 参数
ReadTimeout string `field:"readTimeout"` // 读取超时
ConnTimeout string `field:"connTimeout"` // 连接超时
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
State uint8 `field:"state"` // 状态
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Address string `field:"address"` // 地址
Params dbs.JSON `field:"params"` // 参数
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
State uint8 `field:"state"` // 状态
}
type HTTPFastcgiOperator struct {

View File

@@ -2,6 +2,7 @@ package models
import (
"encoding/json"
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
@@ -116,7 +117,7 @@ func (this *HTTPFirewallPolicyDAO) FindAllEnabledFirewallPolicies(tx *dbs.Tx) (r
// CreateFirewallPolicy 创建策略
func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64, serverGroupId int64, serverId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte) (int64, error) {
op := NewHTTPFirewallPolicyOperator()
var op = NewHTTPFirewallPolicyOperator()
op.UserId = userId
op.GroupId = serverGroupId
op.ServerId = serverId
@@ -130,14 +131,31 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
if len(outboundJSON) > 0 {
op.Outbound = outboundJSON
}
op.UseLocalFirewall = true
{
synFloodJSON, err := json.Marshal(firewallconfigs.DefaultSYNFloodConfig())
if userId <= 0 && serverGroupId <=0 && serverId <= 0 {
// synFlood
var synFloodConfig = firewallconfigs.DefaultSYNFloodConfig()
synFloodJSON, err := json.Marshal(synFloodConfig)
if err != nil {
return 0, err
}
op.SynFlood = synFloodJSON
// block options
var blockOptions = firewallconfigs.DefaultHTTPFirewallBlockAction()
blockOptionsJSON, err := json.Marshal(blockOptions)
if err != nil {
return 0, err
}
op.BlockOptions = blockOptionsJSON
// captcha options
var captchaOptions = firewallconfigs.DefaultHTTPFirewallCaptchaAction()
captchaOptionsJSON, err := json.Marshal(captchaOptions)
if err != nil {
return 0, err
}
op.CaptchaOptions = captchaOptionsJSON
}
err := this.Save(tx, op)
@@ -159,8 +177,8 @@ func (this *HTTPFirewallPolicyDAO) CreateDefaultFirewallPolicy(tx *dbs.Tx, name
groupCodes = append(groupCodes, group.Code)
}
inboundConfig := &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
outboundConfig := &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
var inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
var outboundConfig = &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
if templatePolicy.Inbound != nil {
for _, group := range templatePolicy.Inbound.Groups {
isOn := lists.ContainsString(groupCodes, group.Code)
@@ -206,6 +224,7 @@ func (this *HTTPFirewallPolicyDAO) CreateDefaultFirewallPolicy(tx *dbs.Tx, name
if err != nil {
return 0, err
}
return policyId, nil
}
@@ -259,11 +278,23 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
}
// UpdateFirewallPolicy 修改策略
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte, blockOptionsJSON []byte, mode firewallconfigs.FirewallMode, useLocalFirewall bool, synFloodConfig *firewallconfigs.SYNFloodConfig) error {
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
policyId int64,
isOn bool,
name string,
description string,
inboundJSON []byte,
outboundJSON []byte,
blockOptionsJSON []byte,
captchaOptionsJSON []byte,
mode firewallconfigs.FirewallMode,
useLocalFirewall bool,
synFloodConfig *firewallconfigs.SYNFloodConfig,
logConfig *firewallconfigs.HTTPFirewallPolicyLogConfig) error {
if policyId <= 0 {
return errors.New("invalid policyId")
}
op := NewHTTPFirewallPolicyOperator()
var op = NewHTTPFirewallPolicyOperator()
op.Id = policyId
op.IsOn = isOn
op.Name = name
@@ -279,9 +310,12 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
} else {
op.Outbound = "null"
}
if len(blockOptionsJSON) > 0 {
if IsNotNull(blockOptionsJSON) {
op.BlockOptions = blockOptionsJSON
}
if IsNotNull(captchaOptionsJSON) {
op.CaptchaOptions = captchaOptionsJSON
}
if synFloodConfig != nil {
synFloodConfigJSON, err := json.Marshal(synFloodConfig)
@@ -293,6 +327,16 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
op.SynFlood = "null"
}
if logConfig != nil {
logJSON, err := json.Marshal(logConfig)
if err != nil {
return err
}
op.Log = logJSON
} else {
op.Log = "null"
}
op.UseLocalFirewall = useLocalFirewall
err := this.Save(tx, op)
if err != nil {
@@ -311,7 +355,7 @@ func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, c
}
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
return query.
State(HTTPFirewallPolicyStateEnabled).
@@ -330,7 +374,7 @@ func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, clust
}
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
Param("keyword", dbutils.QuoteLike(keyword))
}
_, err = query.
State(HTTPFirewallPolicyStateEnabled).
@@ -364,9 +408,9 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
return nil, nil
}
config := &firewallconfigs.HTTPFirewallPolicy{}
var config = &firewallconfigs.HTTPFirewallPolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
config.Name = policy.Name
config.Description = policy.Description
config.UseLocalFirewall = policy.UseLocalFirewall == 1
@@ -379,7 +423,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
// Inbound
inbound := &firewallconfigs.HTTPFirewallInboundConfig{}
if IsNotNull(policy.Inbound) {
err = json.Unmarshal([]byte(policy.Inbound), inbound)
err = json.Unmarshal(policy.Inbound, inbound)
if err != nil {
return nil, err
}
@@ -407,7 +451,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
// Outbound
outbound := &firewallconfigs.HTTPFirewallOutboundConfig{}
if IsNotNull(policy.Outbound) {
err = json.Unmarshal([]byte(policy.Outbound), outbound)
err = json.Unmarshal(policy.Outbound, outbound)
if err != nil {
return nil, err
}
@@ -434,24 +478,46 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
// Block动作配置
if IsNotNull(policy.BlockOptions) {
blockAction := &firewallconfigs.HTTPFirewallBlockAction{}
err = json.Unmarshal([]byte(policy.BlockOptions), blockAction)
var blockAction = &firewallconfigs.HTTPFirewallBlockAction{}
err = json.Unmarshal(policy.BlockOptions, blockAction)
if err != nil {
return config, err
}
config.BlockOptions = blockAction
}
// Captcha动作配置
if IsNotNull(policy.CaptchaOptions) {
var captchaAction = &firewallconfigs.HTTPFirewallCaptchaAction{}
err = json.Unmarshal(policy.CaptchaOptions, captchaAction)
if err != nil {
return config, err
}
config.CaptchaOptions = captchaAction
}
// syn flood
if len(policy.SynFlood) > 0 {
if IsNotNull(policy.SynFlood) {
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
err = json.Unmarshal([]byte(policy.SynFlood), synFloodConfig)
err = json.Unmarshal(policy.SynFlood, synFloodConfig)
if err != nil {
return nil, err
}
config.SYNFlood = synFloodConfig
}
// log
if IsNotNull(policy.Log) {
var logConfig = &firewallconfigs.HTTPFirewallPolicyLogConfig{}
err = json.Unmarshal(policy.Log, logConfig)
if err != nil {
return nil, err
}
config.Log = logConfig
} else {
config.Log = firewallconfigs.DefaultHTTPFirewallPolicyLogConfig
}
if cacheMap != nil {
cacheMap.Put(cacheKey, config)
}
@@ -492,6 +558,7 @@ func (this *HTTPFirewallPolicyDAO) CheckUserFirewallPolicy(tx *dbs.Tx, userId in
}
// FindEnabledFirewallPolicyIdsWithIPListId 查找包含某个IPList的所有策略
// TODO 改成通过 serverId 查询
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *dbs.Tx, ipListId int64) ([]int64, error) {
ones, err := this.Query(tx).
ResultPk().
@@ -510,6 +577,7 @@ func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *
}
// FindEnabledFirewallPolicyWithIPListId 查找使用某个IPList的策略
// TODO 改成通过 serverId 查询
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyWithIPListId(tx *dbs.Tx, ipListId int64) (*HTTPFirewallPolicy, error) {
one, err := this.Query(tx).
State(HTTPFirewallPolicyStateEnabled).

View File

@@ -1,24 +1,28 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallPolicy HTTP防火墙
type HTTPFirewallPolicy struct {
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ServerId uint32 `field:"serverId"` // 服务ID
GroupId uint32 `field:"groupId"` // 服务分组ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Inbound string `field:"inbound"` // 入站规则
Outbound string `field:"outbound"` // 出站规则
BlockOptions string `field:"blockOptions"` // BLOCK选项
Mode string `field:"mode"` // 模式
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
SynFlood string `field:"synFlood"` // SynFlood防御设置
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ServerId uint32 `field:"serverId"` // 服务ID
GroupId uint32 `field:"groupId"` // 服务分组ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Inbound dbs.JSON `field:"inbound"` // 入站规则
Outbound dbs.JSON `field:"outbound"` // 出站规则
BlockOptions dbs.JSON `field:"blockOptions"` // BLOCK选项
CaptchaOptions dbs.JSON `field:"captchaOptions"` // 验证码选项
Mode string `field:"mode"` // 模式
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
SynFlood dbs.JSON `field:"synFlood"` // SynFlood防御设置
Log dbs.JSON `field:"log"` // 日志配置
}
type HTTPFirewallPolicyOperator struct {
@@ -36,9 +40,11 @@ type HTTPFirewallPolicyOperator struct {
Inbound interface{} // 入站规则
Outbound interface{} // 出站规则
BlockOptions interface{} // BLOCK选项
CaptchaOptions interface{} // 验证码选项
Mode interface{} // 模式
UseLocalFirewall interface{} // 是否自动使用本地防火墙
SynFlood interface{} // SynFlood防御设置
Log interface{} // 日志配置
}
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {

View File

@@ -35,12 +35,12 @@ func init() {
})
}
// 初始化
// Init 初始化
func (this *HTTPFirewallRuleDAO) Init() {
_ = this.DAOObject.Init()
}
// 启用条目
// EnableHTTPFirewallRule 启用条目
func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
@@ -49,7 +49,7 @@ func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) er
return err
}
// 禁用条目
// DisableHTTPFirewallRule 禁用条目
func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int64) error {
_, err := this.Query(tx).
Pk(ruleId).
@@ -61,7 +61,7 @@ func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int6
return this.NotifyUpdate(tx, ruleId)
}
// 查找启用中的条目
// FindEnabledHTTPFirewallRule 查找启用中的条目
func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int64) (*HTTPFirewallRule, error) {
result, err := this.Query(tx).
Pk(id).
@@ -73,7 +73,7 @@ func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int6
return result.(*HTTPFirewallRule), err
}
// 组合配置
// ComposeFirewallRule 组合配置
func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (*firewallconfigs.HTTPFirewallRule, error) {
rule, err := this.FindEnabledHTTPFirewallRule(tx, ruleId)
if err != nil {
@@ -84,12 +84,12 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
}
config := &firewallconfigs.HTTPFirewallRule{}
config.Id = int64(rule.Id)
config.IsOn = rule.IsOn == 1
config.IsOn = rule.IsOn
config.Param = rule.Param
paramFilters := []*firewallconfigs.ParamFilter{}
if IsNotNull(rule.ParamFilters) {
err = json.Unmarshal([]byte(rule.ParamFilters), &paramFilters)
err = json.Unmarshal(rule.ParamFilters, &paramFilters)
if err != nil {
return nil, err
}
@@ -98,11 +98,11 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
config.Operator = rule.Operator
config.Value = rule.Value
config.IsCaseInsensitive = rule.IsCaseInsensitive == 1
config.IsCaseInsensitive = rule.IsCaseInsensitive
if IsNotNull(rule.CheckpointOptions) {
checkpointOptions := map[string]interface{}{}
err = json.Unmarshal([]byte(rule.CheckpointOptions), &checkpointOptions)
err = json.Unmarshal(rule.CheckpointOptions, &checkpointOptions)
if err != nil {
return nil, err
}
@@ -114,7 +114,7 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
return config, nil
}
// 从配置中配置规则
// CreateOrUpdateRuleFromConfig 从配置中配置规则
func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleConfig *firewallconfigs.HTTPFirewallRule) (int64, error) {
op := NewHTTPFirewallRuleOperator()
op.Id = ruleConfig.Id
@@ -160,7 +160,7 @@ func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleCo
return types.Int64(op.Id), nil
}
// 通知更新
// NotifyUpdate 通知更新
func (this *HTTPFirewallRuleDAO) NotifyUpdate(tx *dbs.Tx, ruleId int64) error {
setId, err := SharedHTTPFirewallRuleSetDAO.FindEnabledRuleSetIdWithRuleId(tx, ruleId)
if err != nil {

View File

@@ -91,15 +91,15 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
}
config := &firewallconfigs.HTTPFirewallRuleGroup{}
config.Id = int64(group.Id)
config.IsOn = group.IsOn == 1
config.IsOn = group.IsOn
config.Name = group.Name
config.Description = group.Description
config.Code = group.Code
config.IsTemplate = group.IsTemplate == 1
config.IsTemplate = group.IsTemplate
if IsNotNull(group.Sets) {
setRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
err = json.Unmarshal([]byte(group.Sets), &setRefs)
err = json.Unmarshal(group.Sets, &setRefs)
if err != nil {
return nil, err
}

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallRuleGroup 防火墙规则分组
type HTTPFirewallRuleGroup struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Code string `field:"code"` // 代号
IsTemplate uint8 `field:"isTemplate"` // 是否为预置模板
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
Sets string `field:"sets"` // 规则集列表
CreatedAt uint64 `field:"createdAt"` // 创建时间
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Code string `field:"code"` // 代号
IsTemplate bool `field:"isTemplate"` // 是否为预置模板
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
Sets dbs.JSON `field:"sets"` // 规则集列表
CreatedAt uint64 `field:"createdAt"` // 创建时间
}
type HTTPFirewallRuleGroupOperator struct {

View File

@@ -1,20 +1,22 @@
package models
// 防火墙规则
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallRule 防火墙规则
type HTTPFirewallRule struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Description string `field:"description"` // 说明
Param string `field:"param"` // 参数
ParamFilters string `field:"paramFilters"` // 处理器
Operator string `field:"operator"` // 操作符
Value string `field:"value"` // 对比值
IsCaseInsensitive uint8 `field:"isCaseInsensitive"` // 是否大小写不敏感
CheckpointOptions string `field:"checkpointOptions"` // 检查点参数
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Description string `field:"description"` // 说明
Param string `field:"param"` // 参数
ParamFilters dbs.JSON `field:"paramFilters"` // 处理器
Operator string `field:"operator"` // 操作符
Value string `field:"value"` // 对比值
IsCaseInsensitive bool `field:"isCaseInsensitive"` // 是否大小写不敏感
CheckpointOptions dbs.JSON `field:"checkpointOptions"` // 检查点参数
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
}
type HTTPFirewallRuleOperator struct {

View File

@@ -94,7 +94,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
}
config := &firewallconfigs.HTTPFirewallRuleSet{}
config.Id = int64(set.Id)
config.IsOn = set.IsOn == 1
config.IsOn = set.IsOn
config.Name = set.Name
config.Description = set.Description
config.Code = set.Code
@@ -103,7 +103,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
if IsNotNull(set.Rules) {
ruleRefs := []*firewallconfigs.HTTPFirewallRuleRef{}
err = json.Unmarshal([]byte(set.Rules), &ruleRefs)
err = json.Unmarshal(set.Rules, &ruleRefs)
if err != nil {
return nil, err
}
@@ -121,7 +121,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
var actionConfigs = []*firewallconfigs.HTTPFirewallActionConfig{}
if len(set.Actions) > 0 {
err = json.Unmarshal([]byte(set.Actions), &actionConfigs)
err = json.Unmarshal(set.Actions, &actionConfigs)
if err != nil {
return nil, err
}

View File

@@ -1,22 +1,24 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallRuleSet 防火墙规则集
type HTTPFirewallRuleSet struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Code string `field:"code"` // 代号
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
CreatedAt uint64 `field:"createdAt"` // 创建时间
Rules string `field:"rules"` // 规则列表
Connector string `field:"connector"` // 规则之间的关系
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Action string `field:"action"` // 执行的动作(过期)
ActionOptions string `field:"actionOptions"` // 动作的选项(过期)
Actions string `field:"actions"` // 一组动作
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Code string `field:"code"` // 代号
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
CreatedAt uint64 `field:"createdAt"` // 创建时间
Rules dbs.JSON `field:"rules"` // 规则列表
Connector string `field:"connector"` // 规则之间的关系
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Action string `field:"action"` // 执行的动作(过期)
ActionOptions dbs.JSON `field:"actionOptions"` // 动作的选项(过期)
Actions dbs.JSON `field:"actions"` // 一组动作
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
}
type HTTPFirewallRuleSetOperator struct {

View File

@@ -88,10 +88,10 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
config := &serverconfigs.HTTPGzipCompressionConfig{}
config.Id = int64(gzip.Id)
config.IsOn = gzip.IsOn == 1
config.IsOn = gzip.IsOn
if IsNotNull(gzip.MinLength) {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(gzip.MinLength), minLengthConfig)
err = json.Unmarshal(gzip.MinLength, minLengthConfig)
if err != nil {
return nil, err
}
@@ -99,7 +99,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
}
if IsNotNull(gzip.MaxLength) {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(gzip.MaxLength), maxLengthConfig)
err = json.Unmarshal(gzip.MaxLength, maxLengthConfig)
if err != nil {
return nil, err
}
@@ -109,7 +109,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
if IsNotNull(gzip.Conds) {
condsConfig := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(gzip.Conds), condsConfig)
err = json.Unmarshal(gzip.Conds, condsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,17 +1,19 @@
package models
// Gzip配置
import "github.com/iwind/TeaGo/dbs"
// HTTPGzip Gzip配置
type HTTPGzip struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds string `field:"conds"` // 条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds dbs.JSON `field:"conds"` // 条件
}
type HTTPGzipOperator struct {

View File

@@ -5,22 +5,22 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
// 解析最小长度
// DecodeMinLength 解析最小长度
func (this *HTTPGzip) DecodeMinLength() (*shared.SizeCapacity, error) {
if len(this.MinLength) == 0 {
return nil, nil
}
capacity := &shared.SizeCapacity{}
err := json.Unmarshal([]byte(this.MinLength), capacity)
err := json.Unmarshal(this.MinLength, capacity)
return capacity, err
}
// 解析最大长度
// DecodeMaxLength 解析最大长度
func (this *HTTPGzip) DecodeMaxLength() (*shared.SizeCapacity, error) {
if len(this.MaxLength) == 0 {
return nil, nil
}
capacity := &shared.SizeCapacity{}
err := json.Unmarshal([]byte(this.MaxLength), capacity)
err := json.Unmarshal(this.MaxLength, capacity)
return capacity, err
}

View File

@@ -236,7 +236,7 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
config := &shared.HTTPHeaderConfig{}
config.Id = int64(header.Id)
config.IsOn = header.IsOn == 1
config.IsOn = header.IsOn
config.Name = header.Name
config.Value = header.Value
config.DisableRedirect = header.DisableRedirect == 1
@@ -244,9 +244,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
// replace
config.ShouldReplace = header.ShouldReplace == 1
if len(header.ReplaceValues) > 0 {
if IsNotNull(header.ReplaceValues) {
var values = []*shared.HTTPHeaderReplaceValue{}
err = json.Unmarshal([]byte(header.ReplaceValues), &values)
err = json.Unmarshal(header.ReplaceValues, &values)
if err != nil {
return nil, err
}
@@ -254,9 +254,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
}
// status
if len(header.Status) > 0 {
if IsNotNull(header.Status) {
status := &shared.HTTPStatusConfig{}
err = json.Unmarshal([]byte(header.Status), status)
err = json.Unmarshal(header.Status, status)
if err != nil {
return nil, err
}
@@ -264,9 +264,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
}
// methods
if len(header.Methods) > 0 {
if IsNotNull(header.Methods) {
var methods = []string{}
err = json.Unmarshal([]byte(header.Methods), &methods)
err = json.Unmarshal(header.Methods, &methods)
if err != nil {
return nil, err
}
@@ -274,9 +274,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
}
// domains
if len(header.Domains) > 0 {
if IsNotNull(header.Domains) {
var domains = []string{}
err = json.Unmarshal([]byte(header.Domains), &domains)
err = json.Unmarshal(header.Domains, &domains)
if err != nil {
return nil, err
}

View File

@@ -1,24 +1,26 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPHeader HTTP Header
type HTTPHeader struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Value string `field:"value"` // 值
Order uint32 `field:"order"` // 排序
Status string `field:"status"` // 状态码设置
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
ReplaceValues string `field:"replaceValues"` // 替换的值
Methods string `field:"methods"` // 支持的方法
Domains string `field:"domains"` // 支持的域名
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Value string `field:"value"` // 值
Order uint32 `field:"order"` // 排序
Status dbs.JSON `field:"status"` // 状态码设置
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
ReplaceValues dbs.JSON `field:"replaceValues"` // 替换的值
Methods dbs.JSON `field:"methods"` // 支持的方法
Domains dbs.JSON `field:"domains"` // 支持的域名
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
}
type HTTPHeaderOperator struct {

View File

@@ -184,12 +184,12 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
config := &shared.HTTPHeaderPolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
// SetHeaders
if len(policy.SetHeaders) > 0 {
if IsNotNull(policy.SetHeaders) {
refs := []*shared.HTTPHeaderRef{}
err = json.Unmarshal([]byte(policy.SetHeaders), &refs)
err = json.Unmarshal(policy.SetHeaders, &refs)
if err != nil {
return nil, err
}
@@ -211,9 +211,9 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
}
// Delete Headers
if len(policy.DeleteHeaders) > 0 {
if IsNotNull(policy.DeleteHeaders) {
headers := []string{}
err = json.Unmarshal([]byte(policy.DeleteHeaders), &headers)
err = json.Unmarshal(policy.DeleteHeaders, &headers)
if err != nil {
return nil, err
}

View File

@@ -1,19 +1,21 @@
package models
import "github.com/iwind/TeaGo/dbs"
//
type HTTPHeaderPolicy struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
AddHeaders string `field:"addHeaders"` // 添加的Header
AddTrailers string `field:"addTrailers"` // 添加的Trailers
SetHeaders string `field:"setHeaders"` // 设置Header
ReplaceHeaders string `field:"replaceHeaders"` // 替换Header内容
Expires string `field:"expires"` // Expires单独设置
DeleteHeaders string `field:"deleteHeaders"` // 删除的Headers
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
AddHeaders dbs.JSON `field:"addHeaders"` // 添加的Header
AddTrailers dbs.JSON `field:"addTrailers"` // 添加的Trailers
SetHeaders dbs.JSON `field:"setHeaders"` // 设置Header
ReplaceHeaders dbs.JSON `field:"replaceHeaders"` // 替换Header内容
Expires dbs.JSON `field:"expires"` // Expires单独设置
DeleteHeaders dbs.JSON `field:"deleteHeaders"` // 删除的Headers
}
type HTTPHeaderPolicyOperator struct {

View File

@@ -170,12 +170,12 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
config := &serverconfigs.HTTPLocationConfig{}
config.Id = int64(location.Id)
config.IsOn = location.IsOn == 1
config.IsOn = location.IsOn
config.Description = location.Description
config.Name = location.Name
config.Pattern = location.Pattern
config.URLPrefix = location.UrlPrefix
config.IsBreak = location.IsBreak == 1
config.IsBreak = location.IsBreak
// web
if location.WebId > 0 {
@@ -189,7 +189,7 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
// reverse proxy
if IsNotNull(location.ReverseProxy) {
ref := &serverconfigs.ReverseProxyRef{}
err = json.Unmarshal([]byte(location.ReverseProxy), ref)
err = json.Unmarshal(location.ReverseProxy, ref)
if err != nil {
return nil, err
}
@@ -204,9 +204,9 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
}
// conds
if len(location.Conds) > 0 {
if IsNotNull(location.Conds) {
conds := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(location.Conds), conds)
err = json.Unmarshal(location.Conds, conds)
if err != nil {
return nil, err
}
@@ -214,9 +214,9 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
}
// domains
if len(location.Domains) > 0 {
if IsNotNull(location.Domains) {
var domains = []string{}
err = json.Unmarshal([]byte(location.Domains), &domains)
err = json.Unmarshal(location.Domains, &domains)
if err != nil {
return nil, err
}
@@ -241,7 +241,7 @@ func (this *HTTPLocationDAO) FindLocationReverseProxy(tx *dbs.Tx, locationId int
if err != nil {
return nil, err
}
if IsNotNull(refString) {
if IsNotNull([]byte(refString)) {
ref := &serverconfigs.ReverseProxyRef{}
err = json.Unmarshal([]byte(refString), ref)
if err != nil {

View File

@@ -1,24 +1,26 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPLocation 路由规则配置
type HTTPLocation struct {
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ParentId uint32 `field:"parentId"` // 父级ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
WebId uint32 `field:"webId"` // Web配置ID
ReverseProxy string `field:"reverseProxy"` // 反向代理
UrlPrefix string `field:"urlPrefix"` // URL前缀
IsBreak uint8 `field:"isBreak"` // 是否终止匹配
Conds string `field:"conds"` // 匹配条件
Domains string `field:"domains"` // 专属域名
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ParentId uint32 `field:"parentId"` // 父级ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
WebId uint32 `field:"webId"` // Web配置ID
ReverseProxy dbs.JSON `field:"reverseProxy"` // 反向代理
UrlPrefix string `field:"urlPrefix"` // URL前缀
IsBreak bool `field:"isBreak"` // 是否终止匹配
Conds dbs.JSON `field:"conds"` // 匹配条件
Domains dbs.JSON `field:"domains"` // 专属域名
}
type HTTPLocationOperator struct {

View File

@@ -77,8 +77,9 @@ func (this *HTTPPageDAO) FindEnabledHTTPPage(tx *dbs.Tx, id int64) (*HTTPPage, e
}
// CreatePage 创建Page
func (this *HTTPPageDAO) CreatePage(tx *dbs.Tx, statusList []string, bodyType shared.BodyType, url string, body string, newStatus int) (pageId int64, err error) {
func (this *HTTPPageDAO) CreatePage(tx *dbs.Tx, userId int64, statusList []string, bodyType shared.BodyType, url string, body string, newStatus int) (pageId int64, err error) {
op := NewHTTPPageOperator()
op.UserId = userId
op.IsOn = true
op.State = HTTPPageStateEnabled
@@ -154,7 +155,7 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
config := &serverconfigs.HTTPPageConfig{}
config.Id = int64(page.Id)
config.IsOn = page.IsOn == 1
config.IsOn = page.IsOn
config.NewStatus = int(page.NewStatus)
config.URL = page.Url
config.Body = page.Body
@@ -166,7 +167,7 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
if len(page.StatusList) > 0 {
statusList := []string{}
err = json.Unmarshal([]byte(page.StatusList), &statusList)
err = json.Unmarshal(page.StatusList, &statusList)
if err != nil {
return nil, err
}
@@ -182,6 +183,26 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
return config, nil
}
// CheckUserPage 检查用户页面
func (this *HTTPPageDAO) CheckUserPage(tx *dbs.Tx, userId int64, pageId int64) error {
if userId <= 0 || pageId <= 0 {
return ErrNotFound
}
b, err := this.Query(tx).
Pk(pageId).
Attr("userId", userId).
State(HTTPPageStateEnabled).
Exist()
if err != nil {
return err
}
if !b {
return ErrNotFound
}
return nil
}
// NotifyUpdate 通知更新
func (this *HTTPPageDAO) NotifyUpdate(tx *dbs.Tx, pageId int64) error {
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithPageId(tx, pageId)

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPPage 特殊页面
type HTTPPage struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
StatusList string `field:"statusList"` // 状态列表
Url string `field:"url"` // 页面URL
NewStatus int32 `field:"newStatus"` // 新状态码
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Body string `field:"body"` // 页面内容
BodyType string `field:"bodyType"` // 内容类型
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
StatusList dbs.JSON `field:"statusList"` // 状态列表
Url string `field:"url"` // 页面URL
NewStatus int32 `field:"newStatus"` // 新状态码
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Body string `field:"body"` // 页面内容
BodyType string `field:"bodyType"` // 内容类型
}
type HTTPPageOperator struct {

View File

@@ -97,19 +97,19 @@ func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int
config := &serverconfigs.HTTPRewriteRule{}
config.Id = int64(rule.Id)
config.IsOn = rule.IsOn == 1
config.IsOn = rule.IsOn
config.Pattern = rule.Pattern
config.Replace = rule.Replace
config.Mode = rule.Mode
config.RedirectStatus = types.Int(rule.RedirectStatus)
config.ProxyHost = rule.ProxyHost
config.IsBreak = rule.IsBreak == 1
config.IsBreak = rule.IsBreak
config.WithQuery = rule.WithQuery == 1
// conds
if len(rule.Conds) > 0 {
conds := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(rule.Conds), conds)
err = json.Unmarshal(rule.Conds, conds)
if err != nil {
return nil, err
}

View File

@@ -1,22 +1,24 @@
package models
import "github.com/iwind/TeaGo/dbs"
// 重写规则
type HTTPRewriteRule struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
Replace string `field:"replace"` // 跳转后的地址
Mode string `field:"mode"` // 替换模式
RedirectStatus uint32 `field:"redirectStatus"` // 跳转的状态码
ProxyHost string `field:"proxyHost"` // 代理的主机名
IsBreak uint8 `field:"isBreak"` // 是否终止解析
WithQuery uint8 `field:"withQuery"` // 是否保留URI参数
Conds string `field:"conds"` // 匹配条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn bool `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
Replace string `field:"replace"` // 跳转后的地址
Mode string `field:"mode"` // 替换模式
RedirectStatus uint32 `field:"redirectStatus"` // 跳转的状态码
ProxyHost string `field:"proxyHost"` // 代理的主机名
IsBreak bool `field:"isBreak"` // 是否终止解析
WithQuery uint8 `field:"withQuery"` // 是否保留URI参数
Conds dbs.JSON `field:"conds"` // 匹配条件
}
type HTTPRewriteRuleOperator struct {

View File

@@ -3,6 +3,7 @@ package models
import (
"encoding/json"
"errors"
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
@@ -94,14 +95,14 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
return nil, nil
}
config := &serverconfigs.HTTPWebConfig{}
var config = &serverconfigs.HTTPWebConfig{}
config.Id = webId
config.IsOn = web.IsOn == 1
config.IsOn = web.IsOn
// root
if IsNotNull(web.Root) {
rootConfig := &serverconfigs.HTTPRootConfig{}
err = json.Unmarshal([]byte(web.Root), rootConfig)
err = json.Unmarshal(web.Root, rootConfig)
if err != nil {
return nil, err
}
@@ -111,7 +112,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// compression
if IsNotNull(web.Compression) {
compression := &serverconfigs.HTTPCompressionConfig{}
err = json.Unmarshal([]byte(web.Compression), compression)
err = json.Unmarshal(web.Compression, compression)
if err != nil {
return nil, err
}
@@ -148,7 +149,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// charset
if IsNotNull(web.Charset) {
charsetConfig := &serverconfigs.HTTPCharsetConfig{}
err = json.Unmarshal([]byte(web.Charset), charsetConfig)
err = json.Unmarshal(web.Charset, charsetConfig)
if err != nil {
return nil, err
}
@@ -158,7 +159,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// headers
if IsNotNull(web.RequestHeader) {
ref := &shared.HTTPHeaderPolicyRef{}
err = json.Unmarshal([]byte(web.RequestHeader), ref)
err = json.Unmarshal(web.RequestHeader, ref)
if err != nil {
return nil, err
}
@@ -177,7 +178,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
if IsNotNull(web.ResponseHeader) {
ref := &shared.HTTPHeaderPolicyRef{}
err = json.Unmarshal([]byte(web.ResponseHeader), ref)
err = json.Unmarshal(web.ResponseHeader, ref)
if err != nil {
return nil, err
}
@@ -197,7 +198,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// shutdown
if IsNotNull(web.Shutdown) {
shutdownConfig := &serverconfigs.HTTPShutdownConfig{}
err = json.Unmarshal([]byte(web.Shutdown), shutdownConfig)
err = json.Unmarshal(web.Shutdown, shutdownConfig)
if err != nil {
return nil, err
}
@@ -207,7 +208,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// pages
if IsNotNull(web.Pages) {
pages := []*serverconfigs.HTTPPageConfig{}
err = json.Unmarshal([]byte(web.Pages), &pages)
err = json.Unmarshal(web.Pages, &pages)
if err != nil {
return nil, err
}
@@ -226,7 +227,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 访问日志
if IsNotNull(web.AccessLog) {
accessLogConfig := &serverconfigs.HTTPAccessLogRef{}
err = json.Unmarshal([]byte(web.AccessLog), accessLogConfig)
err = json.Unmarshal(web.AccessLog, accessLogConfig)
if err != nil {
return nil, err
}
@@ -236,7 +237,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 统计配置
if IsNotNull(web.Stat) {
statRef := &serverconfigs.HTTPStatRef{}
err = json.Unmarshal([]byte(web.Stat), statRef)
err = json.Unmarshal(web.Stat, statRef)
if err != nil {
return nil, err
}
@@ -246,7 +247,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 缓存配置
if IsNotNull(web.Cache) {
cacheConfig := &serverconfigs.HTTPCacheConfig{}
err = json.Unmarshal([]byte(web.Cache), &cacheConfig)
err = json.Unmarshal(web.Cache, &cacheConfig)
if err != nil {
return nil, err
}
@@ -258,7 +259,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 防火墙配置
if IsNotNull(web.Firewall) {
firewallRef := &firewallconfigs.HTTPFirewallRef{}
err = json.Unmarshal([]byte(web.Firewall), firewallRef)
err = json.Unmarshal(web.Firewall, firewallRef)
if err != nil {
return nil, err
}
@@ -281,7 +282,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 路由规则
if IsNotNull(web.Locations) {
refs := []*serverconfigs.HTTPLocationRef{}
err = json.Unmarshal([]byte(web.Locations), &refs)
err = json.Unmarshal(web.Locations, &refs)
if err != nil {
return nil, err
}
@@ -299,7 +300,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 跳转
if IsNotNull(web.RedirectToHttps) {
redirectToHTTPSConfig := &serverconfigs.HTTPRedirectToHTTPSConfig{}
err = json.Unmarshal([]byte(web.RedirectToHttps), redirectToHTTPSConfig)
err = json.Unmarshal(web.RedirectToHttps, redirectToHTTPSConfig)
if err != nil {
return nil, err
}
@@ -309,7 +310,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// Websocket
if IsNotNull(web.Websocket) {
ref := &serverconfigs.HTTPWebsocketRef{}
err = json.Unmarshal([]byte(web.Websocket), ref)
err = json.Unmarshal(web.Websocket, ref)
if err != nil {
return nil, err
}
@@ -328,7 +329,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 重写规则
if IsNotNull(web.RewriteRules) {
refs := []*serverconfigs.HTTPRewriteRef{}
err = json.Unmarshal([]byte(web.RewriteRules), &refs)
err = json.Unmarshal(web.RewriteRules, &refs)
if err != nil {
return nil, err
}
@@ -347,7 +348,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 主机跳转
if IsNotNull(web.HostRedirects) {
redirects := []*serverconfigs.HTTPHostRedirectConfig{}
err = json.Unmarshal([]byte(web.HostRedirects), &redirects)
err = json.Unmarshal(web.HostRedirects, &redirects)
if err != nil {
return nil, err
}
@@ -357,7 +358,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// Fastcgi
if IsNotNull(web.Fastcgi) {
ref := &serverconfigs.HTTPFastcgiRef{}
err = json.Unmarshal([]byte(web.Fastcgi), ref)
err = json.Unmarshal(web.Fastcgi, ref)
if err != nil {
return nil, err
}
@@ -381,7 +382,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 认证
if IsNotNull(web.Auth) {
authConfig := &serverconfigs.HTTPAuthConfig{}
err = json.Unmarshal([]byte(web.Auth), authConfig)
err = json.Unmarshal(web.Auth, authConfig)
if err != nil {
return nil, err
}
@@ -402,7 +403,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// WebP
if IsNotNull(web.Webp) {
var webpConfig = &serverconfigs.WebPImageConfig{}
err = json.Unmarshal([]byte(web.Webp), webpConfig)
err = json.Unmarshal(web.Webp, webpConfig)
if err != nil {
return nil, err
}
@@ -412,7 +413,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// RemoteAddr
if IsNotNull(web.RemoteAddr) {
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{}
err = json.Unmarshal([]byte(web.RemoteAddr), remoteAddrConfig)
err = json.Unmarshal(web.RemoteAddr, remoteAddrConfig)
if err != nil {
return nil, err
}
@@ -426,7 +427,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
if len(web.RequestLimit) > 0 {
var requestLimitConfig = &serverconfigs.HTTPRequestLimitConfig{}
if len(web.RequestLimit) > 0 {
err = json.Unmarshal([]byte(web.RequestLimit), requestLimitConfig)
err = json.Unmarshal(web.RequestLimit, requestLimitConfig)
if err != nil {
return nil, err
}
@@ -438,7 +439,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
if len(web.RequestScripts) > 0 {
var requestScriptsConfig = &serverconfigs.HTTPRequestScriptsConfig{}
if len(web.RequestScripts) > 0 {
err = json.Unmarshal([]byte(web.RequestScripts), requestScriptsConfig)
err = json.Unmarshal(web.RequestScripts, requestScriptsConfig)
if err != nil {
return nil, err
}
@@ -446,6 +447,16 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
}
}
// UAM
if teaconst.IsPlus && IsNotNull(web.Uam) {
var uamConfig = &serverconfigs.UAMConfig{}
err = json.Unmarshal(web.Uam, uamConfig)
if err != nil {
return nil, err
}
config.UAM = uamConfig
}
if cacheMap != nil {
cacheMap.Put(cacheKey, config)
}
@@ -1168,6 +1179,35 @@ func (this *HTTPWebDAO) FindWebRequestScripts(tx *dbs.Tx, webId int64) (*serverc
return config, nil
}
// UpdateWebUAM 开启UAM
func (this *HTTPWebDAO) UpdateWebUAM(tx *dbs.Tx, webId int64, uamConfig *serverconfigs.UAMConfig) error {
if uamConfig == nil {
return nil
}
configJSON, err := json.Marshal(uamConfig)
if err != nil {
return err
}
err = this.Query(tx).
Pk(webId).
Set("uam", configJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, webId)
}
// FindWebUAM 查找服务的UAM配置
func (this *HTTPWebDAO) FindWebUAM(tx *dbs.Tx, webId int64) ([]byte, error) {
return this.Query(tx).
Pk(webId).
Result("uam").
FindJSONCol()
}
// NotifyUpdate 通知更新
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
// server

View File

@@ -1,40 +1,43 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPWeb HTTP Web
type HTTPWeb struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Root string `field:"root"` // 根目录
Charset string `field:"charset"` // 字符集
Shutdown string `field:"shutdown"` // 临时关闭页面配置
Pages string `field:"pages"` // 特殊页面
RedirectToHttps string `field:"redirectToHttps"` // 跳转到HTTPS设置
Indexes string `field:"indexes"` // 首页文件列表
MaxRequestBodySize string `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸
RequestHeader string `field:"requestHeader"` // 请求Header配置
ResponseHeader string `field:"responseHeader"` // 响应Header配置
AccessLog string `field:"accessLog"` // 访问日志配置
Stat string `field:"stat"` // 统计配置
Gzip string `field:"gzip"` // Gzip配置v0.3.2弃用)
Compression string `field:"compression"` // 压缩配置
Cache string `field:"cache"` // 缓存配置
Firewall string `field:"firewall"` // 防火墙设置
Locations string `field:"locations"` // 路由规则配置
Websocket string `field:"websocket"` // Websocket设置
RewriteRules string `field:"rewriteRules"` // 重写规则配置
HostRedirects string `field:"hostRedirects"` // 域名跳转
Fastcgi string `field:"fastcgi"` // Fastcgi配置
Auth string `field:"auth"` // 认证策略配置
Webp string `field:"webp"` // WebP配置
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
RequestLimit string `field:"requestLimit"` // 请求限制
RequestScripts string `field:"requestScripts"` // 请求脚本
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Root dbs.JSON `field:"root"` // 根目录
Charset dbs.JSON `field:"charset"` // 字符集
Shutdown dbs.JSON `field:"shutdown"` // 临时关闭页面配置
Pages dbs.JSON `field:"pages"` // 特殊页面
RedirectToHttps dbs.JSON `field:"redirectToHttps"` // 跳转到HTTPS设置
Indexes dbs.JSON `field:"indexes"` // 首页文件列表
MaxRequestBodySize dbs.JSON `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸
RequestHeader dbs.JSON `field:"requestHeader"` // 请求Header配置
ResponseHeader dbs.JSON `field:"responseHeader"` // 响应Header配置
AccessLog dbs.JSON `field:"accessLog"` // 访问日志配置
Stat dbs.JSON `field:"stat"` // 统计配置
Gzip dbs.JSON `field:"gzip"` // Gzip配置v0.3.2弃用)
Compression dbs.JSON `field:"compression"` // 压缩配置
Cache dbs.JSON `field:"cache"` // 缓存配置
Firewall dbs.JSON `field:"firewall"` // 防火墙设置
Locations dbs.JSON `field:"locations"` // 路由规则配置
Websocket dbs.JSON `field:"websocket"` // Websocket设置
RewriteRules dbs.JSON `field:"rewriteRules"` // 重写规则配置
HostRedirects dbs.JSON `field:"hostRedirects"` // 域名跳转
Fastcgi dbs.JSON `field:"fastcgi"` // Fastcgi配置
Auth dbs.JSON `field:"auth"` // 认证策略配置
Webp dbs.JSON `field:"webp"` // WebP配置
RemoteAddr dbs.JSON `field:"remoteAddr"` // 客户端IP配置
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
RequestLimit dbs.JSON `field:"requestLimit"` // 请求限制
RequestScripts dbs.JSON `field:"requestScripts"` // 请求脚本
Uam dbs.JSON `field:"uam"` // UAM设置
}
type HTTPWebOperator struct {
@@ -71,6 +74,7 @@ type HTTPWebOperator struct {
MergeSlashes interface{} // 是否合并路径中的斜杠
RequestLimit interface{} // 请求限制
RequestScripts interface{} // 请求脚本
Uam interface{} // UAM设置
}
func NewHTTPWebOperator() *HTTPWebOperator {

View File

@@ -37,7 +37,7 @@ func init() {
})
}
// 启用条目
// EnableHTTPWebsocket 启用条目
func (this *HTTPWebsocketDAO) EnableHTTPWebsocket(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
@@ -46,7 +46,7 @@ func (this *HTTPWebsocketDAO) EnableHTTPWebsocket(tx *dbs.Tx, id int64) error {
return err
}
// 禁用条目
// DisableHTTPWebsocket 禁用条目
func (this *HTTPWebsocketDAO) DisableHTTPWebsocket(tx *dbs.Tx, websocketId int64) error {
_, err := this.Query(tx).
Pk(websocketId).
@@ -58,7 +58,7 @@ func (this *HTTPWebsocketDAO) DisableHTTPWebsocket(tx *dbs.Tx, websocketId int64
return this.NotifyUpdate(tx, websocketId)
}
// 查找启用中的条目
// FindEnabledHTTPWebsocket 查找启用中的条目
func (this *HTTPWebsocketDAO) FindEnabledHTTPWebsocket(tx *dbs.Tx, id int64) (*HTTPWebsocket, error) {
result, err := this.Query(tx).
Pk(id).
@@ -70,7 +70,7 @@ func (this *HTTPWebsocketDAO) FindEnabledHTTPWebsocket(tx *dbs.Tx, id int64) (*H
return result.(*HTTPWebsocket), err
}
// 组合配置
// ComposeWebsocketConfig 组合配置
func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int64) (*serverconfigs.HTTPWebsocketConfig, error) {
websocket, err := this.FindEnabledHTTPWebsocket(tx, websocketId)
if err != nil {
@@ -81,12 +81,12 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
}
config := &serverconfigs.HTTPWebsocketConfig{}
config.Id = int64(websocket.Id)
config.IsOn = websocket.IsOn == 1
config.IsOn = websocket.IsOn
config.AllowAllOrigins = websocket.AllowAllOrigins == 1
if IsNotNull(websocket.AllowedOrigins) {
origins := []string{}
err = json.Unmarshal([]byte(websocket.AllowedOrigins), &origins)
err = json.Unmarshal(websocket.AllowedOrigins, &origins)
if err != nil {
return nil, err
}
@@ -95,7 +95,7 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
if IsNotNull(websocket.HandshakeTimeout) {
duration := &shared.TimeDuration{}
err = json.Unmarshal([]byte(websocket.HandshakeTimeout), duration)
err = json.Unmarshal(websocket.HandshakeTimeout, duration)
if err != nil {
return nil, err
}
@@ -108,7 +108,7 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
return config, nil
}
// 创建Websocket配置
// CreateWebsocket 创建Websocket配置
func (this *HTTPWebsocketDAO) CreateWebsocket(tx *dbs.Tx, handshakeTimeoutJSON []byte, allowAllOrigins bool, allowedOrigins []string, requestSameOrigin bool, requestOrigin string) (websocketId int64, err error) {
op := NewHTTPWebsocketOperator()
op.IsOn = true
@@ -130,7 +130,7 @@ func (this *HTTPWebsocketDAO) CreateWebsocket(tx *dbs.Tx, handshakeTimeoutJSON [
return types.Int64(op.Id), err
}
// 修改Websocket配置
// UpdateWebsocket 修改Websocket配置
func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, handshakeTimeoutJSON []byte, allowAllOrigins bool, allowedOrigins []string, requestSameOrigin bool, requestOrigin string) error {
if websocketId <= 0 {
return errors.New("invalid websocketId")
@@ -159,7 +159,7 @@ func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, han
return this.NotifyUpdate(tx, websocketId)
}
// 通知更新
// NotifyUpdate 通知更新
func (this *HTTPWebsocketDAO) NotifyUpdate(tx *dbs.Tx, websocketId int64) error {
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithWebsocketId(tx, websocketId)
if err != nil {

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