Compare commits

..
175 Commits
Author SHA1 Message Date
ssongliu 67ce559b12 fix: 概览页磁盘信息获取增加锁 (#3100) 2023-11-29 15:34:51 +08:00
ssongliu 71869b7264 fix: 概览页磁盘显示优化 (#3096) 2023-11-29 14:44:02 +08:00
ssongliu 03774bbba6 fix: 概览页磁盘信息获取增加超时时间 (#3074)
Refs #2825
2023-11-28 15:10:35 +08:00
igophper e07b6bc050 fix: 类名重命名 2023-11-28 15:10:26 +08:00
igophper b1935d8368 fix: 修复网站404重定向次数过多 (#3054) (#3056)
Refs #3054
2023-11-28 15:10:17 +08:00
江杭辉 f8e344db76 fix: 修复登录菜单消失 2023-11-23 22:20:06 +08:00
江杭辉 2c3a8dd6af fix: 修复登录菜单消失 2023-11-23 22:20:01 +08:00
江杭辉 86e5fc36f4 fix: 修复登录菜单消失 2023-11-23 22:19:56 +08:00
江杭辉 858cefc0c9 fix: mfa登录菜单消失 2023-11-23 22:19:53 +08:00
ssongliu 4535c0b90b fix: 解决镜像仓库编辑失败的问题 (#3029) 2023-11-23 22:19:43 +08:00
zhengkunwang 136489e346 fix: 解决网站某些设置会报服务器内部错误的问题 (#2973)
Refs https://github.com/1Panel-dev/1Panel/issues/2955
2023-11-23 22:18:20 +08:00
wanghe e2882fd1cc Update sonar-project.properties (#3004) 2023-11-23 22:17:15 +08:00
hzz dba97076df fix: 本地数据备份命令增加 --default-character-set 参数 与备份还原的编码保持一致 2023-11-23 22:17:02 +08:00
QuentinHsu 000bcd37c1 fix: FileRole 初始化 (#2956) 2023-11-23 22:16:53 +08:00
wanghe bf28223745 Update README.md (#2937) 2023-11-23 22:16:47 +08:00
maninhill 1fed5c4d15 Update README.md 2023-11-23 22:16:42 +08:00
ssongliu aa1f2d0f01 fix: 优化镜像清理弹框内容显示 (#2931)
Refs #2928
2023-11-13 08:56:08 +00:00
zhengkunwang 80c68b8e49 fix: 解决部分文件不能上传的问题 (#2933) 2023-11-13 08:52:08 +00:00
ssongliu fb556d6149 feat: 概览页重启按钮优化 (#2926)
Refs #2921
2023-11-13 07:02:08 +00:00
zhengkunwang 78576a3724 fix: 解决文件上传多选可能导致的文件列表丢失的问题 (#2925) 2023-11-13 07:00:08 +00:00
zhengkunwang e09cefd0f7 fix: logr 依赖回退版本 (#2920) 2023-11-13 11:30:59 +08:00
zhengkunwang ed3262a07c fix: 解决 Openresty 性能调整保存报错的问题 (#2919) 2023-11-13 03:14:08 +00:00
dependabot[bot] b904650682 build(deps): bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc (#2916)
Bumps [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.44.0 to 0.46.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.44.0...zpages/v0.46.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 09:18:46 +08:00
QuentinHsu abb3073251 perf: home page style (#2911) 2023-11-13 09:14:58 +08:00
dependabot[bot] d8d46aa27c build(deps): bump axios from 0.27.2 to 1.6.0 in /frontend
Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 1.6.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.27.2...v1.6.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-12 02:20:36 +08:00
QuentinHsu 0737a75bd3 perf: 弹窗操作的 successMsg 参数 2023-11-12 02:19:23 +08:00
zhengkunwang 7667399c5e fix: 解决网站密码访问启动报错的问题 (#2891)
Refs #2894
2023-11-10 15:08:09 +00:00
QuentinHsu 0a003d3750 perf: 弹窗操作的 successMsg 参数 (#2892) 2023-11-10 23:07:16 +08:00
zhengkunwang adc34aaf75 feat: 增加文件压缩解压的超时时间 (#2886)
Refs https://github.com/1Panel-dev/1Panel/issues/2884
2023-11-10 09:04:07 +00:00
zhengkunwang acb0bf2bfd fix: 解决网站设置默认站点失败的问题 (#2885) 2023-11-10 08:54:07 +00:00
zhengkunwang 88ad8b1b71 fix: 解决文件复制粘贴路径中带空格导致失败的问题 (#2883)
Refs https://github.com/1Panel-dev/1Panel/issues/2877
2023-11-10 08:38:07 +00:00
zhengkunwang 8660ac6fe5 fix: 解决本地应用备份恢复报错的问题 (#2879)
Refs https://github.com/1Panel-dev/1Panel/issues/2854
2023-11-10 07:06:07 +00:00
zhengkunwang 24098e397f feat: 取消检测文件是否存在接口的日志打印 (#2878) 2023-11-10 06:36:07 +00:00
zhengkunwang 21f9e4f201 fix: 解决网站反向代理缓存时间选择年报错的问题 (#2873)
Refs https://github.com/1Panel-dev/1Panel/issues/2866
2023-11-10 03:04:06 +00:00
zhengkunwang f60500791a feat: 增加证书续签的超时时间 (#2869) 2023-11-09 13:58:07 +00:00
zhengkunwang 70c0602970 fix: 解决网站保存设置报错的问题 (#2864) 2023-11-09 13:56:06 +00:00
Node adfa021760 fix:解决备份还原到新建应用失败的问题 #2854 (#2863) 2023-11-09 21:53:38 +08:00
Node 0e93d7815b feat:增加控制台静态资源/assets/浏览器缓存 (#2859)
#### What this PR does / why we need it?
当前操作控制台(每点击一个不同的页面)或刷新后,都需要从服务器加载静态资源且没有缓存,在网络差的情况下访问特别慢

#### Summary of your change
给静态资源增加浏览器缓存时间
#### Please indicate you've done the following:

- [x] Made sure tests are passing and test coverage is added if needed.
- [x] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [x] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-11-09 02:44:15 +00:00
zhengkunwang 253776d6fe fix: 解决选择单个文件复制再选多个文件之后显示异常的问题 (#2852) 2023-11-08 08:55:29 +00:00
ssongliu 7082e2fa43 fix: 修改 ssh 开启自启状态判断 (#2851) 2023-11-08 08:53:29 +00:00
zhengkunwang 01f5c868b7 fix: 解决网站域名重复端口不能提交的问题 (#2850) 2023-11-08 08:41:29 +00:00
ssongliu ac97d3c05a fix: 解决系统别名导致无法修改开机自启的问题 (#2849) 2023-11-08 08:19:29 +00:00
ssongliu e8ee373fc4 fix: 处理容器日志导致的僵尸进程 (#2847)
Refs #2846
2023-11-08 06:29:30 +00:00
ssongliu 460687928a fix: 修改文件删除样式 (#2848) 2023-11-08 06:27:29 +00:00
zhengkunwang e279362b85 fix: 解决反代保存失败的问题 (#2845) 2023-11-08 02:39:29 +00:00
zhengkunwang 4b4f53d09b fix: 解决上传文件夹失败的问题 (#2843) 2023-11-08 02:37:30 +00:00
zhengkunwang 8599a858e4 feat: 前后端域名校验保持一致 (#2842) 2023-11-08 02:35:29 +00:00
zhengkunwang 1a820e00ff feat: 回收站选择为空的时候禁用删除按钮 (#2841) 2023-11-08 02:33:29 +00:00
ssongliu 53e18b2aee fix: 缓存容器刷新状态 (#2840) 2023-11-08 01:37:29 +00:00
ssongliu d8588d06ce fix: 解决主机默认分组失败的问题 (#2839) 2023-11-07 15:41:28 +00:00
ssongliu 8adca0efa2 fix: 主机连接、数据库连接适配 IPv6 (#2832) 2023-11-07 06:09:28 +00:00
zhengkunwang fbc34c2847 feat: 修改应用升级流程 (#2831) 2023-11-07 06:07:30 +00:00
zhengkunwang 80f916f4c7 feat: 优化文件复制-粘贴逻辑 (#2830) 2023-11-07 06:05:28 +00:00
zhengkunwang dd60eb099d fix: 解决日志审计-网站切换网站日志显示错误的问题 (#2829) 2023-11-07 04:19:29 +00:00
zhengkunwang ebe74d905c fix: 解决日志审计-网站日志的错误日志不显示的问题 (#2828) 2023-11-07 04:17:28 +00:00
zhengkunwang 09447e4988 fix: 解决 PHP 版本切换可以选择 Node.js 的问题 (#2827) 2023-11-07 03:25:28 +00:00
ssongliu bb93cb076e fix: 解决 UFW 防火墙启用失败的问题 (#2823)
Refs #2811
2023-11-06 13:27:28 +00:00
zhengkunwang 8d9b21e4a2 fix: 解决反代域名失败的问题 (#2821) 2023-11-06 12:11:28 +00:00
zhengkunwang ce38ae2544 fix: 解决移动文件夹,所选路径下有同名文件夹时会在同名文件夹下再创建一个文件夹的问题 (#2819) 2023-11-06 06:14:31 +00:00
ssongliu 262ddb5f12 fix: 解决 UFW 防火墙规则为空时插入规则失败的问题 (#2816)
Refs #2794
2023-11-06 02:54:39 +00:00
zhengkunwang cd5658adab fix: 解决 zip 压缩在某些情况下失败的问题 (#2809) 2023-11-05 13:43:32 +00:00
zhengkunwang 9d1757dba6 feat: Node.js 运行环境外部映射端口增加校验 (#2808) 2023-11-05 13:41:31 +00:00
zhengkunwang e43de97890 feat: 创建网站-其他域名增加端口校验 (#2807) 2023-11-05 13:39:36 +00:00
zhengkunwang 76f495fc83 fix: 解决文件拖拽上传空文件夹失败的问题 (#2806) 2023-11-05 13:37:40 +00:00
zhengkunwang 78f07eb574 fix: 文件复制粘贴,选择覆盖已存在文件,限制修改文件名 (#2805) 2023-11-05 13:35:44 +00:00
zhengkunwang 1fc75ac000 fix: 解决排序之后获取文件夹大小导致排序失效的问题 (#2804) 2023-11-05 13:33:40 +00:00
ssongliu dedfe1e1e1 feat: 服务升级重启等操作时取消前端定时请求 (#2801) 2023-11-04 21:46:23 +08:00
zhengkunwang 4b69d77d3c fix: 解决批量修改文件权限错误的问题 (#2799) 2023-11-03 10:51:43 +00:00
ssongliu be46fc26df fix: 解决计划任务备份日志的一些问题 (#2798) 2023-11-03 10:23:41 +00:00
zhengkunwang 6546c10fb8 fix: 解决收藏夹和回收站切换每页数量不生效的问题 (#2797) 2023-11-03 10:21:46 +00:00
zhengkunwang dc420256e2 feat: 网站 WAF 增加 user-agent 过滤 (#2796) 2023-11-03 10:19:45 +00:00
zhengkunwang a55d571bc9 feat: 优化应用商店同步 (#2795) 2023-11-03 10:18:12 +00:00
zhengkunwang 5ff23f44d5 feat: host 模式应用增加提示 (#2792) 2023-11-03 07:39:38 +00:00
ssongliu 0d9fc1ccee feat: 优化防火墙错误返回 (#2791) 2023-11-03 06:38:13 +00:00
zhengkunwang 6a989482a9 fix: 解决文件名和图标堆叠显示问题 (#2790) 2023-11-03 06:32:14 +00:00
ssongliu 7e00b46d5c fix: 解决计划任务备份日志报错的问题 (#2786) 2023-11-03 03:18:45 +00:00
ssongliu 46320634f6 fix: 解决 firewalld 防火墙规则 ipv6 下不生效的问题 (#2789) 2023-11-03 03:14:43 +00:00
dependabot[bot] b42a500c62 build(deps): bump golang.org/x/image from 0.5.0 to 0.10.0 (#2788)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.5.0 to 0.10.0.
- [Commits](https://github.com/golang/image/compare/v0.5.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-03 10:56:58 +08:00
wangdan-fit2cloud 67371dff06 fix: 修复黑色主题部分样式 (#2780)
#### What this PR does / why we need it?

#### Summary of your change

#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-11-02 12:53:55 +00:00
zhengkunwang 51cbd7bf9c feat: 新增批量修改文件权限功能 (#2778)
Refs https://github.com/1Panel-dev/1Panel/issues/1330
2023-11-02 10:38:50 +00:00
zhengkunwang eebef06c77 feat: 域名支持批量添加 (#2774)
Refs https://github.com/1Panel-dev/1Panel/issues/2633
2023-11-02 10:36:55 +00:00
ssongliu 082032e15f fix: 解决主机标题显示不一致的问题 (#2779) 2023-11-02 10:23:00 +00:00
ssongliu f14b8641d3 feat: 服务启动时自动同步系统时间 (#2775)
Refs #2747
2023-11-02 10:22:41 +00:00
zhengkunwang 47b75673f9 feat: 处理 1Panel 重启导致运行环境状态异常的问题 (#2773) 2023-11-02 06:35:58 +00:00
ssongliu 2d8a7bbbc3 feat: 腾讯 COS 支持大文件分片上传 (#2772) 2023-11-02 06:29:46 +00:00
ssongliu 05029a3eda fix: 调整面板设置样式 (#2765) 2023-11-01 14:25:08 +00:00
zhengkunwang d15bd1d6b4 feat: PHP 运行环境增加日志 (#2764)
Refs https://github.com/1Panel-dev/1Panel/issues/2761
2023-11-01 10:30:56 +00:00
zhengkunwang c47075beeb feat: 文件复制、粘贴操作支持修改名称 (#2763)
Refs https://github.com/1Panel-dev/1Panel/issues/1570
2023-11-01 10:27:19 +00:00
ssongliu f6b094039b fix: 修改 SSH 端口时自动放开防火墙 (#2760)
Refs #2729
2023-11-01 09:12:01 +00:00
ssongliu 30c23a237f fix: 解决依赖升级导致无法启动的问题 (#2759) 2023-11-01 06:24:10 +00:00
zhengkunwang 9acd315fef style: 修改文件列表部分样式 (#2758) 2023-11-01 06:22:33 +00:00
ssongliu 00cad5b586 fix: 处理代码警告 (#2756) 2023-11-01 05:49:30 +00:00
ssongliu 0b67c8dfc9 fix: 登陆增加参数校验 (#2751) 2023-11-01 13:48:06 +08:00
zhengkunwang 94ca229e71 fix: 解决部分情况下文件移动失败的问题 (#2752)
Refs https://github.com/1Panel-dev/1Panel/issues/1095
2023-11-01 03:51:30 +00:00
dependabot[bot] b76d73dc13 build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace (#2754)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.40.0 to 0.44.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.40.0...zpages/v0.44.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 11:33:22 +08:00
dependabot[bot] 919cd9d74f build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#2753)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.40.0 to 0.44.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.40.0...zpages/v0.44.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 11:27:05 +08:00
ssongliu 909f8c96e2 fix: 解决部分机器监听 IPv4 失败的问题 (#2750) 2023-11-01 02:48:38 +00:00
ssongliu 34ca984018 fix: 解决启用 https 时无法访问的问题 (#2745) 2023-10-31 13:59:39 +00:00
ssongliu 000f175d97 fix: 修改计划任务样式 (#2744) 2023-10-31 12:49:53 +00:00
zhengkunwang e35d0c9aed fix: 优化证书申请超时问题 (#2742)
Refs https://github.com/1Panel-dev/1Panel/issues/2447
2023-10-31 12:47:56 +00:00
zhengkunwang b6fc1efd6a style: 修改文件列表部分样式 (#2741) 2023-10-31 12:45:57 +00:00
zhengkunwang223 9198707ca4 fix: 解决编辑 PHP 运行环境版本显示错误的问题 2023-10-31 20:25:36 +08:00
ssongliu b5f2716299 fix: 解决概览页样式不统一的问题 (#2740)
Refs #2728
2023-10-31 10:53:07 +00:00
ssongliu ded99190c1 fix: 解决容器端口解析失败的问题 (#2739) 2023-10-31 10:03:51 +00:00
zhengkunwang bc80dfdc68 fix: 解决 PHP 网站切换版本导致 serviceName 变更的问题 (#2737)
Refs https://github.com/1Panel-dev/1Panel/issues/2689
2023-10-31 09:53:50 +00:00
zhengkunwang d43bc3e427 feat: 证书页面增加上传证书功能 (#2735)
Refs https://github.com/1Panel-dev/1Panel/issues/1323
2023-10-31 08:01:50 +00:00
ssongliu c526e7a5ac fix: 升级 Go 到 1.20.10 (#2736) 2023-10-31 07:57:49 +00:00
wanghe c78e9cf350 chore: Update README.md (#2734) 2023-10-31 14:33:58 +08:00
ssongliu 824476992b fix: 解决自动升级导致的代码问题 (#2733) 2023-10-31 06:14:41 +00:00
ssongliu fe1290e933 fix: 快速命令增加分组 (#2732)
Refs #2725
2023-10-31 06:14:30 +00:00
zhengkunwang 45d233bade feat: 修改部分接口报错和页面显示问题 (#2731) 2023-10-31 05:51:00 +00:00
dependabot[bot] c346cae288 build(deps): bump github.com/docker/docker (#2730)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.3+incompatible to 24.0.7+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v23.0.3...v24.0.7)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 10:43:55 +08:00
ssongliu e9007ad8f3 fix: 统一网站等删除样式 (#2724) 2023-10-30 10:36:55 +00:00
ssongliu 5e27aa04dd fix: 统一删除提示框 (#2711) 2023-10-28 03:11:31 +00:00
ssongliu 32c6826496 fix: 解决终端连接无法正常打开的问题 (#2710) 2023-10-27 09:19:04 +00:00
zhengkunwang e952b77334 fix: 解决网站日志审计切换网站日志显示错误的问题 (#2708)
Refs https://github.com/1Panel-dev/1Panel/issues/2670
2023-10-27 07:27:25 +00:00
zhengkunwang 1ca199ac6b fix: 解决网站域名可以重复添加的问题 (#2707)
Refs https://github.com/1Panel-dev/1Panel/issues/2636
2023-10-27 07:13:25 +00:00
ssongliu abedc724df fix: 压缩过程忽略 .sock 套接字 (#2706)
Refs #2702
2023-10-27 07:05:25 +00:00
ssongliu 12dcb4d646 fix: 简化接口校验代码 (#2704) 2023-10-27 06:19:26 +00:00
maninhill 63bbc0242c Update README.md 2023-10-27 14:16:20 +08:00
zhengkunwang 6c1d769d15 feat: 统一修改部分接口参数校验 (#2703) 2023-10-27 04:04:11 +00:00
zhengkunwang 18de677636 fix: 解决可以创建同名网站的问题 (#2701) 2023-10-27 04:02:15 +00:00
ssongliu de2cac5ebc fix: 面板设置样式调整 (#2700) 2023-10-27 03:54:11 +00:00
zhengkunwang 6c957d157b fix: 解决创建网站报端口被占用的问题 (#2699)
Refs https://github.com/1Panel-dev/1Panel/issues/2695
2023-10-27 03:00:16 +00:00
zhengkunwang 048df6f390 feat: Node.js 运行环境增加多端口 (#2691)
Refs https://github.com/1Panel-dev/1Panel/issues/2566
2023-10-27 02:12:15 +00:00
ssongliu 8857d97dd7 fix: 统一删除提示信息及样式 (#2690) 2023-10-26 10:20:16 +00:00
dependabot[bot] 3f6ea63d73 build(deps): bump google.golang.org/grpc from 1.53.0 to 1.56.3 (#2682)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.56.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.56.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-26 09:32:11 +08:00
ssongliu 0dd14ddeff fix: 解决页面加载先后导致的分页错误问题 (#2680)
Refs #2674
2023-10-25 15:01:29 +00:00
ssongliu 0ed1b1aceb fix: 解决未设置默认字符集导致数据库导入备份失败的问题 (#2678)
Refs #2657
2023-10-25 14:59:33 +00:00
zhengkunwang 5db6e7eb68 feat: Node.js 运行环境增加自定义启动命令 (#2677)
Refs https://github.com/1Panel-dev/1Panel/issues/2559
2023-10-25 08:05:03 +00:00
ssongliu 87cd5c957c fix: 优化终端界面菜单按钮样式 (#2676)
Refs #2669
2023-10-25 07:44:36 +00:00
ssongliu b0e8787f05 fix: 修改计划任务脚本执行状态判断 (#2675)
Refs #2652
2023-10-25 07:28:36 +00:00
ssongliu 084351a063 feat: 命令行支持切换监听 IP (#2671) 2023-10-25 03:13:26 +00:00
zhengkunwang 287f047a7b fix: 修改部分错误代码 (#2673) 2023-10-25 03:01:27 +00:00
zhengkunwang 86b6afe0b4 feat: 1Panel 日志文件取消压缩 (#2672) 2023-10-25 02:59:26 +00:00
ssongliu d638796798 feat: 面板设置增加监听地址 (#2663) 2023-10-25 02:41:26 +00:00
zhengkunwang b045261f16 feat: 增加上传文件夹功能 (#2661)
Refs https://github.com/1Panel-dev/1Panel/issues/1364
Refs https://github.com/1Panel-dev/1Panel/issues/2053
2023-10-24 14:27:32 +00:00
f30f561723 fix: 同步数据库时, 忽略recycle_bin和__recycle_bin__ (#2664)
* fix: 同步数据库时, 忽略recycle_bin改为__recycle_bin__

* fix: 同步数据库时, 忽略recycle_bin和__recycle_bin__

---------

Co-authored-by: tt <www@tt.local>
Co-authored-by: shao <shao@mac.local>
2023-10-24 22:26:47 +08:00
zhengkunwang 3c3fd5fd78 feat: 文件增加打开终端功能 (#2660)
Refs https://github.com/1Panel-dev/1Panel/issues/958
2023-10-24 09:55:27 +00:00
shaoandtt d7f25da581 fix: 同步数据库时, 忽略recycle_bin改为__recycle_bin__ (#2659)
Co-authored-by: tt <www@tt.local>
2023-10-24 17:36:56 +08:00
zhengkunwang 833a3e1a4f feat: 文件收藏夹增加快速跳转 (#2642) 2023-10-23 09:53:24 +00:00
ssongliu 44b5a8d6bf feat: 终端主机地址校验支持 ipv6 (#2643)
Refs #2526
2023-10-23 09:17:29 +00:00
ssongliu 2b9a7df4b2 fix: 解决容器创建默认 Cmd 失败的问题 (#2641) 2023-10-23 07:25:17 +00:00
ssongliu 057b5067af fix: 计划任务报告样式调整 (#2640) 2023-10-23 07:23:22 +00:00
ssongliu 67ec72b9cb fix: 解决容器创建默认 Entrypoint 失败的问题 (#2638) 2023-10-23 06:05:15 +00:00
ssongliu e8ece0dfd7 feat: 优化计划任务脚本执行输出 (#2637) 2023-10-23 06:03:19 +00:00
ssongliu 8cbbef1ac0 feat: 优化计划任务脚本执行错误处理 (#2635) 2023-10-23 03:28:33 +00:00
zhengkunwang eb54030ecd feat: supervisor 优化状态判断 (#2634) 2023-10-23 03:25:20 +00:00
ssongliu 88120aa988 fix: 修改 OneDrive 授权码长度限制 (#2629)
Refs #2626
2023-10-23 03:11:14 +00:00
igophper 523f1ea67f feat: 优化判断systemctl的service文件是否存在函数 (#2615) 2023-10-22 21:37:35 -05:00
igophperand江杭辉 a86ec12b86 fix: ssh日志识别错误 (#2630)
Co-authored-by: 江杭辉 <jianghanghui@k.app>
2023-10-23 10:24:37 +08:00
igophper fb19437f5f fix: 修复数据库修改端口错误 (#2627) 2023-10-23 09:46:48 +08:00
ssongliu e1cf68becc feat: OneDrive 授权码增加格式校验 (#2614)
Refs #2610
2023-10-21 14:46:48 +00:00
ssongliu 8a7e61e9e5 fix: 解决 firewalld 防火墙规则 ipv6 下不生效的问题 (#2613)
Refs #2144
2023-10-21 14:44:52 +00:00
zhengkunwang b38abf852d feat: 文件增加收藏夹功能 (#2612)
Refs https://github.com/1Panel-dev/1Panel/issues/492
2023-10-20 09:56:46 +00:00
ssongliu 8715cfc343 feat: 解决容器编辑内存限额失败的问题 (#2607)
Refs #2608
2023-10-20 06:16:45 +00:00
ssongliu 7a1d4345fe fix: 计划任务增加日志备份 (#2595)
Refs #2008
2023-10-20 03:32:45 +00:00
ssongliu a5c0e41bda feat: 缓存容器界面刷新频率 (#2606)
Refs #2569
2023-10-20 03:20:45 +00:00
ssongliu 1dc2b292ec fix: 系统用户名、密码增加空格校验 (#2604)
Refs #2602
2023-10-19 13:54:44 +00:00
ssongliu 581ed16b73 feat: 优化 mfa 登陆方式 (#2605)
Refs #1884
2023-10-19 13:52:44 +00:00
ssongliu 8bb07cf4f5 feat: 计划任务增加缓存清理 (#2592)
Refs #2564
2023-10-18 09:08:24 +00:00
zhengkunwang 743e7d0b59 feat: 文件增加回收站功能 (#2586)
Refs https://github.com/1Panel-dev/1Panel/issues/1137
Refs https://github.com/1Panel-dev/1Panel/issues/624
2023-10-18 09:02:24 +00:00
ssongliu eeb80749a2 fix: 同步数据库时,忽略 recycle_bin (#2591)
Refs #2589
2023-10-18 02:16:22 +00:00
ssongliu 161ccc8039 feat: 容器列表增加状态筛选 (#2587)
Refs #2471
2023-10-18 02:14:26 +00:00
ssongliu 4806a57d92 feat: 备份账号创建增加上传测试 (#2585) 2023-10-17 09:58:21 +00:00
ssongliu 0f7ec06404 fix: 解决容器设置 host 网络失败的问题 (#2582)
Refs #2550
2023-10-17 09:56:25 +00:00
ssongliu 3ff09c8b7a feat: 概览界面增加服务重启以及面板重启功能 (#2579)
Refs #328
2023-10-17 09:54:30 +00:00
ssongliu e9eea9c795 feat: SSH 服务支持开机自启设置 (#2578)
Refs #2225
2023-10-17 09:52:34 +00:00
dependabot[bot] a33094d169 build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace (#2577)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.29.0 to 0.44.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.29.0...zpages/v0.44.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 20:23:24 -05:00
dependabot[bot] 65725d102e build(deps-dev): bump @babel/traverse from 7.21.5 to 7.23.2 in /frontend (#2573)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.21.5 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 09:35:56 -05:00
dependabot[bot] 1b403d8c24 build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#2572)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.29.0 to 0.44.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.29.0...zpages/v0.44.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 09:33:21 -05:00
ssongliu 2e13d86a69 feat: SSH 登陆日志适配 Debian12 (#2567)
Refs #2367
2023-10-16 09:46:14 +00:00
zhengkunwang c880caa770 fix: 解决部分情况下 zip 文件压缩解压失败的问题 (#2565)
Refs https://github.com/1Panel-dev/1Panel/issues/1245
Refs https://github.com/1Panel-dev/1Panel/issues/263
2023-10-16 08:34:15 +00:00
zhengkunwang 90af56511c fix: 解决解压 .tar 文件失败的问题 (#2562) 2023-10-16 02:48:06 -05:00
zhengkunwang 8efe0c8bed feat: 文件列表增加排序功能 (#2541)
Refs https://github.com/1Panel-dev/1Panel/issues/2343
Refs https://github.com/1Panel-dev/1Panel/issues/1698
Refs https://github.com/1Panel-dev/1Panel/issues/1032
2023-10-16 03:08:15 +00:00
273 changed files with 9692 additions and 3590 deletions
+1 -4
View File
@@ -44,10 +44,7 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_
- [在线文档](https://1panel.cn/docs/)
- [教学视频](https://space.bilibili.com/510493147/channel/collectiondetail?sid=1199760)
- [社区论坛](https://bbs.fit2cloud.com/c/1p/7)
**加入微信交流群**
<img src="https://1panel.cn/img/wechat-group.jpg" width="156" height="156"/>
- [如何加入微信交流群?](https://bbs.fit2cloud.com/t/topic/2147)
## 安全说明
+8 -5
View File
@@ -19,8 +19,7 @@ import (
// @Router /apps/search [post]
func (b *BaseApi) SearchApp(c *gin.Context) {
var req request.AppSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list, err := appService.PageApp(req)
@@ -45,8 +44,13 @@ func (b *BaseApi) SyncApp(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
if !res.CanUpdate {
helper.SuccessWithMsg(c, i18n.GetMsgByKey("AppStoreIsUpToDate"))
if res.IsSyncing {
helper.SuccessWithMsg(c, i18n.GetMsgByKey("AppStoreIsSyncing"))
} else {
helper.SuccessWithMsg(c, i18n.GetMsgByKey("AppStoreIsUpToDate"))
}
return
}
go func() {
@@ -154,8 +158,7 @@ func (b *BaseApi) GetIgnoredApp(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"name","input_value":"name","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"info":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"安装应用 [appKey]-[name]","formatEN":"Install app [appKey]-[name]"}
func (b *BaseApi) InstallApp(c *gin.Context) {
var req request.AppInstallCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
tx, ctx := helper.GetTxAndContext()
+17 -32
View File
@@ -1,8 +1,6 @@
package v1
import (
"reflect"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
@@ -22,11 +20,17 @@ import (
// @Router /apps/installed/search [post]
func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
var req request.AppInstalledSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if !reflect.DeepEqual(req.PageInfo, dto.PageInfo{}) {
if req.All {
list, err := appInstallService.SearchForWebsite(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
} else {
total, list, err := appInstallService.Page(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -36,13 +40,6 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
Items: list,
Total: total,
})
} else {
list, err := appInstallService.SearchForWebsite(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
}
@@ -72,8 +69,7 @@ func (b *BaseApi) ListAppInstalled(c *gin.Context) {
// @Router /apps/installed/check [post]
func (b *BaseApi) CheckAppInstalled(c *gin.Context) {
var req request.AppInstalledInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := global.VALID.Struct(req); err != nil {
@@ -98,8 +94,7 @@ func (b *BaseApi) CheckAppInstalled(c *gin.Context) {
// @Router /apps/installed/loadport [post]
func (b *BaseApi) LoadPort(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
port, err := appInstallService.LoadPort(req)
@@ -120,8 +115,7 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
// @Router /apps/installed/conninfo/:key [get]
func (b *BaseApi) LoadConnInfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
conn, err := appInstallService.LoadConnInfo(req)
@@ -181,8 +175,7 @@ func (b *BaseApi) SyncInstalled(c *gin.Context) {
// @x-panel-log {"bodyKeys":["installId","operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"name","output_value":"appName"},{"input_column":"id","input_value":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"[operate] 应用 [appKey][appName]","formatEN":"[operate] App [appKey][appName]"}
func (b *BaseApi) OperateInstalled(c *gin.Context) {
var req request.AppInstalledOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appInstallService.Operate(req); err != nil {
@@ -243,12 +236,7 @@ func (b *BaseApi) GetUpdateVersions(c *gin.Context) {
// @x-panel-log {"bodyKeys":["key","name","port"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用端口修改 [key]-[name] => [port]","formatEN":"Application port update [key]-[name] => [port]"}
func (b *BaseApi) ChangeAppPort(c *gin.Context) {
var req request.PortUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appInstallService.ChangeAppPort(req); err != nil {
@@ -268,8 +256,7 @@ func (b *BaseApi) ChangeAppPort(c *gin.Context) {
// @Router /apps/installed/conf [post]
func (b *BaseApi) GetDefaultConfig(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content, err := appInstallService.GetDefaultConfigByKey(req.Type, req.Name)
@@ -314,8 +301,7 @@ func (b *BaseApi) GetParams(c *gin.Context) {
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用参数修改 [installId]","formatEN":"Application param update [installId]"}
func (b *BaseApi) UpdateInstalled(c *gin.Context) {
var req request.AppInstalledUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appInstallService.Update(req); err != nil {
@@ -336,8 +322,7 @@ func (b *BaseApi) UpdateInstalled(c *gin.Context) {
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"忽略应用 [installId] 版本升级","formatEN":"Application param update [installId]"}
func (b *BaseApi) IgnoreUpgrade(c *gin.Context) {
var req request.AppInstalledIgnoreUpgrade
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appInstallService.IgnoreUpgrade(req); err != nil {
+4 -8
View File
@@ -25,10 +25,10 @@ type BaseApi struct{}
// @Router /auth/login [post]
func (b *BaseApi) Login(c *gin.Context) {
var req dto.Login
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if req.AuthMethod != "jwt" && !req.IgnoreCaptcha {
if err := captcha.VerifyCode(req.CaptchaID, req.Captcha); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -60,14 +60,10 @@ func (b *BaseApi) Login(c *gin.Context) {
// @Header 200 {string} EntranceCode "安全入口"
func (b *BaseApi) MFALogin(c *gin.Context) {
var req dto.MFALogin
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
entranceItem := c.Request.Header.Get("EntranceCode")
var entrance []byte
if len(entranceItem) != 0 {
+13 -63
View File
@@ -8,7 +8,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -23,12 +22,7 @@ import (
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建备份账号 [type]","formatEN":"create backup account [type]"}
func (b *BaseApi) CreateBackup(c *gin.Context) {
var req dto.BackupOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.Credential) != 0 {
@@ -65,12 +59,7 @@ func (b *BaseApi) CreateBackup(c *gin.Context) {
// @Router /settings/backup/search [post]
func (b *BaseApi) ListBuckets(c *gin.Context) {
var req dto.ForBuckets
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.Credential) != 0 {
@@ -125,12 +114,7 @@ func (b *BaseApi) LoadOneDriveInfo(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":true,"db":"backup_accounts","output_column":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"}
func (b *BaseApi) DeleteBackup(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -151,8 +135,7 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) {
// @Router /settings/backup/record/search [post]
func (b *BaseApi) SearchBackupRecords(c *gin.Context) {
var req dto.RecordSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -179,12 +162,7 @@ func (b *BaseApi) SearchBackupRecords(c *gin.Context) {
// @x-panel-log {"bodyKeys":["source","fileName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载备份记录 [source][fileName]","formatEN":"download backup records [source][fileName]"}
func (b *BaseApi) DownloadRecord(c *gin.Context) {
var req dto.DownloadRecord
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -207,12 +185,7 @@ func (b *BaseApi) DownloadRecord(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"backup_records","output_column":"file_name","output_value":"files"}],"formatZH":"删除备份记录 [files]","formatEN":"delete backup records [files]"}
func (b *BaseApi) DeleteBackupRecord(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -234,14 +207,10 @@ func (b *BaseApi) DeleteBackupRecord(c *gin.Context) {
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新备份账号 [types]","formatEN":"update backup account [types]"}
func (b *BaseApi) UpdateBackup(c *gin.Context) {
var req dto.BackupOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.Credential) != 0 {
credential, err := base64.StdEncoding.DecodeString(req.Credential)
if err != nil {
@@ -292,14 +261,10 @@ func (b *BaseApi) ListBackup(c *gin.Context) {
// @Router /settings/backup/search/files [post]
func (b *BaseApi) LoadFilesFromBackup(c *gin.Context) {
var req dto.BackupSearchFile
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := backupService.ListFiles(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -320,12 +285,7 @@ func (b *BaseApi) LoadFilesFromBackup(c *gin.Context) {
// @x-panel-log {"bodyKeys":["type","name","detailName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"备份 [type] 数据 [name][detailName]","formatEN":"backup [type] data [name][detailName]"}
func (b *BaseApi) Backup(c *gin.Context) {
var req dto.CommonBackup
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -365,12 +325,7 @@ func (b *BaseApi) Backup(c *gin.Context) {
// @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"}
func (b *BaseApi) Recover(c *gin.Context) {
var req dto.CommonRecover
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -418,12 +373,7 @@ func (b *BaseApi) Recover(c *gin.Context) {
// @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"}
func (b *BaseApi) RecoverByUpload(c *gin.Context) {
var req dto.CommonRecover
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+24 -22
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,14 +18,10 @@ import (
// @x-panel-log {"bodyKeys":["name","command"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建快捷命令 [name][command]","formatEN":"create quick command [name][command]"}
func (b *BaseApi) CreateCommand(c *gin.Context) {
var req dto.CommandOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := commandService.Create(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -43,9 +38,8 @@ func (b *BaseApi) CreateCommand(c *gin.Context) {
// @Security ApiKeyAuth
// @Router /hosts/command/search [post]
func (b *BaseApi) SearchCommand(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
var req dto.SearchCommandWithPage
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -61,6 +55,23 @@ func (b *BaseApi) SearchCommand(c *gin.Context) {
})
}
// @Tags Command
// @Summary Tree commands
// @Description 获取快速命令树
// @Accept json
// @Success 200 {Array} dto.CommandTree
// @Security ApiKeyAuth
// @Router /hosts/command/tree [get]
func (b *BaseApi) SearchCommandTree(c *gin.Context) {
list, err := commandService.SearchForTree()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags Command
// @Summary List commands
// @Description 获取快速命令列表
@@ -88,12 +99,7 @@ func (b *BaseApi) ListCommand(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"commands","output_column":"name","output_value":"names"}],"formatZH":"删除快捷命令 [names]","formatEN":"delete quick command [names]"}
func (b *BaseApi) DeleteCommand(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -115,17 +121,13 @@ func (b *BaseApi) DeleteCommand(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新快捷命令 [name]","formatEN":"update quick command [name]"}
func (b *BaseApi) UpdateCommand(c *gin.Context) {
var req dto.CommandOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
upMap := make(map[string]interface{})
upMap["name"] = req.Name
upMap["group_id"] = req.GroupID
upMap["command"] = req.Command
if err := commandService.Update(req.ID, upMap); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+5 -21
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,14 +18,10 @@ import (
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 compose 模版 [name]","formatEN":"create compose template [name]"}
func (b *BaseApi) CreateComposeTemplate(c *gin.Context) {
var req dto.ComposeTemplateCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := composeTemplateService.Create(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -45,8 +40,7 @@ func (b *BaseApi) CreateComposeTemplate(c *gin.Context) {
// @Router /containers/template/search [post]
func (b *BaseApi) SearchComposeTemplate(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -90,12 +84,7 @@ func (b *BaseApi) ListComposeTemplate(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"compose_templates","output_column":"name","output_value":"names"}],"formatZH":"删除 compose 模版 [names]","formatEN":"delete compose template [names]"}
func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -117,12 +106,7 @@ func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"compose_templates","output_column":"name","output_value":"name"}],"formatZH":"更新 compose 模版 [name]","formatEN":"update compose template information [name]"}
func (b *BaseApi) UpdateComposeTemplate(c *gin.Context) {
var req dto.ComposeTemplateUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+56 -127
View File
@@ -20,12 +20,7 @@ import (
// @Router /containers/search [post]
func (b *BaseApi) SearchContainer(c *gin.Context) {
var req dto.PageContainer
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -67,12 +62,7 @@ func (b *BaseApi) ListContainer(c *gin.Context) {
// @Router /containers/compose/search [post]
func (b *BaseApi) SearchCompose(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -98,12 +88,7 @@ func (b *BaseApi) SearchCompose(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测 compose [name] 格式","formatEN":"check compose [name]"}
func (b *BaseApi) TestCompose(c *gin.Context) {
var req dto.ComposeCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -126,12 +111,7 @@ func (b *BaseApi) TestCompose(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 compose [name]","formatEN":"create compose [name]"}
func (b *BaseApi) CreateCompose(c *gin.Context) {
var req dto.ComposeCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -154,12 +134,7 @@ func (b *BaseApi) CreateCompose(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name","operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"compose [operation] [name]","formatEN":"compose [operation] [name]"}
func (b *BaseApi) OperatorCompose(c *gin.Context) {
var req dto.ComposeOperation
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -181,14 +156,10 @@ func (b *BaseApi) OperatorCompose(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器 [name][image]","formatEN":"update container [name][image]"}
func (b *BaseApi) ContainerUpdate(c *gin.Context) {
var req dto.ContainerOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerUpdate(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -206,14 +177,10 @@ func (b *BaseApi) ContainerUpdate(c *gin.Context) {
// @Router /containers/info [post]
func (b *BaseApi) ContainerInfo(c *gin.Context) {
var req dto.OperationWithName
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := containerService.ContainerInfo(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -242,12 +209,12 @@ func (b *BaseApi) LoadResourceLimit(c *gin.Context) {
// @Security ApiKeyAuth
// @Router /containers/list/stats [get]
func (b *BaseApi) ContainerListStats(c *gin.Context) {
datas, err := containerService.ContainerListStats()
data, err := containerService.ContainerListStats()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, datas)
helper.SuccessWithData(c, data)
}
// @Tags Container
@@ -261,14 +228,10 @@ func (b *BaseApi) ContainerListStats(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器 [name][image]","formatEN":"create container [name][image]"}
func (b *BaseApi) ContainerCreate(c *gin.Context) {
var req dto.ContainerOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerCreate(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -287,14 +250,10 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [name][image]","formatEN":"upgrade container image [name][image]"}
func (b *BaseApi) ContainerUpgrade(c *gin.Context) {
var req dto.ContainerUpgrade
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerUpgrade(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -313,14 +272,10 @@ func (b *BaseApi) ContainerUpgrade(c *gin.Context) {
// @x-panel-log {"bodyKeys":["pruneType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [pruneType]","formatEN":"clean container [pruneType]"}
func (b *BaseApi) ContainerPrune(c *gin.Context) {
var req dto.ContainerPrune
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
report, err := containerService.Prune(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -340,14 +295,10 @@ func (b *BaseApi) ContainerPrune(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [name] 日志","formatEN":"clean container [name] logs"}
func (b *BaseApi) CleanContainerLog(c *gin.Context) {
var req dto.OperationWithName
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerLogClean(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -365,14 +316,36 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) {
// @Router /containers/load/log [post]
func (b *BaseApi) LoadContainerLog(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content := containerService.LoadContainerLogs(req)
helper.SuccessWithData(c, content)
}
// @Tags Container
// @Summary Rename Container
// @Description 容器重命名
// @Accept json
// @Param request body dto.ContainerRename true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /containers/rename [post]
// @x-panel-log {"bodyKeys":["name","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器重命名 [name] => [newName]","formatEN":"rename container [name] => [newName]"}
func (b *BaseApi) ContainerRename(c *gin.Context) {
var req dto.ContainerRename
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerRename(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Container
// @Summary Operate Container
// @Description 容器操作
@@ -381,17 +354,13 @@ func (b *BaseApi) LoadContainerLog(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Router /containers/operate [post]
// @x-panel-log {"bodyKeys":["name","operation","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器 [name] 执行 [operation] [newName]","formatEN":"container [operation] [name] [newName]"}
// @x-panel-log {"bodyKeys":["names","operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器 [names] 执行 [operation]","formatEN":"container [operation] [names]"}
func (b *BaseApi) ContainerOperation(c *gin.Context) {
var req dto.ContainerOperation
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := containerService.ContainerOperation(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -431,12 +400,7 @@ func (b *BaseApi) ContainerStats(c *gin.Context) {
// @Router /containers/inspect [post]
func (b *BaseApi) Inspect(c *gin.Context) {
var req dto.InspectReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -470,7 +434,7 @@ func (b *BaseApi) ContainerLogs(c *gin.Context) {
follow := c.Query("follow") == "true"
tail := c.Query("tail")
if err := containerService.ContainerLogs(wsConn, container, since, tail, follow); err != nil {
if err := containerService.ContainerLogs(wsConn, "container", container, since, tail, follow); err != nil {
_ = wsConn.WriteMessage(1, []byte(err.Error()))
return
}
@@ -487,12 +451,7 @@ func (b *BaseApi) ContainerLogs(c *gin.Context) {
// @Router /containers/network/search [post]
func (b *BaseApi) SearchNetwork(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -535,12 +494,7 @@ func (b *BaseApi) ListNetwork(c *gin.Context) {
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器网络 [names]","formatEN":"delete container network [names]"}
func (b *BaseApi) DeleteNetwork(c *gin.Context) {
var req dto.BatchDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -562,12 +516,7 @@ func (b *BaseApi) DeleteNetwork(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器网络 name","formatEN":"create container network [name]"}
func (b *BaseApi) CreateNetwork(c *gin.Context) {
var req dto.NetworkCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -589,12 +538,7 @@ func (b *BaseApi) CreateNetwork(c *gin.Context) {
// @Router /containers/volume/search [post]
func (b *BaseApi) SearchVolume(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -637,12 +581,7 @@ func (b *BaseApi) ListVolume(c *gin.Context) {
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器存储卷 [names]","formatEN":"delete container volume [names]"}
func (b *BaseApi) DeleteVolume(c *gin.Context) {
var req dto.BatchDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -664,12 +603,7 @@ func (b *BaseApi) DeleteVolume(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器存储卷 [name]","formatEN":"create container volume [name]"}
func (b *BaseApi) CreateVolume(c *gin.Context) {
var req dto.VolumeCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -691,12 +625,7 @@ func (b *BaseApi) CreateVolume(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 compose [name]","formatEN":"update compose information [name]"}
func (b *BaseApi) ComposeUpdate(c *gin.Context) {
var req dto.ComposeUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -729,7 +658,7 @@ func (b *BaseApi) ComposeLogs(c *gin.Context) {
follow := c.Query("follow") == "true"
tail := c.Query("tail")
if err := containerService.ComposeLogs(wsConn, compose, since, tail, follow); err != nil {
if err := containerService.ContainerLogs(wsConn, "compose", compose, since, tail, follow); err != nil {
_ = wsConn.WriteMessage(1, []byte(err.Error()))
return
}
+12 -45
View File
@@ -6,7 +6,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/gin-gonic/gin"
)
@@ -22,14 +21,10 @@ import (
// @x-panel-log {"bodyKeys":["type","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建计划任务 [type][name]","formatEN":"create cronjob [type][name]"}
func (b *BaseApi) CreateCronjob(c *gin.Context) {
var req dto.CronjobCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := cronjobService.Create(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -47,8 +42,7 @@ func (b *BaseApi) CreateCronjob(c *gin.Context) {
// @Router /cronjobs/search [post]
func (b *BaseApi) SearchCronjob(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -74,10 +68,10 @@ func (b *BaseApi) SearchCronjob(c *gin.Context) {
// @Router /cronjobs/search/records [post]
func (b *BaseApi) SearchJobRecords(c *gin.Context) {
var req dto.SearchRecord
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
loc, _ := time.LoadLocation(common.LoadTimeZone())
req.StartTime = req.StartTime.In(loc)
req.EndTime = req.EndTime.In(loc)
@@ -104,8 +98,7 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) {
// @Router /cronjob/record/log [post]
func (b *BaseApi) LoadRecordLog(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content, err := cronjobService.LoadRecordLog(req)
@@ -127,8 +120,7 @@ func (b *BaseApi) LoadRecordLog(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
func (b *BaseApi) CleanRecord(c *gin.Context) {
var req dto.CronjobClean
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -151,12 +143,7 @@ func (b *BaseApi) CleanRecord(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"cronjobs","output_column":"name","output_value":"names"}],"formatZH":"删除计划任务 [names]","formatEN":"delete cronjob [names]"}
func (b *BaseApi) DeleteCronjob(c *gin.Context) {
var req dto.CronjobBatchDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -178,12 +165,7 @@ func (b *BaseApi) DeleteCronjob(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"更新计划任务 [name]","formatEN":"update cronjob [name]"}
func (b *BaseApi) UpdateCronjob(c *gin.Context) {
var req dto.CronjobUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -205,12 +187,7 @@ func (b *BaseApi) UpdateCronjob(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id","status"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"修改计划任务 [name] 状态为 [status]","formatEN":"change the status of cronjob [name] to [status]."}
func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) {
var req dto.CronjobUpdateStatus
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -232,12 +209,7 @@ func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) {
// @x-panel-log {"bodyKeys":["recordID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"recordID","isList":false,"db":"job_records","output_column":"file","output_value":"file"}],"formatZH":"下载计划任务记录 [file]","formatEN":"download the cronjob record [file]"}
func (b *BaseApi) TargetDownload(c *gin.Context) {
var req dto.CronjobDownload
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -261,12 +233,7 @@ func (b *BaseApi) TargetDownload(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"手动执行计划任务 [name]","formatEN":"manually execute the cronjob [name]"}
func (b *BaseApi) HandleOnce(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+22
View File
@@ -56,6 +56,28 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error netOption in path"))
return
}
data := dashboardService.LoadCurrentInfo(ioOption, netOption)
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary System restart
// @Description 重启服务器/面板
// @Accept json
// @Param operation path string true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /dashboard/system/restart/:operation [post]
func (b *BaseApi) SystemRestart(c *gin.Context) {
operation, ok := c.Params.Get("operation")
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error operation in path"))
return
}
if err := dashboardService.Restart(operation); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
+8 -33
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,14 +18,10 @@ import (
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建远程数据库 [name][type]","formatEN":"create database [name][type]"}
func (b *BaseApi) CreateDatabase(c *gin.Context) {
var req dto.DatabaseCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := databaseService.Create(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -45,14 +40,10 @@ func (b *BaseApi) CreateDatabase(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测远程数据库 [name][type] 连接性","formatEN":"check if database [name][type] is connectable"}
func (b *BaseApi) CheckDatabase(c *gin.Context) {
var req dto.DatabaseCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, databaseService.CheckDatabase(req))
}
@@ -66,8 +57,7 @@ func (b *BaseApi) CheckDatabase(c *gin.Context) {
// @Router /databases/db/search [post]
func (b *BaseApi) SearchDatabase(c *gin.Context) {
var req dto.DatabaseSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -135,12 +125,7 @@ func (b *BaseApi) GetDatabase(c *gin.Context) {
// @Router /db/remote/del/check [post]
func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -163,12 +148,7 @@ func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete database [names]"}
func (b *BaseApi) DeleteDatabase(c *gin.Context) {
var req dto.DatabaseDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -190,12 +170,7 @@ func (b *BaseApi) DeleteDatabase(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新远程数据库 [name]","formatEN":"update database [name]"}
func (b *BaseApi) UpdateDatabase(c *gin.Context) {
var req dto.DatabaseUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+25 -63
View File
@@ -7,7 +7,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -22,14 +21,10 @@ import (
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 mysql 数据库 [name]","formatEN":"create mysql database [name]"}
func (b *BaseApi) CreateMysql(c *gin.Context) {
var req dto.MysqlDBCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.Password) != 0 {
password, err := base64.StdEncoding.DecodeString(req.Password)
if err != nil {
@@ -57,14 +52,10 @@ func (b *BaseApi) CreateMysql(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"mysql 数据库 [name] 描述信息修改 [description]","formatEN":"The description of the mysql database [name] is modified => [description]"}
func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) {
var req dto.UpdateDescription
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := mysqlService.UpdateDescription(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -83,14 +74,10 @@ func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 密码","formatEN":"Update database [name] password"}
func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) {
var req dto.ChangeDBInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.Value) != 0 {
value, err := base64.StdEncoding.DecodeString(req.Value)
if err != nil {
@@ -118,14 +105,10 @@ func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 访问权限","formatEN":"Update database [name] access"}
func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) {
var req dto.ChangeDBInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := mysqlService.ChangeAccess(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -144,8 +127,7 @@ func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"调整 mysql 数据库性能参数","formatEN":"adjust mysql database performance parameters"}
func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
var req dto.MysqlVariablesUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -167,12 +149,7 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 mysql 数据库配置信息","formatEN":"update the mysql database configuration information"}
func (b *BaseApi) UpdateMysqlConfByFile(c *gin.Context) {
var req dto.MysqlConfUpdateByFile
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -194,8 +171,7 @@ func (b *BaseApi) UpdateMysqlConfByFile(c *gin.Context) {
// @Router /databases/search [post]
func (b *BaseApi) SearchMysql(c *gin.Context) {
var req dto.MysqlDBSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -238,14 +214,10 @@ func (b *BaseApi) ListDBName(c *gin.Context) {
// @Router /databases/load [post]
func (b *BaseApi) LoadDBFromRemote(c *gin.Context) {
var req dto.MysqlLoadDB
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := mysqlService.LoadFromRemote(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -264,12 +236,7 @@ func (b *BaseApi) LoadDBFromRemote(c *gin.Context) {
// @Router /databases/del/check [post]
func (b *BaseApi) DeleteCheckMysql(c *gin.Context) {
var req dto.MysqlDBDeleteCheck
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -292,12 +259,7 @@ func (b *BaseApi) DeleteCheckMysql(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"删除 mysql 数据库 [name]","formatEN":"delete mysql database [name]"}
func (b *BaseApi) DeleteMysql(c *gin.Context) {
var req dto.MysqlDBDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -321,10 +283,10 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) {
// @Router /databases/baseinfo [post]
func (b *BaseApi) LoadBaseinfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := mysqlService.LoadBaseInfo(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -344,10 +306,10 @@ func (b *BaseApi) LoadBaseinfo(c *gin.Context) {
// @Router /databases/load/file [post]
func (b *BaseApi) LoadDatabaseFile(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content, err := mysqlService.LoadDatabaseFile(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -366,10 +328,10 @@ func (b *BaseApi) LoadDatabaseFile(c *gin.Context) {
// @Router /databases/remote [post]
func (b *BaseApi) LoadRemoteAccess(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
isRemote, err := mysqlService.LoadRemoteAccess(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -389,10 +351,10 @@ func (b *BaseApi) LoadRemoteAccess(c *gin.Context) {
// @Router /databases/status [post]
func (b *BaseApi) LoadStatus(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := mysqlService.LoadStatus(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -412,10 +374,10 @@ func (b *BaseApi) LoadStatus(c *gin.Context) {
// @Router /databases/variables [post]
func (b *BaseApi) LoadVariables(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := mysqlService.LoadVariables(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+9 -23
View File
@@ -9,7 +9,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
"github.com/gin-gonic/gin"
)
@@ -73,14 +72,10 @@ func (b *BaseApi) LoadPersistenceConf(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
func (b *BaseApi) UpdateRedisConf(c *gin.Context) {
var req dto.RedisConfUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBind(&req, c); err != nil {
return
}
if err := redisService.UpdateConf(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -99,14 +94,10 @@ func (b *BaseApi) UpdateRedisConf(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 redis 数据库密码","formatEN":"change the password of the redis database"}
func (b *BaseApi) ChangeRedisPassword(c *gin.Context) {
var req dto.ChangeRedisPass
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.Value) != 0 {
value, err := base64.StdEncoding.DecodeString(req.Value)
if err != nil {
@@ -134,14 +125,10 @@ func (b *BaseApi) ChangeRedisPassword(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"redis 数据库持久化配置更新","formatEN":"redis database persistence configuration update"}
func (b *BaseApi) UpdateRedisPersistenceConf(c *gin.Context) {
var req dto.RedisConfPersistenceUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := redisService.UpdatePersistenceConf(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -159,8 +146,7 @@ func (b *BaseApi) UpdateRedisPersistenceConf(c *gin.Context) {
// @Router /databases/redis/backup/search [post]
func (b *BaseApi) RedisBackupList(c *gin.Context) {
var req dto.PageInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -187,10 +173,10 @@ func (b *BaseApi) RedisBackupList(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
func (b *BaseApi) UpdateRedisConfByFile(c *gin.Context) {
var req dto.RedisConfUpdateByFile
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
redisInfo, err := redisService.LoadConf()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+4 -17
View File
@@ -6,7 +6,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -65,8 +64,7 @@ func (b *BaseApi) LoadDaemonJson(c *gin.Context) {
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置 [key]=>[value]","formatEN":"Updated the docker daemon.json configuration [key]=>[value]"}
func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
var req dto.SettingUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -89,8 +87,7 @@ func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 日志配置","formatEN":"Updated the docker daemon.json log option"}
func (b *BaseApi) UpdateLogOption(c *gin.Context) {
var req dto.LogOption
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBind(&req, c); err != nil {
return
}
@@ -113,12 +110,7 @@ func (b *BaseApi) UpdateLogOption(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置","formatEN":"Updated the docker daemon.json configuration"}
func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) {
var req dto.DaemonJsonUpdateByFile
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -141,12 +133,7 @@ func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"docker 服务 [operation]","formatEN":"[operation] docker service"}
func (b *BaseApi) OperateDocker(c *gin.Context) {
var req dto.DockerOperation
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+3
View File
@@ -53,4 +53,7 @@ var (
processService = service.NewIProcessService()
hostToolService = service.NewIHostToolService()
recycleBinService = service.NewIRecycleBinService()
favoriteService = service.NewIFavoriteService()
)
+76
View File
@@ -0,0 +1,76 @@
package v1
import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/gin-gonic/gin"
)
// @Tags File
// @Summary List favorites
// @Description 获取收藏列表
// @Accept json
// @Param request body dto.PageInfo true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/favorite/search [post]
func (b *BaseApi) SearchFavorite(c *gin.Context) {
var req dto.PageInfo
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := favoriteService.Page(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: list,
})
}
// @Tags File
// @Summary Create favorite
// @Description 创建收藏
// @Accept json
// @Param request body request.FavoriteCreate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/favorite [post]
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"收藏文件/文件夹 [path]","formatEN":"收藏文件/文件夹 [path]"}
func (b *BaseApi) CreateFavorite(c *gin.Context) {
var req request.FavoriteCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
favorite, err := favoriteService.Create(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, favorite)
}
// @Tags File
// @Summary Delete favorite
// @Description 删除收藏
// @Accept json
// @Param request body request.FavoriteDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/favorite/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"favorites","output_column":"path","output_value":"path"}],"formatZH":"删除收藏 [path]","formatEN":"delete avorite [path]"}
func (b *BaseApi) DeleteFavorite(c *gin.Context) {
var req request.FavoriteDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := favoriteService.Delete(req.ID); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
+71 -55
View File
@@ -35,8 +35,7 @@ import (
// @Router /files/search [post]
func (b *BaseApi) ListFiles(c *gin.Context) {
var req request.FileOption
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
files, err := fileService.GetFileList(req)
@@ -57,12 +56,7 @@ func (b *BaseApi) ListFiles(c *gin.Context) {
// @Router /files/upload/search [post]
func (b *BaseApi) SearchUploadWithPage(c *gin.Context) {
var req request.SearchUploadWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, files, err := fileService.SearchUploadWithPage(req)
@@ -86,8 +80,7 @@ func (b *BaseApi) SearchUploadWithPage(c *gin.Context) {
// @Router /files/tree [post]
func (b *BaseApi) GetFileTree(c *gin.Context) {
var req request.FileOption
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
tree, err := fileService.GetFileTree(req)
@@ -109,8 +102,7 @@ func (b *BaseApi) GetFileTree(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建文件/文件夹 [path]","formatEN":"Create dir or file [path]"}
func (b *BaseApi) CreateFile(c *gin.Context) {
var req request.FileCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := fileService.Create(req)
@@ -132,8 +124,7 @@ func (b *BaseApi) CreateFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除文件/文件夹 [path]","formatEN":"Delete dir or file [path]"}
func (b *BaseApi) DeleteFile(c *gin.Context) {
var req request.FileDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := fileService.Delete(req)
@@ -155,8 +146,7 @@ func (b *BaseApi) DeleteFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["paths"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量删除文件/文件夹 [paths]","formatEN":"Batch delete dir or file [paths]"}
func (b *BaseApi) BatchDeleteFile(c *gin.Context) {
var req request.FileBatchDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := fileService.BatchDelete(req)
@@ -178,8 +168,7 @@ func (b *BaseApi) BatchDeleteFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path","mode"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改权限 [paths] => [mode]","formatEN":"Change mode [paths] => [mode]"}
func (b *BaseApi) ChangeFileMode(c *gin.Context) {
var req request.FileCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := fileService.ChangeMode(req)
@@ -201,8 +190,7 @@ func (b *BaseApi) ChangeFileMode(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path","user","group"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改用户/组 [paths] => [user]/[group]","formatEN":"Change owner [paths] => [user]/[group]"}
func (b *BaseApi) ChangeFileOwner(c *gin.Context) {
var req request.FileRoleUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := fileService.ChangeOwner(req); err != nil {
@@ -223,8 +211,7 @@ func (b *BaseApi) ChangeFileOwner(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"压缩文件 [name]","formatEN":"Compress file [name]"}
func (b *BaseApi) CompressFile(c *gin.Context) {
var req request.FileCompress
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := fileService.Compress(req)
@@ -246,8 +233,7 @@ func (b *BaseApi) CompressFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"解压 [path]","formatEN":"Decompress file [path]"}
func (b *BaseApi) DeCompressFile(c *gin.Context) {
var req request.FileDeCompress
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := fileService.DeCompress(req)
@@ -262,15 +248,14 @@ func (b *BaseApi) DeCompressFile(c *gin.Context) {
// @Summary Load file content
// @Description 获取文件内容
// @Accept json
// @Param request body request.FileOption true "request"
// @Param request body request.FileContentReq true "request"
// @Success 200 {object} response.FileInfo
// @Security ApiKeyAuth
// @Router /files/content [post]
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"获取文件内容 [path]","formatEN":"Load file content [path]"}
func (b *BaseApi) GetContent(c *gin.Context) {
var req request.FileOption
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
var req request.FileContentReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
info, err := fileService.GetContent(req)
@@ -292,8 +277,7 @@ func (b *BaseApi) GetContent(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新文件内容 [path]","formatEN":"Update file content [path]"}
func (b *BaseApi) SaveContent(c *gin.Context) {
var req request.FileEdit
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := fileService.SaveContent(req); err != nil {
@@ -356,24 +340,16 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Router /files/check [post]
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测文件 [path] 是否存在","formatEN":"Check whether file [path] exists"}
func (b *BaseApi) CheckFile(c *gin.Context) {
var req request.FilePathCheck
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if _, err := os.Stat(req.Path); err != nil {
helper.SuccessWithData(c, false)
return
}
if _, err := os.Stat(req.Path); err != nil && os.IsNotExist(err) {
helper.SuccessWithData(c, true)
return
}
helper.SuccessWithData(c, false)
helper.SuccessWithData(c, true)
}
// @Tags File
@@ -387,8 +363,7 @@ func (b *BaseApi) CheckFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["oldName","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重命名 [oldName] => [newName]","formatEN":"Rename [oldName] => [newName]"}
func (b *BaseApi) ChangeFileName(c *gin.Context) {
var req request.FileRename
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := fileService.ChangeName(req); err != nil {
@@ -409,8 +384,7 @@ func (b *BaseApi) ChangeFileName(c *gin.Context) {
// @x-panel-log {"bodyKeys":["url","path","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载 url => [path]/[name]","formatEN":"Download url => [path]/[name]"}
func (b *BaseApi) WgetFile(c *gin.Context) {
var req request.FileWget
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
key, err := fileService.Wget(req)
@@ -434,8 +408,7 @@ func (b *BaseApi) WgetFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["oldPaths","newPath"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"移动文件 [oldPaths] => [newPath]","formatEN":"Move [oldPaths] => [newPath]"}
func (b *BaseApi) MoveFile(c *gin.Context) {
var req request.FileMove
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := fileService.MvFile(req); err != nil {
@@ -477,8 +450,7 @@ func (b *BaseApi) Download(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"}
func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
var req request.FileChunkDownload
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
fileOp := files.NewFileOp()
@@ -555,8 +527,7 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"获取文件夹大小 [path]","formatEN":"Load file size [path]"}
func (b *BaseApi) Size(c *gin.Context) {
var req request.DirSizeReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := fileService.DirSize(req)
@@ -568,12 +539,13 @@ func (b *BaseApi) Size(c *gin.Context) {
}
func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error {
if _, err := os.Stat(path.Dir(dstDir)); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(dstDir), os.ModePerm); err != nil {
op := files.NewFileOp()
dstDir = strings.TrimSpace(dstDir)
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
if err = op.CreateDir(dstDir, os.ModePerm); err != nil {
return err
}
}
targetFile, err := os.Create(filepath.Join(dstDir, fileName))
if err != nil {
return err
@@ -710,3 +682,47 @@ func (b *BaseApi) Keys(c *gin.Context) {
res.Keys = keys
helper.SuccessWithData(c, res)
}
// @Tags File
// @Summary Read file by Line
// @Description 按行读取文件
// @Param request body request.FileReadByLineReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/read [post]
func (b *BaseApi) ReadFileByLine(c *gin.Context) {
var req request.FileReadByLineReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
lines, end, err := files.ReadFileByLine(req.Path, req.Page, req.PageSize)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
}
res := response.FileLineContent{
End: end,
}
res.Path = req.Path
res.Content = strings.Join(lines, "\n")
helper.SuccessWithData(c, res)
}
// @Tags File
// @Summary Batch change file mode and owner
// @Description 批量修改文件权限和用户/组
// @Accept json
// @Param request body request.FileRoleReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/batch/role [post]
// @x-panel-log {"bodyKeys":["paths","mode","user","group"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量修改文件权限和用户/组 [paths] => [mode]/[user]/[group]","formatEN":"Batch change file mode and owner [paths] => [mode]/[user]/[group]"}
func (b *BaseApi) BatchChangeModeAndOwner(c *gin.Context) {
var req request.FileRoleReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := fileService.BatchChangeModeAndOwner(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
}
helper.SuccessWithOutData(c)
}
+15 -50
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -28,18 +27,13 @@ func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) {
// @Summary Page firewall rules
// @Description 获取防火墙规则列表分页
// @Accept json
// @Param request body dto.SearchWithPage true "request"
// @Param request body dto.RuleSearch true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Router /hosts/firewall/search [post]
func (b *BaseApi) SearchFirewallRule(c *gin.Context) {
var req dto.RuleSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -66,12 +60,7 @@ func (b *BaseApi) SearchFirewallRule(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"}
func (b *BaseApi) OperateFirewall(c *gin.Context) {
var req dto.FirewallOperation
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -94,14 +83,10 @@ func (b *BaseApi) OperateFirewall(c *gin.Context) {
// @x-panel-log {"bodyKeys":["port","strategy"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加端口规则 [strategy] [port]","formatEN":"create port rules [strategy][port]"}
func (b *BaseApi) OperatePortRule(c *gin.Context) {
var req dto.PortRuleOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := firewallService.OperatePortRule(req, true); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -120,14 +105,10 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) {
// @x-panel-log {"bodyKeys":["strategy","address"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 ip 规则 [strategy] [address]","formatEN":"create address rules [strategy][address]"}
func (b *BaseApi) OperateIPRule(c *gin.Context) {
var req dto.AddrRuleOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := firewallService.OperateAddressRule(req, true); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -145,14 +126,10 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) {
// @Router /hosts/firewall/batch [post]
func (b *BaseApi) BatchOperateRule(c *gin.Context) {
var req dto.BatchRuleOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := firewallService.BatchOperateRule(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -170,14 +147,10 @@ func (b *BaseApi) BatchOperateRule(c *gin.Context) {
// @Router /hosts/firewall/update/description [post]
func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) {
var req dto.UpdateFirewallDescription
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := firewallService.UpdateDescription(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -195,14 +168,10 @@ func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) {
// @Router /hosts/firewall/update/port [post]
func (b *BaseApi) UpdatePortRule(c *gin.Context) {
var req dto.PortRuleUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := firewallService.UpdatePortRule(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -220,14 +189,10 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) {
// @Router /hosts/firewall/update/addr [post]
func (b *BaseApi) UpdateAddrRule(c *gin.Context) {
var req dto.AddrRuleUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := firewallService.UpdateAddrRule(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
+6 -25
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,14 +18,10 @@ import (
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"}
func (b *BaseApi) CreateGroup(c *gin.Context) {
var req dto.GroupCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := groupService.Create(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -45,12 +40,7 @@ func (b *BaseApi) CreateGroup(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"name","output_value":"name"},{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"}
func (b *BaseApi) DeleteGroup(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -72,14 +62,10 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"}
func (b *BaseApi) UpdateGroup(c *gin.Context) {
var req dto.GroupUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := groupService.Update(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -97,12 +83,7 @@ func (b *BaseApi) UpdateGroup(c *gin.Context) {
// @Router /groups/search [post]
func (b *BaseApi) ListGroup(c *gin.Context) {
var req dto.GroupSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+9 -1
View File
@@ -115,7 +115,7 @@ func GetTxAndContext() (tx *gorm.DB, ctx context.Context) {
}
func CheckBindAndValidate(req interface{}, c *gin.Context) error {
if err := c.ShouldBindJSON(&req); err != nil {
if err := c.ShouldBindJSON(req); err != nil {
ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return err
}
@@ -125,3 +125,11 @@ func CheckBindAndValidate(req interface{}, c *gin.Context) error {
}
return nil
}
func CheckBind(req interface{}, c *gin.Context) error {
if err := c.ShouldBindJSON(&req); err != nil {
ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return err
}
return nil
}
+8 -35
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
"github.com/gin-gonic/gin"
)
@@ -20,12 +19,7 @@ import (
// @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建主机 [name][addr]","formatEN":"create host [name][addr]"}
func (b *BaseApi) CreateHost(c *gin.Context) {
var req dto.HostOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -47,12 +41,7 @@ func (b *BaseApi) CreateHost(c *gin.Context) {
// @Router /hosts/test/byinfo [post]
func (b *BaseApi) TestByInfo(c *gin.Context) {
var req dto.HostConnTest
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -89,8 +78,7 @@ func (b *BaseApi) TestByID(c *gin.Context) {
// @Router /hosts/tree [post]
func (b *BaseApi) HostTree(c *gin.Context) {
var req dto.SearchForTree
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBind(&req, c); err != nil {
return
}
@@ -113,8 +101,7 @@ func (b *BaseApi) HostTree(c *gin.Context) {
// @Router /hosts/search [post]
func (b *BaseApi) SearchHost(c *gin.Context) {
var req dto.SearchHostWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -141,12 +128,7 @@ func (b *BaseApi) SearchHost(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"hosts","output_column":"addr","output_value":"addrs"}],"formatZH":"删除主机 [addrs]","formatEN":"delete host [addrs]"}
func (b *BaseApi) DeleteHost(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -168,14 +150,10 @@ func (b *BaseApi) DeleteHost(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新主机信息 [name][addr]","formatEN":"update host [name][addr]"}
func (b *BaseApi) UpdateHost(c *gin.Context) {
var req dto.HostOperate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
var err error
if len(req.Password) != 0 && req.AuthMode == "password" {
req.Password, err = hostService.EncryptHost(req.Password)
@@ -238,12 +216,7 @@ func (b *BaseApi) UpdateHost(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id","group"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"hosts","output_column":"addr","output_value":"addr"}],"formatZH":"切换主机[addr]分组 => [group]","formatEN":"change host [addr] group => [group]"}
func (b *BaseApi) UpdateHostGroup(c *gin.Context) {
var req dto.ChangeHostGroup
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+7 -40
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -18,12 +17,7 @@ import (
// @Router /host/tool [post]
func (b *BaseApi) GetToolStatus(c *gin.Context) {
var req request.HostToolReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -46,12 +40,7 @@ func (b *BaseApi) GetToolStatus(c *gin.Context) {
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 [type] 配置","formatEN":"create [type] config"}
func (b *BaseApi) InitToolConfig(c *gin.Context) {
var req request.HostToolCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -73,15 +62,9 @@ func (b *BaseApi) InitToolConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operate","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] [type] ","formatEN":"[operate] [type]"}
func (b *BaseApi) OperateTool(c *gin.Context) {
var req request.HostToolReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
err := hostToolService.OperateTool(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -101,12 +84,7 @@ func (b *BaseApi) OperateTool(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 主机工具配置文件 ","formatEN":"[operate] tool config"}
func (b *BaseApi) OperateToolConfig(c *gin.Context) {
var req request.HostToolConfig
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -128,12 +106,7 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) {
// @Router /host/tool/log [post]
func (b *BaseApi) GetToolLog(c *gin.Context) {
var req request.HostToolLogReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -156,12 +129,7 @@ func (b *BaseApi) GetToolLog(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 守护进程 ","formatEN":"[operate] process"}
func (b *BaseApi) OperateProcess(c *gin.Context) {
var req request.SupervisorProcessConfig
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -200,8 +168,7 @@ func (b *BaseApi) GetProcess(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] Supervisor 进程文件 ","formatEN":"[operate] Supervisor Process Config file"}
func (b *BaseApi) GetProcessFile(c *gin.Context) {
var req request.SupervisorProcessFileReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content, err := hostToolService.OperateSupervisorProcessFile(req)
+8 -49
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,12 +18,7 @@ import (
// @Router /containers/image/search [post]
func (b *BaseApi) SearchImage(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -67,12 +61,7 @@ func (b *BaseApi) ListImage(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"构建镜像 [name]","formatEN":"build image [name]"}
func (b *BaseApi) ImageBuild(c *gin.Context) {
var req dto.ImageBuild
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -96,12 +85,7 @@ func (b *BaseApi) ImageBuild(c *gin.Context) {
// @x-panel-log {"bodyKeys":["repoID","imageName"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"镜像拉取 [reponame][imageName]","formatEN":"image pull [reponame][imageName]"}
func (b *BaseApi) ImagePull(c *gin.Context) {
var req dto.ImagePull
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -125,12 +109,7 @@ func (b *BaseApi) ImagePull(c *gin.Context) {
// @x-panel-log {"bodyKeys":["repoID","tagName","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"[tagName] 推送到 [reponame][name]","formatEN":"push [tagName] to [reponame][name]"}
func (b *BaseApi) ImagePush(c *gin.Context) {
var req dto.ImagePush
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -154,12 +133,7 @@ func (b *BaseApi) ImagePush(c *gin.Context) {
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"移除镜像 [names]","formatEN":"remove image [names]"}
func (b *BaseApi) ImageRemove(c *gin.Context) {
var req dto.BatchDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -182,12 +156,7 @@ func (b *BaseApi) ImageRemove(c *gin.Context) {
// @x-panel-log {"bodyKeys":["tagName","path","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"保留 [tagName] 为 [path]/[name]","formatEN":"save [tagName] as [path]/[name]"}
func (b *BaseApi) ImageSave(c *gin.Context) {
var req dto.ImageSave
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -210,12 +179,7 @@ func (b *BaseApi) ImageSave(c *gin.Context) {
// @x-panel-log {"bodyKeys":["repoID","targetName"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"tag 镜像 [reponame][targetName]","formatEN":"tag image [reponame][targetName]"}
func (b *BaseApi) ImageTag(c *gin.Context) {
var req dto.ImageTag
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -238,12 +202,7 @@ func (b *BaseApi) ImageTag(c *gin.Context) {
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [path] 加载镜像","formatEN":"load image from [path]"}
func (b *BaseApi) ImageLoad(c *gin.Context) {
var req dto.ImageLoad
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+7 -31
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,12 +18,7 @@ import (
// @Router /containers/repo/search [post]
func (b *BaseApi) SearchRepo(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -68,14 +62,10 @@ func (b *BaseApi) ListRepo(c *gin.Context) {
// @Router /containers/repo/status [get]
func (b *BaseApi) CheckRepoStatus(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := imageRepoService.Login(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -95,14 +85,10 @@ func (b *BaseApi) CheckRepoStatus(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建镜像仓库 [name]","formatEN":"create image repo [name]"}
func (b *BaseApi) CreateRepo(c *gin.Context) {
var req dto.ImageRepoCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := imageRepoService.Create(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -122,12 +108,7 @@ func (b *BaseApi) CreateRepo(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"image_repos","output_column":"name","output_value":"names"}],"formatZH":"删除镜像仓库 [names]","formatEN":"delete image repo [names]"}
func (b *BaseApi) DeleteRepo(c *gin.Context) {
var req dto.ImageRepoDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -150,12 +131,7 @@ func (b *BaseApi) DeleteRepo(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"image_repos","output_column":"name","output_value":"name"}],"formatZH":"更新镜像仓库 [name]","formatEN":"update image repo information [name]"}
func (b *BaseApi) UpdateRepo(c *gin.Context) {
var req dto.ImageRepoUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+5 -13
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -18,8 +17,7 @@ import (
// @Router /logs/login [post]
func (b *BaseApi) GetLoginLogs(c *gin.Context) {
var req dto.SearchLgLogWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -45,8 +43,7 @@ func (b *BaseApi) GetLoginLogs(c *gin.Context) {
// @Router /logs/operation [post]
func (b *BaseApi) GetOperationLogs(c *gin.Context) {
var req dto.SearchOpLogWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -73,12 +70,7 @@ func (b *BaseApi) GetOperationLogs(c *gin.Context) {
// @x-panel-log {"bodyKeys":["logType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空 [logType] 日志信息","formatEN":"Clean the [logType] log information"}
func (b *BaseApi) CleanLogs(c *gin.Context) {
var req dto.CleanLog
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -114,10 +106,10 @@ func (b *BaseApi) GetSystemFiles(c *gin.Context) {
// @Router /logs/system [post]
func (b *BaseApi) GetSystemLogs(c *gin.Context) {
var req dto.OperationWithName
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := logService.LoadSystemLog(req.Name)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
+2 -6
View File
@@ -17,14 +17,10 @@ import (
func (b *BaseApi) LoadMonitor(c *gin.Context) {
var req dto.MonitorSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
loc, _ := time.LoadLocation(common.LoadTimeZone())
req.StartTime = req.StartTime.In(loc)
req.EndTime = req.EndTime.In(loc)
+3 -6
View File
@@ -32,8 +32,7 @@ func (b *BaseApi) GetNginx(c *gin.Context) {
// @Router /openResty/scope [post]
func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) {
var req request.NginxScopeReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -56,8 +55,7 @@ func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新 nginx 配置 [domain]","formatEN":"Update nginx conf [domain]"}
func (b *BaseApi) UpdateNginxConfigByScope(c *gin.Context) {
var req request.NginxConfigUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := nginxService.UpdateConfigByScope(req); err != nil {
@@ -93,8 +91,7 @@ func (b *BaseApi) GetNginxStatus(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 nginx 配置","formatEN":"Update nginx conf"}
func (b *BaseApi) UpdateNginxFile(c *gin.Context) {
var req request.NginxConfigFileUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+1 -2
View File
@@ -28,8 +28,7 @@ func (b *BaseApi) ProcessWs(c *gin.Context) {
// @x-panel-log {"bodyKeys":["PID"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"结束进程 [PID]","formatEN":"结束进程 [PID]"}
func (b *BaseApi) StopProcess(c *gin.Context) {
var req request.ProcessReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := processService.StopProcess(req); err != nil {
+70
View File
@@ -0,0 +1,70 @@
package v1
import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/gin-gonic/gin"
)
// @Tags File
// @Summary List RecycleBin files
// @Description 获取回收站文件列表
// @Accept json
// @Param request body dto.PageInfo true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/recycle/search [post]
func (b *BaseApi) SearchRecycleBinFile(c *gin.Context) {
var req dto.PageInfo
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := recycleBinService.Page(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags File
// @Summary Reduce RecycleBin files
// @Description 还原回收站文件
// @Accept json
// @Param request body request.RecycleBinReduce true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /files/recycle/reduce [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"还原回收站文件 [name]","formatEN":"Reduce RecycleBin file [name]"}
func (b *BaseApi) ReduceRecycleBinFile(c *gin.Context) {
var req request.RecycleBinReduce
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := recycleBinService.Reduce(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
// @Tags File
// @Summary Clear RecycleBin files
// @Description 清空回收站文件
// @Accept json
// @Success 200
// @Security ApiKeyAuth
// @Router /files/recycle/clear [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空回收站","formatEN":"清空回收站"}
func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) {
if err := recycleBinService.Clear(); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
+50 -38
View File
@@ -49,12 +49,7 @@ func (b *BaseApi) GetSystemAvailable(c *gin.Context) {
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统配置 [key] => [value]","formatEN":"update system setting [key] => [value]"}
func (b *BaseApi) UpdateSetting(c *gin.Context) {
var req dto.SettingUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -76,12 +71,7 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统密码","formatEN":"update system password"}
func (b *BaseApi) UpdatePassword(c *gin.Context) {
var req dto.PasswordUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -103,12 +93,7 @@ func (b *BaseApi) UpdatePassword(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ssl"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统 ssl => [ssl]","formatEN":"update system ssl => [ssl]"}
func (b *BaseApi) UpdateSSL(c *gin.Context) {
var req dto.SSLUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -150,6 +135,44 @@ func (b *BaseApi) DownloadSSL(c *gin.Context) {
c.File(pathItem)
}
// @Tags System Setting
// @Summary Load system address
// @Description 获取系统地址信息
// @Accept json
// @Success 200
// @Security ApiKeyAuth
// @Router /settings/interface [get]
func (b *BaseApi) LoadInterfaceAddr(c *gin.Context) {
data, err := settingService.LoadInterfaceAddr()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags System Setting
// @Summary Update system bind info
// @Description 更新系统监听信息
// @Accept json
// @Param request body dto.BindInfo true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /settings/bind/update [post]
// @x-panel-log {"bodyKeys":["ipv6", "bindAddress"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统监听信息 => ipv6: [ipv6], 监听 IP: [bindAddress]","formatEN":"update system bind info => ipv6: [ipv6], 监听 IP: [bindAddress]"}
func (b *BaseApi) UpdateBindInfo(c *gin.Context) {
var req dto.BindInfo
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.UpdateBindInfo(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags System Setting
// @Summary Update system port
// @Description 更新系统端口
@@ -161,12 +184,7 @@ func (b *BaseApi) DownloadSSL(c *gin.Context) {
// @x-panel-log {"bodyKeys":["serverPort"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统端口 => [serverPort]","formatEN":"update system port => [serverPort]"}
func (b *BaseApi) UpdatePort(c *gin.Context) {
var req dto.PortUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -188,12 +206,7 @@ func (b *BaseApi) UpdatePort(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重置过期密码","formatEN":"reset an expired Password"}
func (b *BaseApi) HandlePasswordExpired(c *gin.Context) {
var req dto.PasswordUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -230,10 +243,10 @@ func (b *BaseApi) LoadTimeZone(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ntpSite"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"系统时间同步[ntpSite]","formatEN":"sync system time [ntpSite]"}
func (b *BaseApi) SyncTime(c *gin.Context) {
var req dto.SyncTime
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.SyncTime(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -297,10 +310,10 @@ func (b *BaseApi) ScanSystem(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理系统垃圾文件","formatEN":"Clean system junk files"}
func (b *BaseApi) SystemClean(c *gin.Context) {
var req []dto.Clean
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBind(&req, c); err != nil {
return
}
settingService.SystemClean(req)
helper.SuccessWithData(c, nil)
@@ -316,8 +329,7 @@ func (b *BaseApi) SystemClean(c *gin.Context) {
// @Router /settings/mfa [post]
func (b *BaseApi) LoadMFA(c *gin.Context) {
var req dto.MfaRequest
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -341,10 +353,10 @@ func (b *BaseApi) LoadMFA(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"mfa 绑定","formatEN":"bind mfa"}
func (b *BaseApi) MFABind(c *gin.Context) {
var req dto.MfaCredential
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
success := mfa.ValidCode(req.Code, req.Interval, req.Secret)
if !success {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, errors.New("code is not valid"))
+13 -45
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -19,14 +18,10 @@ import (
// @x-panel-log {"bodyKeys":["from", "description"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建系统快照 [description] 到 [from]","formatEN":"Create system backup [description] to [from]"}
func (b *BaseApi) CreateSnapshot(c *gin.Context) {
var req dto.SnapshotCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := snapshotService.SnapshotCreate(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -45,14 +40,10 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) {
// @x-panel-log {"bodyKeys":["from", "names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [from] 同步系统快照 [names]","formatEN":"Sync system snapshots [names] from [from]"}
func (b *BaseApi) ImportSnapshot(c *gin.Context) {
var req dto.SnapshotImport
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := snapshotService.SnapshotImport(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -70,14 +61,10 @@ func (b *BaseApi) ImportSnapshot(c *gin.Context) {
// @Router /settings/snapshot/status [post]
func (b *BaseApi) LoadSnapShotStatus(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := snapshotService.LoadSnapShotStatus(req.ID)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -97,14 +84,10 @@ func (b *BaseApi) LoadSnapShotStatus(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"快照 [name] 描述信息修改 [description]","formatEN":"The description of the snapshot [name] is modified => [description]"}
func (b *BaseApi) UpdateSnapDescription(c *gin.Context) {
var req dto.UpdateDescription
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := snapshotService.UpdateDescription(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -122,10 +105,10 @@ func (b *BaseApi) UpdateSnapDescription(c *gin.Context) {
// @Router /settings/snapshot/search [post]
func (b *BaseApi) SearchSnapshot(c *gin.Context) {
var req dto.SearchWithPage
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, accounts, err := snapshotService.SearchWithPage(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -148,12 +131,7 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 恢复","formatEN":"Recover from system backup [name]"}
func (b *BaseApi) RecoverSnapshot(c *gin.Context) {
var req dto.SnapshotRecover
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -175,12 +153,7 @@ func (b *BaseApi) RecoverSnapshot(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 回滚","formatEN":"Rollback from system backup [name]"}
func (b *BaseApi) RollbackSnapshot(c *gin.Context) {
var req dto.SnapshotRecover
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -202,12 +175,7 @@ func (b *BaseApi) RollbackSnapshot(c *gin.Context) {
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"删除系统快照 [name]","formatEN":"Delete system backup [name]"}
func (b *BaseApi) DeleteSnapshot(c *gin.Context) {
var req dto.BatchDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+10 -46
View File
@@ -4,7 +4,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
)
@@ -33,12 +32,7 @@ func (b *BaseApi) GetSSHInfo(c *gin.Context) {
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] SSH ","formatEN":"[operation] SSH"}
func (b *BaseApi) OperateSSH(c *gin.Context) {
var req dto.Operate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -53,23 +47,18 @@ func (b *BaseApi) OperateSSH(c *gin.Context) {
// @Summary Update host SSH setting
// @Description 更新 SSH 配置
// @Accept json
// @Param request body dto.SettingUpdate true "request"
// @Param request body dto.SSHUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /host/ssh/update [post]
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"}
func (b *BaseApi) UpdateSSH(c *gin.Context) {
var req dto.SettingUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
var req dto.SSHUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := sshService.Update(req.Key, req.Value); err != nil {
if err := sshService.Update(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
@@ -87,12 +76,7 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"}
func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
var req dto.SSHConf
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -114,12 +98,7 @@ func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
func (b *BaseApi) GenerateSSH(c *gin.Context) {
var req dto.GenerateSSH
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -140,12 +119,7 @@ func (b *BaseApi) GenerateSSH(c *gin.Context) {
// @Router /host/ssh/secret [post]
func (b *BaseApi) LoadSSHSecret(c *gin.Context) {
var req dto.GenerateLoad
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -167,12 +141,7 @@ func (b *BaseApi) LoadSSHSecret(c *gin.Context) {
// @Router /host/ssh/log/analysis [post]
func (b *BaseApi) AnalysisLog(c *gin.Context) {
var req dto.SearchForAnalysis
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
@@ -194,12 +163,7 @@ func (b *BaseApi) AnalysisLog(c *gin.Context) {
// @Router /host/ssh/log [post]
func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
var req dto.SearchSSHLog
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+4 -4
View File
@@ -32,10 +32,10 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) {
// @Router /settings/upgrade [get]
func (b *BaseApi) GetNotesByVersion(c *gin.Context) {
var req dto.Upgrade
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
notes, err := upgradeService.LoadNotes(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -55,10 +55,10 @@ func (b *BaseApi) GetNotesByVersion(c *gin.Context) {
// @x-panel-log {"bodyKeys":["version"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新系统 => [version]","formatEN":"upgrade service => [version]"}
func (b *BaseApi) Upgrade(c *gin.Context) {
var req dto.Upgrade
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := upgradeService.Upgrade(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
+33 -136
View File
@@ -18,8 +18,7 @@ import (
// @Router /websites/search [post]
func (b *BaseApi) PageWebsite(c *gin.Context) {
var req request.WebsiteSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, websites, err := websiteService.PageWebsite(req)
@@ -74,11 +73,9 @@ func (b *BaseApi) GetWebsiteOptions(c *gin.Context) {
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"}
func (b *BaseApi) CreateWebsite(c *gin.Context) {
var req request.WebsiteCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.CreateWebsite(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -98,8 +95,7 @@ func (b *BaseApi) CreateWebsite(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[operate] 网站 [domain]","formatEN":"[operate] website [domain]"}
func (b *BaseApi) OpWebsite(c *gin.Context) {
var req request.WebsiteOp
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.OpWebsite(req)
@@ -121,11 +117,9 @@ func (b *BaseApi) OpWebsite(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain]","formatEN":"Delete website [domain]"}
func (b *BaseApi) DeleteWebsite(c *gin.Context) {
var req request.WebsiteDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.DeleteWebsite(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@@ -145,8 +139,7 @@ func (b *BaseApi) DeleteWebsite(c *gin.Context) {
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 [primaryDomain]","formatEN":"Update website [primaryDomain]"}
func (b *BaseApi) UpdateWebsite(c *gin.Context) {
var req request.WebsiteUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateWebsite(req); err != nil {
@@ -202,74 +195,6 @@ func (b *BaseApi) GetWebsiteNginx(c *gin.Context) {
helper.SuccessWithData(c, fileInfo)
}
// @Tags Website Domain
// @Summary Search website domains by websiteId
// @Description 通过网站 id 查询域名
// @Accept json
// @Param websiteId path integer true "request"
// @Success 200 {array} model.WebsiteDomain
// @Security ApiKeyAuth
// @Router /websites/domains/:websiteId [get]
func (b *BaseApi) GetWebDomains(c *gin.Context) {
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return
}
list, err := websiteService.GetWebsiteDomain(websiteId)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags Website Domain
// @Summary Delete website domain
// @Description 删除网站域名
// @Accept json
// @Param request body request.WebsiteDomainDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /websites/domains/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"}
func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
var req request.WebsiteDomainDelete
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := websiteService.DeleteWebsiteDomain(req.ID); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Website Domain
// @Summary Create website domain
// @Description 创建网站域名
// @Accept json
// @Param request body request.WebsiteDomainCreate true "request"
// @Success 200 {object} model.WebsiteDomain
// @Security ApiKeyAuth
// @Router /websites/domains [post]
// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"}
func (b *BaseApi) CreateWebDomain(c *gin.Context) {
var req request.WebsiteDomainCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
domain, err := websiteService.CreateWebsiteDomain(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, domain)
}
// @Tags Website Nginx
// @Summary Load nginx conf
// @Description 获取 nginx 配置
@@ -280,8 +205,7 @@ func (b *BaseApi) CreateWebDomain(c *gin.Context) {
// @Router /websites/config [post]
func (b *BaseApi) GetNginxConfig(c *gin.Context) {
var req request.NginxScopeReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
config, err := websiteService.GetNginxConfigByScope(req)
@@ -303,8 +227,7 @@ func (b *BaseApi) GetNginxConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"nginx 配置修改 [domain]","formatEN":"Nginx conf update [domain]"}
func (b *BaseApi) UpdateNginxConfig(c *gin.Context) {
var req request.NginxConfigUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateNginxConfigByScope(req); err != nil {
@@ -347,8 +270,7 @@ func (b *BaseApi) GetHTTPSConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] https 配置","formatEN":"Update website https [domain] conf"}
func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) {
var req request.WebsiteHTTPSOp
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
tx, ctx := helper.GetTxAndContext()
@@ -372,8 +294,7 @@ func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) {
// @Router /websites/check [post]
func (b *BaseApi) CreateWebsiteCheck(c *gin.Context) {
var req request.WebsiteInstallCheckReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := websiteService.PreInstallCheck(req)
@@ -394,8 +315,7 @@ func (b *BaseApi) CreateWebsiteCheck(c *gin.Context) {
// @Router /websites/waf/config [post]
func (b *BaseApi) GetWebsiteWafConfig(c *gin.Context) {
var req request.WebsiteWafReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := websiteService.GetWafConfig(req)
@@ -417,8 +337,7 @@ func (b *BaseApi) GetWebsiteWafConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置修改 [domain]","formatEN":"WAF conf update [domain]"}
func (b *BaseApi) UpdateWebsiteWafConfig(c *gin.Context) {
var req request.WebsiteWafUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateWafConfig(req); err != nil {
@@ -439,8 +358,7 @@ func (b *BaseApi) UpdateWebsiteWafConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置文件修改 [domain]","formatEN":"WAF conf file update [domain]"}
func (b *BaseApi) UpdateWebsiteWafFile(c *gin.Context) {
var req request.WebsiteWafFileUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateWafFile(req); err != nil {
@@ -461,8 +379,7 @@ func (b *BaseApi) UpdateWebsiteWafFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] Nginx 配置修改","formatEN":"[domain] Nginx conf update"}
func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) {
var req request.WebsiteNginxUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateNginxConfigFile(req); err != nil {
@@ -483,8 +400,7 @@ func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain][operate] 日志","formatEN":"[domain][operate] logs"}
func (b *BaseApi) OpWebsiteLog(c *gin.Context) {
var req request.WebsiteLogReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.OpWebsiteLog(req)
@@ -506,8 +422,7 @@ func (b *BaseApi) OpWebsiteLog(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改默认 server => [domain]","formatEN":"Change default server => [domain]"}
func (b *BaseApi) ChangeDefaultServer(c *gin.Context) {
var req request.WebsiteDefaultUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.ChangeDefaultServer(req.ID); err != nil {
@@ -550,8 +465,7 @@ func (b *BaseApi) GetWebsitePHPConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] PHP 配置修改","formatEN":"[domain] PHP conf update"}
func (b *BaseApi) UpdateWebsitePHPConfig(c *gin.Context) {
var req request.WebsitePHPConfigUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdatePHPConfig(req); err != nil {
@@ -572,8 +486,7 @@ func (b *BaseApi) UpdateWebsitePHPConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 配置修改 [domain]","formatEN":"Nginx conf update [domain]"}
func (b *BaseApi) UpdatePHPFile(c *gin.Context) {
var req request.WebsitePHPFileUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdatePHPConfigFile(req); err != nil {
@@ -594,8 +507,7 @@ func (b *BaseApi) UpdatePHPFile(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 版本变更 [domain]","formatEN":"php version update [domain]"}
func (b *BaseApi) ChangePHPVersion(c *gin.Context) {
var req request.WebsitePHPVersionReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.ChangePHPVersion(req); err != nil {
@@ -615,8 +527,7 @@ func (b *BaseApi) ChangePHPVersion(c *gin.Context) {
// @Router /websites/rewrite [post]
func (b *BaseApi) GetRewriteConfig(c *gin.Context) {
var req request.NginxRewriteReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.GetRewriteConfig(req)
@@ -638,8 +549,7 @@ func (b *BaseApi) GetRewriteConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"伪静态配置修改 [domain]","formatEN":"Nginx conf rewrite update [domain]"}
func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) {
var req request.NginxRewriteUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateRewriteConfig(req); err != nil {
@@ -660,8 +570,7 @@ func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录","formatEN":"Update domain [domain] dir"}
func (b *BaseApi) UpdateSiteDir(c *gin.Context) {
var req request.WebsiteUpdateDir
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateSiteDir(req); err != nil {
@@ -682,8 +591,7 @@ func (b *BaseApi) UpdateSiteDir(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录权限","formatEN":"Update domain [domain] dir permission"}
func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) {
var req request.WebsiteUpdateDirPermission
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateSitePermission(req); err != nil {
@@ -703,8 +611,7 @@ func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) {
// @Router /websites/proxies [post]
func (b *BaseApi) GetProxyConfig(c *gin.Context) {
var req request.WebsiteProxyReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.GetProxies(req.ID)
@@ -726,8 +633,7 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 ","formatEN":"Update domain [domain] proxy config"}
func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
var req request.WebsiteProxyConfig
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.OperateProxy(req)
@@ -749,8 +655,7 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"}
func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
var req request.NginxProxyUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateProxyFile(req); err != nil {
@@ -770,8 +675,7 @@ func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
// @Router /websites/auths [post]
func (b *BaseApi) GetAuthConfig(c *gin.Context) {
var req request.NginxAuthReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.GetAuthBasics(req)
@@ -792,8 +696,7 @@ func (b *BaseApi) GetAuthConfig(c *gin.Context) {
// @Router /websites/auths/update [post]
func (b *BaseApi) UpdateAuthConfig(c *gin.Context) {
var req request.NginxAuthUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateAuthBasic(req); err != nil {
@@ -813,8 +716,7 @@ func (b *BaseApi) UpdateAuthConfig(c *gin.Context) {
// @Router /websites/leech [post]
func (b *BaseApi) GetAntiLeech(c *gin.Context) {
var req request.NginxCommonReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.GetAntiLeech(req.WebsiteID)
@@ -835,8 +737,7 @@ func (b *BaseApi) GetAntiLeech(c *gin.Context) {
// @Router /websites/leech/update [post]
func (b *BaseApi) UpdateAntiLeech(c *gin.Context) {
var req request.NginxAntiLeechUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateAntiLeech(req); err != nil {
@@ -857,8 +758,7 @@ func (b *BaseApi) UpdateAntiLeech(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 重定向理配置 ","formatEN":"Update domain [domain] redirect config"}
func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
var req request.NginxRedirectReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.OperateRedirect(req)
@@ -879,8 +779,7 @@ func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
// @Router /websites/redirect [post]
func (b *BaseApi) GetRedirectConfig(c *gin.Context) {
var req request.WebsiteRedirectReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.GetRedirect(req.WebsiteID)
@@ -902,8 +801,7 @@ func (b *BaseApi) GetRedirectConfig(c *gin.Context) {
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新重定向文件 [domain]","formatEN":"Nginx conf redirect file update [domain]"}
func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) {
var req request.NginxRedirectUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateRedirectFile(req); err != nil {
@@ -923,8 +821,7 @@ func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) {
// @Router /websites/dir [post]
func (b *BaseApi) GetDirConfig(c *gin.Context) {
var req request.WebsiteCommonReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteService.LoadWebsiteDirConfig(req)
+3 -6
View File
@@ -18,8 +18,7 @@ import (
// @Router /websites/acme/search [post]
func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) {
var req dto.PageInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, accounts, err := websiteAcmeAccountService.Page(req)
@@ -44,8 +43,7 @@ func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) {
// @x-panel-log {"bodyKeys":["email"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 acme [email]","formatEN":"Create website acme [email]"}
func (b *BaseApi) CreateWebsiteAcmeAccount(c *gin.Context) {
var req request.WebsiteAcmeAccountCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteAcmeAccountService.Create(req)
@@ -67,8 +65,7 @@ func (b *BaseApi) CreateWebsiteAcmeAccount(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_acme_accounts","output_column":"email","output_value":"email"}],"formatZH":"删除网站 acme [email]","formatEN":"Delete website acme [email]"}
func (b *BaseApi) DeleteWebsiteAcmeAccount(c *gin.Context) {
var req request.WebsiteResourceReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteAcmeAccountService.Delete(req.ID); err != nil {
+4 -9
View File
@@ -18,8 +18,7 @@ import (
// @Router /websites/dns/search [post]
func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) {
var req dto.PageInfo
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, accounts, err := websiteDnsAccountService.Page(req)
@@ -44,8 +43,7 @@ func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 dns [name]","formatEN":"Create website dns [name]"}
func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) {
var req request.WebsiteDnsAccountCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if _, err := websiteDnsAccountService.Create(req); err != nil {
@@ -66,8 +64,7 @@ func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) {
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 dns [name]","formatEN":"Update website dns [name]"}
func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) {
var req request.WebsiteDnsAccountUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if _, err := websiteDnsAccountService.Update(req); err != nil {
@@ -88,11 +85,9 @@ func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_dns_accounts","output_column":"name","output_value":"name"}],"formatZH":"删除网站 dns [name]","formatEN":"Delete website dns [name]"}
func (b *BaseApi) DeleteWebsiteDnsAccount(c *gin.Context) {
var req request.WebsiteResourceReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteDnsAccountService.Delete(req.ID); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
+73
View File
@@ -0,0 +1,73 @@
package v1
import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/gin-gonic/gin"
)
// @Tags Website Domain
// @Summary Delete website domain
// @Description 删除网站域名
// @Accept json
// @Param request body request.WebsiteDomainDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /websites/domains/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"}
func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
var req request.WebsiteDomainDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.DeleteWebsiteDomain(req.ID); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Website Domain
// @Summary Create website domain
// @Description 创建网站域名
// @Accept json
// @Param request body request.WebsiteDomainCreate true "request"
// @Success 200 {object} model.WebsiteDomain
// @Security ApiKeyAuth
// @Router /websites/domains [post]
// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"}
func (b *BaseApi) CreateWebDomain(c *gin.Context) {
var req request.WebsiteDomainCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
domain, err := websiteService.CreateWebsiteDomain(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, domain)
}
// @Tags Website Domain
// @Summary Search website domains by websiteId
// @Description 通过网站 id 查询域名
// @Accept json
// @Param websiteId path integer true "request"
// @Success 200 {array} model.WebsiteDomain
// @Security ApiKeyAuth
// @Router /websites/domains/:websiteId [get]
func (b *BaseApi) GetWebDomains(c *gin.Context) {
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return
}
list, err := websiteService.GetWebsiteDomain(websiteId)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
+27 -12
View File
@@ -20,8 +20,7 @@ import (
// @Router /websites/ssl/search [post]
func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLSearch
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBind(&req, c); err != nil {
return
}
if !reflect.DeepEqual(req.PageInfo, dto.PageInfo{}) {
@@ -55,8 +54,7 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 ssl [primaryDomain]","formatEN":"Create website ssl [primaryDomain]"}
func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteSSLService.Create(req)
@@ -78,8 +76,7 @@ func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
// @x-panel-log {"bodyKeys":["SSLId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"SSLId","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"重置 ssl [domain]","formatEN":"Renew ssl [domain]"}
func (b *BaseApi) RenewWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLRenew
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteSSLService.Renew(req.SSLID); err != nil {
@@ -99,8 +96,7 @@ func (b *BaseApi) RenewWebsiteSSL(c *gin.Context) {
// @Router /websites/ssl/resolve [post]
func (b *BaseApi) GetDNSResolve(c *gin.Context) {
var req request.WebsiteDNSReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := websiteSSLService.GetDNSResolve(req)
@@ -122,8 +118,7 @@ func (b *BaseApi) GetDNSResolve(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除 ssl [domain]","formatEN":"Delete ssl [domain]"}
func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
var req request.WebsiteResourceReq
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteSSLService.Delete(req.ID); err != nil {
@@ -188,8 +183,7 @@ func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) {
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新证书设置 [domain]","formatEN":"Update ssl config [domain]"}
func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteSSLService.Update(req); err != nil {
@@ -198,3 +192,24 @@ func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) {
}
helper.SuccessWithData(c, nil)
}
// @Tags Website SSL
// @Summary Upload ssl
// @Description 上传 ssl
// @Accept json
// @Param request body request.WebsiteSSLUpload true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /websites/ssl/upload [post]
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传 ssl [type]","formatEN":"Upload ssl [type]"}
func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLUpload
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteSSLService.Upload(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
+12 -12
View File
@@ -12,29 +12,29 @@ type UserLoginInfo struct {
}
type MfaRequest struct {
Title string `json:"title"`
Interval int `json:"interval"`
Title string `json:"title" validate:"required"`
Interval int `json:"interval" validate:"required"`
}
type MfaCredential struct {
Secret string `json:"secret"`
Code string `json:"code"`
Interval string `json:"interval"`
Secret string `json:"secret" validate:"required"`
Code string `json:"code" validate:"required"`
Interval string `json:"interval" validate:"required"`
}
type Login struct {
Name string `json:"name"`
Password string `json:"password"`
Name string `json:"name" validate:"required"`
Password string `json:"password" validate:"required"`
IgnoreCaptcha bool `json:"ignoreCaptcha"`
Captcha string `json:"captcha"`
CaptchaID string `json:"captchaID"`
AuthMethod string `json:"authMethod"`
Language string `json:"language"`
AuthMethod string `json:"authMethod" validate:"required,oneof=jwt session"`
Language string `json:"language" validate:"required,oneof=zh en tw"`
}
type MFALogin struct {
Name string `json:"name"`
Password string `json:"password"`
Code string `json:"code"`
Name string `json:"name" validate:"required"`
Password string `json:"password" validate:"required"`
Code string `json:"code" validate:"required"`
AuthMethod string `json:"authMethod"`
}
+1 -1
View File
@@ -41,7 +41,7 @@ type CommonRecover struct {
type RecordSearch struct {
PageInfo
Type string `json:"type" validate:"required"`
Name string `json:"name" validate:"required"`
Name string `json:"name"`
DetailName string `json:"detailName"`
}
+22 -6
View File
@@ -1,13 +1,29 @@
package dto
type SearchCommandWithPage struct {
SearchWithPage
GroupID uint `json:"groupID"`
Info string `json:"info"`
}
type CommandOperate struct {
ID uint `json:"id"`
Name string `json:"name" validate:"required"`
Command string `json:"command" validate:"required"`
ID uint `json:"id"`
GroupID uint `json:"groupID"`
GroupBelong string `json:"groupBelong"`
Name string `json:"name" validate:"required"`
Command string `json:"command" validate:"required"`
}
type CommandInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Command string `json:"command"`
ID uint `json:"id"`
GroupID uint `json:"groupID"`
Name string `json:"name"`
Command string `json:"command"`
GroupBelong string `json:"groupBelong"`
}
type CommandTree struct {
ID uint `json:"id"`
Label string `json:"label"`
Children []CommandInfo `json:"children"`
}
+1 -1
View File
@@ -42,6 +42,6 @@ type DeleteByName struct {
}
type OperationWithNameAndType struct {
Name string `json:"name" validate:"required"`
Name string `json:"name"`
Type string `json:"type" validate:"required"`
}
+16 -11
View File
@@ -5,14 +5,15 @@ import "time"
type PageContainer struct {
PageInfo
Name string `json:"name"`
State string `json:"state" validate:"required,oneof=all created running paused restarting removing exited dead"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
Filters string `json:"filters"`
}
type InspectReq struct {
ID string `json:"id"`
Type string `json:"type"`
ID string `json:"id" validate:"required"`
Type string `json:"type" validate:"required"`
}
type ContainerInfo struct {
@@ -39,8 +40,8 @@ type ResourceLimit struct {
type ContainerOperate struct {
ContainerID string `json:"containerID"`
ForcePull bool `json:"forcePull"`
Name string `json:"name"`
Image string `json:"image"`
Name string `json:"name" validate:"required"`
Image string `json:"image" validate:"required"`
Network string `json:"network"`
PublishAllPorts bool `json:"publishAllPorts"`
ExposedPorts []PortHelper `json:"exposedPorts"`
@@ -103,9 +104,13 @@ type PortHelper struct {
}
type ContainerOperation struct {
Name string `json:"name" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=start stop restart kill pause unpause rename remove"`
NewName string `json:"newName"`
Names []string `json:"names" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=start stop restart kill pause unpause remove"`
}
type ContainerRename struct {
Name string `json:"name" validate:"required"`
NewName string `json:"newName" validate:"required"`
}
type ContainerPrune struct {
@@ -130,8 +135,8 @@ type Network struct {
Attachable bool `json:"attachable"`
}
type NetworkCreate struct {
Name string `json:"name"`
Driver string `json:"driver"`
Name string `json:"name" validate:"required"`
Driver string `json:"driver" validate:"required"`
Options []string `json:"options"`
Subnet string `json:"subnet"`
Gateway string `json:"gateway"`
@@ -147,8 +152,8 @@ type Volume struct {
CreatedAt time.Time `json:"createdAt"`
}
type VolumeCreate struct {
Name string `json:"name"`
Driver string `json:"driver"`
Name string `json:"name" validate:"required"`
Driver string `json:"driver" validate:"required"`
Options []string `json:"options"`
Labels []string `json:"labels"`
}
+1 -1
View File
@@ -65,7 +65,7 @@ type CronjobClean struct {
type CronjobBatchDelete struct {
CleanData bool `json:"cleanData"`
IDs []uint `json:"ids"`
IDs []uint `json:"ids" validate:"required"`
}
type CronjobInfo struct {
+1 -1
View File
@@ -170,7 +170,7 @@ type RedisConfPersistenceUpdate struct {
Save string `json:"save"`
}
type RedisConfUpdateByFile struct {
File string `json:"file"`
File string `json:"file" validate:"required"`
RestartNow bool `json:"restartNow"`
}
+2
View File
@@ -31,6 +31,7 @@ type AppContainerConfig struct {
AllowPort bool `json:"allowPort"`
EditCompose bool `json:"editCompose"`
DockerCompose string `json:"dockerCompose"`
HostMode bool `json:"hostMode"`
}
type AppInstalledSearch struct {
@@ -40,6 +41,7 @@ type AppInstalledSearch struct {
Tags []string `json:"tags"`
Update bool `json:"update"`
Unused bool `json:"unused"`
All bool `json:"all"`
}
type AppInstalledInfo struct {
+9
View File
@@ -0,0 +1,9 @@
package request
type FavoriteCreate struct {
Path string `json:"path" validate:"required"`
}
type FavoriteDelete struct {
ID uint `json:"id" validate:"required"`
}
+30 -4
View File
@@ -9,6 +9,10 @@ type FileOption struct {
files.FileOption
}
type FileContentReq struct {
Path string `json:"path" validate:"required"`
}
type SearchUploadWithPage struct {
dto.PageInfo
Path string `json:"path" validate:"required"`
@@ -25,9 +29,18 @@ type FileCreate struct {
Sub bool `json:"sub"`
}
type FileRoleReq struct {
Paths []string `json:"paths" validate:"required"`
Mode int64 `json:"mode" validate:"required"`
User string `json:"user" validate:"required"`
Group string `json:"group" validate:"required"`
Sub bool `json:"sub"`
}
type FileDelete struct {
Path string `json:"path" validate:"required"`
IsDir bool `json:"isDir"`
Path string `json:"path" validate:"required"`
IsDir bool `json:"isDir"`
ForceDelete bool `json:"forceDelete"`
}
type FileBatchDelete struct {
@@ -73,13 +86,15 @@ type FileMove struct {
Type string `json:"type" validate:"required"`
OldPaths []string `json:"oldPaths" validate:"required"`
NewPath string `json:"newPath" validate:"required"`
Name string `json:"name"`
Cover bool `json:"cover"`
}
type FileDownload struct {
Paths []string `json:"paths" validate:"required"`
Type string `json:"type" validate:"required"`
Name string `json:"name" validate:"required"`
Compress bool `json:"compress" validate:"required"`
Compress bool `json:"compress"`
}
type FileChunkDownload struct {
@@ -99,5 +114,16 @@ type FileRoleUpdate struct {
Path string `json:"path" validate:"required"`
User string `json:"user" validate:"required"`
Group string `json:"group" validate:"required"`
Sub bool `json:"sub" validate:"required"`
Sub bool `json:"sub"`
}
type FileReadByLineReq struct {
Path string `json:"path" validate:"required"`
Page int `json:"page" validate:"required"`
PageSize int `json:"pageSize" validate:"required"`
}
type FileExistReq struct {
Name string `json:"name" validate:"required"`
Dir string `json:"dir" validate:"required"`
}
+8 -8
View File
@@ -4,7 +4,7 @@ import "github.com/1Panel-dev/1Panel/backend/app/dto"
type NginxConfigFileUpdate struct {
Content string `json:"content" validate:"required"`
Backup bool `json:"backup" validate:"required"`
Backup bool `json:"backup"`
}
type NginxScopeReq struct {
@@ -14,8 +14,8 @@ type NginxScopeReq struct {
type NginxConfigUpdate struct {
Scope dto.NginxKey `json:"scope"`
Operate string `json:"operate" validate:"required;oneof=add update delete"`
WebsiteID uint `json:"websiteId" validate:"required"`
Operate string `json:"operate" validate:"required,oneof=add update delete"`
WebsiteID uint `json:"websiteId"`
Params interface{} `json:"params"`
}
@@ -39,8 +39,8 @@ type NginxProxyUpdate struct {
type NginxAuthUpdate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Operate string `json:"operate" validate:"required"`
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
Username string `json:"username"`
Password string `json:"password"`
Remark string `json:"remark"`
}
@@ -56,7 +56,7 @@ type NginxAntiLeechUpdate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Extends string `json:"extends" validate:"required"`
Return string `json:"return" validate:"required"`
Enable bool `json:"enable" validate:"required"`
Enable bool `json:"enable" `
ServerNames []string `json:"serverNames"`
Cache bool `json:"cache"`
CacheTime int `json:"cacheTime"`
@@ -70,8 +70,8 @@ type NginxRedirectReq struct {
Name string `json:"name" validate:"required"`
WebsiteID uint `json:"websiteID" validate:"required"`
Domains []string `json:"domains"`
KeepPath bool `json:"keepPath" validate:"required"`
Enable bool `json:"enable" validate:"required"`
KeepPath bool `json:"keepPath"`
Enable bool `json:"enable"`
Type string `json:"type" validate:"required"`
Redirect string `json:"redirect" validate:"required"`
Path string `json:"path"`
+11
View File
@@ -0,0 +1,11 @@
package request
type RecycleBinCreate struct {
SourcePath string `json:"sourcePath" validate:"required"`
}
type RecycleBinReduce struct {
From string `json:"from" validate:"required"`
RName string `json:"rName" validate:"required"`
Name string `json:"name"`
}
+9 -3
View File
@@ -23,9 +23,15 @@ type RuntimeCreate struct {
}
type NodeConfig struct {
Install bool `json:"install"`
Clean bool `json:"clean"`
Port int `json:"port"`
Install bool `json:"install"`
Clean bool `json:"clean"`
Port int `json:"port"`
ExposedPorts []ExposedPort `json:"exposedPorts"`
}
type ExposedPort struct {
HostPort int `json:"hostPort"`
ContainerPort int `json:"containerPort"`
}
type RuntimeDelete struct {
+12 -13
View File
@@ -45,7 +45,7 @@ type NewAppInstall struct {
}
type WebsiteInstallCheckReq struct {
InstallIds []uint `json:"InstallIds" validate:"required"`
InstallIds []uint `json:"InstallIds"`
}
type WebsiteUpdate struct {
@@ -78,13 +78,13 @@ type WebsiteWafReq struct {
type WebsiteRedirectUpdate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
Enable bool `json:"enable" validate:"required"`
Enable bool `json:"enable"`
}
type WebsiteWafUpdate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
Enable bool `json:"enable" validate:"required"`
Enable bool `json:"enable"`
}
type WebsiteRecover struct {
@@ -111,9 +111,8 @@ type WebsiteGroupUpdate struct {
}
type WebsiteDomainCreate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Port int `json:"port" validate:"required"`
Domain string `json:"domain" validate:"required"`
WebsiteID uint `json:"websiteID" validate:"required"`
Domains string `json:"domains" validate:"required"`
}
type WebsiteDomainDelete struct {
@@ -122,7 +121,7 @@ type WebsiteDomainDelete struct {
type WebsiteHTTPSOp struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Enable bool `json:"enable" validate:"required"`
Enable bool `json:"enable"`
WebsiteSSLID uint `json:"websiteSSLId"`
Type string `json:"type" validate:"oneof=existed auto manual"`
PrivateKey string `json:"privateKey"`
@@ -149,7 +148,7 @@ type WebsiteLogReq struct {
}
type WebsiteDefaultUpdate struct {
ID uint `json:"id" validate:"required"`
ID uint `json:"id"`
}
type WebsitePHPConfigUpdate struct {
@@ -169,7 +168,7 @@ type WebsitePHPFileUpdate struct {
type WebsitePHPVersionReq struct {
WebsiteID uint `json:"websiteID" validate:"required"`
RuntimeID uint `json:"runtimeID" validate:"required"`
RetainConfig bool `json:"retainConfig" validate:"required"`
RetainConfig bool `json:"retainConfig" `
}
type WebsiteUpdateDir struct {
@@ -186,10 +185,10 @@ type WebsiteUpdateDirPermission struct {
type WebsiteProxyConfig struct {
ID uint `json:"id" validate:"required"`
Operate string `json:"operate" validate:"required"`
Enable bool `json:"enable" validate:"required"`
Cache bool `json:"cache" validate:"required"`
CacheTime int `json:"cacheTime" validate:"required"`
CacheUnit string `json:"cacheUnit" validate:"required"`
Enable bool `json:"enable" `
Cache bool `json:"cache" `
CacheTime int `json:"cacheTime" `
CacheUnit string `json:"cacheUnit"`
Name string `json:"name" validate:"required"`
Modifier string `json:"modifier" validate:"required"`
Match string `json:"match" validate:"required"`
+10 -2
View File
@@ -13,7 +13,7 @@ type WebsiteSSLCreate struct {
Provider string `json:"provider" validate:"required"`
AcmeAccountID uint `json:"acmeAccountId" validate:"required"`
DnsAccountID uint `json:"dnsAccountId"`
AutoRenew bool `json:"autoRenew" validate:"required"`
AutoRenew bool `json:"autoRenew"`
}
type WebsiteDNSReq struct {
@@ -48,5 +48,13 @@ type WebsiteResourceReq struct {
type WebsiteSSLUpdate struct {
ID uint `json:"id" validate:"required"`
AutoRenew bool `json:"autoRenew" validate:"required"`
AutoRenew bool `json:"autoRenew"`
}
type WebsiteSSLUpload struct {
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
Type string `json:"type" validate:"required,oneof=paste local"`
}
+5 -3
View File
@@ -15,6 +15,7 @@ type AppRes struct {
type AppUpdateRes struct {
CanUpdate bool `json:"canUpdate"`
IsSyncing bool `json:"isSyncing"`
AppStoreLastModified int `json:"appStoreLastModified"`
AppList *dto.AppList `json:"appList"`
}
@@ -47,9 +48,10 @@ type AppInstalledCheck struct {
type AppDetailDTO struct {
model.AppDetail
Enable bool `json:"enable"`
Params interface{} `json:"params"`
Image string `json:"image"`
Enable bool `json:"enable"`
Params interface{} `json:"params"`
Image string `json:"image"`
HostMode bool `json:"hostMode"`
}
type IgnoredApp struct {
+7
View File
@@ -0,0 +1,7 @@
package response
import "github.com/1Panel-dev/1Panel/backend/app/model"
type FavoriteDTO struct {
model.Favorite
}
+10
View File
@@ -32,3 +32,13 @@ type FileProcessKeys struct {
type FileWgetRes struct {
Key string `json:"key"`
}
type FileLineContent struct {
Content string `json:"content"`
End bool `json:"end"`
Path string `json:"path"`
}
type FileExist struct {
Exist bool `json:"exist"`
}
+14
View File
@@ -0,0 +1,14 @@
package response
import "time"
type RecycleBinDTO struct {
Name string `json:"name"`
Size int `json:"size"`
Type string `json:"type"`
DeleteTime time.Time `json:"deleteTime"`
RName string `json:"rName"`
SourcePath string `json:"sourcePath"`
IsDir bool `json:"isDir"`
From string `json:"from"`
}
+19 -17
View File
@@ -1,28 +1,30 @@
package response
import (
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/model"
"time"
)
type RuntimeDTO struct {
ID uint `json:"id"`
Name string `json:"name"`
Resource string `json:"resource"`
AppDetailID uint `json:"appDetailID"`
AppID uint `json:"appID"`
Source string `json:"source"`
Status string `json:"status"`
Type string `json:"type"`
Image string `json:"image"`
Params map[string]interface{} `json:"params"`
Message string `json:"message"`
Version string `json:"version"`
CreatedAt time.Time `json:"createdAt"`
CodeDir string `json:"codeDir"`
AppParams []AppParam `json:"appParams"`
Port int `json:"port"`
Path string `json:"path"`
ID uint `json:"id"`
Name string `json:"name"`
Resource string `json:"resource"`
AppDetailID uint `json:"appDetailID"`
AppID uint `json:"appID"`
Source string `json:"source"`
Status string `json:"status"`
Type string `json:"type"`
Image string `json:"image"`
Params map[string]interface{} `json:"params"`
Message string `json:"message"`
Version string `json:"version"`
CreatedAt time.Time `json:"createdAt"`
CodeDir string `json:"codeDir"`
AppParams []AppParam `json:"appParams"`
Port int `json:"port"`
Path string `json:"path"`
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
}
type PackageScripts struct {
+10 -2
View File
@@ -14,6 +14,8 @@ type SettingInfo struct {
NtpSite string `json:"ntpSite"`
Port string `json:"port"`
Ipv6 string `json:"ipv6"`
BindAddress string `json:"bindAddress"`
PanelName string `json:"panelName"`
Theme string `json:"theme"`
Language string `json:"language"`
@@ -46,6 +48,7 @@ type SettingInfo struct {
AppStoreVersion string `json:"appStoreVersion"`
AppStoreLastModified string `json:"appStoreLastModified"`
AppStoreSyncStatus string `json:"appStoreSyncStatus"`
}
type SettingUpdate struct {
@@ -133,11 +136,16 @@ type UpgradeInfo struct {
}
type SyncTime struct {
NtpSite string `json:"ntpSite"`
NtpSite string `json:"ntpSite" validate:"required"`
}
type BindInfo struct {
Ipv6 string `json:"ipv6" validate:"required,oneof=enable disable"`
BindAddress string `json:"bindAddress" validate:"required"`
}
type Upgrade struct {
Version string `json:"version"`
Version string `json:"version" validate:"required"`
}
type CleanData struct {
+7
View File
@@ -2,7 +2,14 @@ package dto
import "time"
type SSHUpdate struct {
Key string `json:"key" validate:"required"`
OldValue string `json:"oldValue"`
NewValue string `json:"newValue"`
}
type SSHInfo struct {
AutoStart bool `json:"autoStart"`
Status string `json:"status"`
Message string `json:"message"`
Port string `json:"port"`
+4 -4
View File
@@ -27,18 +27,18 @@ type AppInstall struct {
}
func (i *AppInstall) GetPath() string {
return path.Join(i.getAppPath(), i.Name)
return path.Join(i.GetAppPath(), i.Name)
}
func (i *AppInstall) GetComposePath() string {
return path.Join(i.getAppPath(), i.Name, "docker-compose.yml")
return path.Join(i.GetAppPath(), i.Name, "docker-compose.yml")
}
func (i *AppInstall) GetEnvPath() string {
return path.Join(i.getAppPath(), i.Name, ".env")
return path.Join(i.GetAppPath(), i.Name, ".env")
}
func (i *AppInstall) getAppPath() string {
func (i *AppInstall) GetAppPath() string {
if i.App.Resource == constant.AppResourceLocal {
return path.Join(constant.LocalAppInstallDir, strings.TrimPrefix(i.App.Key, constant.AppResourceLocal))
} else {
+1
View File
@@ -3,5 +3,6 @@ package model
type Command struct {
BaseModel
Name string `gorm:"type:varchar(64);unique;not null" json:"name"`
GroupID uint `gorm:"type:decimal" json:"groupID"`
Command string `gorm:"type:varchar(256);not null" json:"command"`
}
+10
View File
@@ -0,0 +1,10 @@
package model
type Favorite struct {
BaseModel
Name string `gorm:"type:varchar(256);not null;" json:"name" `
Path string `gorm:"type:varchar(256);not null;unique" json:"path"`
Type string `gorm:"type:varchar(64);" json:"type"`
IsDir bool `json:"isDir"`
IsTxt bool `json:"isTxt"`
}
+66
View File
@@ -0,0 +1,66 @@
package repo
import (
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/global"
"gorm.io/gorm"
)
type FavoriteRepo struct{}
type IFavoriteRepo interface {
Page(page, size int, opts ...DBOption) (int64, []model.Favorite, error)
Create(group *model.Favorite) error
Delete(opts ...DBOption) error
GetFirst(opts ...DBOption) (model.Favorite, error)
All() ([]model.Favorite, error)
WithByPath(path string) DBOption
}
func NewIFavoriteRepo() IFavoriteRepo {
return &FavoriteRepo{}
}
func (f *FavoriteRepo) WithByPath(path string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("path = ?", path)
}
}
func (f *FavoriteRepo) Page(page, size int, opts ...DBOption) (int64, []model.Favorite, error) {
var (
favorites []model.Favorite
count int64
)
count = int64(0)
db := getDb(opts...).Model(&model.Favorite{})
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&favorites).Error
return count, favorites, err
}
func (f *FavoriteRepo) Create(favorite *model.Favorite) error {
return global.DB.Create(favorite).Error
}
func (f *FavoriteRepo) GetFirst(opts ...DBOption) (model.Favorite, error) {
var favorite model.Favorite
db := getDb(opts...).Model(&model.Favorite{})
if err := db.First(&favorite).Error; err != nil {
return favorite, err
}
return favorite, nil
}
func (f *FavoriteRepo) Delete(opts ...DBOption) error {
db := getDb(opts...).Model(&model.Favorite{})
return db.Delete(&model.Favorite{}).Error
}
func (f *FavoriteRepo) All() ([]model.Favorite, error) {
var favorites []model.Favorite
if err := getDb().Find(&favorites).Error; err != nil {
return nil, err
}
return favorites, nil
}
+3 -3
View File
@@ -15,7 +15,7 @@ type IGroupRepo interface {
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
CancelDefault(groupType string) error
WithByIsDefault(isDefault bool) DBOption
WithByHostDefault() DBOption
}
func NewIGroupRepo() IGroupRepo {
@@ -50,9 +50,9 @@ func (u *GroupRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.Group{}).Where("id = ?", id).Updates(vars).Error
}
func (u *GroupRepo) WithByIsDefault(isDefault bool) DBOption {
func (u *GroupRepo) WithByHostDefault() DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("is_default = ?", isDefault)
return g.Where("is_default = ? AND type = ?", 1, "host")
}
}
+63 -20
View File
@@ -222,6 +222,27 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response.
appDetailDTO.Params = paramMap
}
if appDetailDTO.DockerCompose == "" {
filename := path.Base(appDetailDTO.DownloadUrl)
dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(appDetailDTO.DownloadUrl, filename), "docker-compose.yml")
composeRes, err := http.Get(dockerComposeUrl)
if err != nil {
return appDetailDTO, buserr.WithDetail("ErrGetCompose", err.Error(), err)
}
bodyContent, err := io.ReadAll(composeRes.Body)
if err != nil {
return appDetailDTO, buserr.WithDetail("ErrGetCompose", err.Error(), err)
}
if composeRes.StatusCode > 200 {
return appDetailDTO, buserr.WithDetail("ErrGetCompose", string(bodyContent), err)
}
detail.DockerCompose = string(bodyContent)
_ = appDetailRepo.Update(context.Background(), detail)
appDetailDTO.DockerCompose = string(bodyContent)
}
appDetailDTO.HostMode = isHostModel(appDetailDTO.DockerCompose)
app, err := appRepo.GetFirst(commonRepo.WithByID(detail.AppId))
if err != nil {
return appDetailDTO, err
@@ -243,6 +264,7 @@ func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) {
return nil, err
}
res.Params = paramMap
res.HostMode = isHostModel(appDetail.DockerCompose)
return res, nil
}
@@ -693,6 +715,11 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
if err != nil {
return nil, err
}
if setting.AppStoreSyncStatus == constant.Syncing {
res.IsSyncing = true
return res, nil
}
appStoreLastModified, _ := strconv.Atoi(setting.AppStoreLastModified)
res.AppStoreLastModified = appStoreLastModified
if setting.AppStoreLastModified == "" || lastModified != appStoreLastModified {
@@ -719,7 +746,7 @@ func getAppFromRepo(downloadPath string) error {
if err := fileOp.DownloadFile(downloadUrl, packagePath); err != nil {
return err
}
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.Zip); err != nil {
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.SdkZip); err != nil {
return err
}
defer func() {
@@ -744,6 +771,12 @@ func getAppList() (*dto.AppList, error) {
return list, nil
}
var InitTypes = map[string]struct{}{
"runtime": {},
"php": {},
"node": {},
}
func (a AppService) SyncAppListFromRemote() (err error) {
global.LOG.Infof("Starting synchronization with App Store...")
updateRes, err := a.GetAppUpdate()
@@ -751,9 +784,14 @@ func (a AppService) SyncAppListFromRemote() (err error) {
return err
}
if !updateRes.CanUpdate {
if updateRes.IsSyncing {
global.LOG.Infof("AppStore is Syncing!")
return
}
global.LOG.Infof("The App Store is at the latest version")
return
}
list := &dto.AppList{}
if updateRes.AppList == nil {
list, err = getAppList()
@@ -763,16 +801,8 @@ func (a AppService) SyncAppListFromRemote() (err error) {
} else {
list = updateRes.AppList
}
if err = NewISettingService().Update("AppStoreLastModified", strconv.Itoa(list.LastModified)); err != nil {
return err
}
defer func() {
if err != nil {
_ = NewISettingService().Update("AppStoreLastModified", strconv.Itoa(updateRes.AppStoreLastModified))
}
}()
settingService := NewISettingService()
_ = settingService.Update("AppStoreSyncStatus", constant.Syncing)
var (
tags []*model.Tag
@@ -796,6 +826,8 @@ func (a AppService) SyncAppListFromRemote() (err error) {
baseRemoteUrl := fmt.Sprintf("%s/%s/1panel", global.CONF.System.AppRepo, global.CONF.System.Mode)
appsMap := getApps(oldApps, list.Apps)
global.LOG.Infof("Starting synchronization of application details...")
for _, l := range list.Apps {
app := appsMap[l.AppProperty.Key]
iconRes, err := http.Get(l.Icon)
@@ -822,16 +854,21 @@ func (a AppService) SyncAppListFromRemote() (err error) {
version := v.Name
detail := detailsMap[version]
versionUrl := fmt.Sprintf("%s/%s/%s", baseRemoteUrl, app.Key, version)
dockerComposeUrl := fmt.Sprintf("%s/%s", versionUrl, "docker-compose.yml")
composeRes, err := http.Get(dockerComposeUrl)
if err != nil {
return err
if _, ok := InitTypes[app.Type]; ok {
dockerComposeUrl := fmt.Sprintf("%s/%s", versionUrl, "docker-compose.yml")
composeRes, err := http.Get(dockerComposeUrl)
if err != nil {
return err
}
bodyContent, err := io.ReadAll(composeRes.Body)
if err != nil {
return err
}
detail.DockerCompose = string(bodyContent)
} else {
detail.DockerCompose = ""
}
bodyContent, err := io.ReadAll(composeRes.Body)
if err != nil {
return err
}
detail.DockerCompose = string(bodyContent)
paramByte, _ := json.Marshal(v.AppForm)
detail.Params = string(paramByte)
@@ -849,6 +886,8 @@ func (a AppService) SyncAppListFromRemote() (err error) {
appsMap[l.AppProperty.Key] = app
}
global.LOG.Infof("Synchronization of application details Success")
var (
addAppArray []model.App
updateAppArray []model.App
@@ -973,6 +1012,10 @@ func (a AppService) SyncAppListFromRemote() (err error) {
}
}
tx.Commit()
_ = settingService.Update("AppStoreSyncStatus", constant.SyncSuccess)
_ = settingService.Update("AppStoreLastModified", strconv.Itoa(list.LastModified))
global.LOG.Infof("Synchronization with the App Store was successful!")
return
}
+2 -1
View File
@@ -518,7 +518,7 @@ func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error {
return nil
}
if err := updateInstallInfoInDB(req.Key, "", "port", true, strconv.FormatInt(req.Port, 10)); err != nil {
if err := updateInstallInfoInDB(req.Key, req.Name, "port", true, strconv.FormatInt(req.Port, 10)); err != nil {
return nil
}
@@ -675,6 +675,7 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
config.ContainerName = install.ContainerName
}
res.AppContainerConfig = config
res.HostMode = isHostModel(install.DockerCompose)
return &res, nil
}
+27 -1
View File
@@ -419,6 +419,16 @@ func upgradeInstall(installId uint, detailId uint, backup bool) error {
_, _ = scriptCmd.CombinedOutput()
}
if detail.DockerCompose == "" {
composeDetail, err := fileOp.GetContent(path.Join(detailDir, "docker-compose.yml"))
if err != nil {
upErr = err
return
}
detail.DockerCompose = string(composeDetail)
_ = appDetailRepo.Update(context.Background(), detail)
}
composeMap := make(map[string]interface{})
if upErr = yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); upErr != nil {
return
@@ -649,7 +659,7 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
global.LOG.Errorf("download app[%s] error %v", app.Name, err)
return
}
if err = fileOp.Decompress(filePath, appResourceDir, files.TarGz); err != nil {
if err = fileOp.Decompress(filePath, appResourceDir, files.SdkTarGz); err != nil {
global.LOG.Errorf("decompress app[%s] error %v", app.Name, err)
return
}
@@ -1196,3 +1206,19 @@ func getAppCommonConfig(envs map[string]interface{}) request.AppContainerConfig
return config
}
func isHostModel(dockerCompose string) bool {
composeMap := make(map[string]interface{})
_ = yaml.Unmarshal([]byte(dockerCompose), &composeMap)
services, serviceValid := composeMap["services"].(map[string]interface{})
if !serviceValid {
return false
}
for _, service := range services {
serviceValue := service.(map[string]interface{})
if value, ok := serviceValue["network_mode"]; ok && value == "host" {
return true
}
}
return false
}
+50 -4
View File
@@ -1,6 +1,7 @@
package service
import (
"bufio"
"context"
"encoding/base64"
"encoding/json"
@@ -150,20 +151,26 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error)
return targetPath, nil
}
func (u *BackupService) Create(backupDto dto.BackupOperate) error {
backup, _ := backupRepo.Get(commonRepo.WithByType(backupDto.Type))
func (u *BackupService) Create(req dto.BackupOperate) error {
backup, _ := backupRepo.Get(commonRepo.WithByType(req.Type))
if backup.ID != 0 {
return constant.ErrRecordExist
}
if err := copier.Copy(&backup, &backupDto); err != nil {
if err := copier.Copy(&backup, &req); err != nil {
return errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if backupDto.Type == constant.OneDrive {
if req.Type == constant.OneDrive {
if err := u.loadAccessToken(&backup); err != nil {
return err
}
}
if req.Type != "LOCAL" {
isOk, err := u.checkBackupConn(&backup)
if err != nil || !isOk {
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
}
}
if err := backupRepo.Create(&backup); err != nil {
return err
}
@@ -242,10 +249,15 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
}
upMap := make(map[string]interface{})
upMap["bucket"] = req.Bucket
upMap["access_key"] = req.AccessKey
upMap["credential"] = req.Credential
upMap["backup_path"] = req.BackupPath
upMap["vars"] = req.Vars
backup.Bucket = req.Bucket
backup.Vars = req.Vars
backup.Credential = req.Credential
backup.AccessKey = req.AccessKey
backup.BackupPath = req.BackupPath
if req.Type == constant.OneDrive {
if err := u.loadAccessToken(&backup); err != nil {
@@ -254,6 +266,13 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
upMap["credential"] = backup.Credential
upMap["vars"] = backup.Vars
}
if backup.Type != "LOCAL" {
isOk, err := u.checkBackupConn(&backup)
if err != nil || !isOk {
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
}
}
if err := backupRepo.Update(req.ID, upMap); err != nil {
return err
}
@@ -441,3 +460,30 @@ func copyDir(src, dst string) error {
return nil
}
func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, error) {
client, err := u.NewClient(backup)
if err != nil {
return false, err
}
fileItem := path.Join(global.CONF.System.TmpDir, "test", "1panel")
if _, err := os.Stat(path.Dir(fileItem)); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(fileItem), os.ModePerm); err != nil {
return false, err
}
}
file, err := os.OpenFile(fileItem, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return false, err
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString(string("1Panel 备份账号测试文件。\n"))
_, _ = write.WriteString(string("1Panel 備份賬號測試文件。\n"))
_, _ = write.WriteString(string("1Panel Backs up account test files.\n"))
_, _ = write.WriteString(string("1Panelアカウントのテストファイルをバックアップします。\n"))
write.Flush()
targetPath := strings.TrimPrefix(path.Join(backup.BackupPath, "test/1panel"), "/")
return client.Upload(fileItem, targetPath)
}
+1 -1
View File
@@ -225,7 +225,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
_ = fileOp.Rename(appDir, backPath)
_ = fileOp.CreateDir(appDir, 0755)
if err := handleUnTar(tmpPath+"/app.tar.gz", fmt.Sprintf("%s/%s", constant.AppInstallDir, install.App.Key)); err != nil {
if err := handleUnTar(tmpPath+"/app.tar.gz", install.GetAppPath()); err != nil {
global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err)
_ = fileOp.DeleteDir(appDir)
_ = fileOp.Rename(backPath, appDir)
+40 -3
View File
@@ -11,7 +11,8 @@ type CommandService struct{}
type ICommandService interface {
List() ([]dto.CommandInfo, error)
SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error)
SearchForTree() ([]dto.CommandTree, error)
SearchWithPage(search dto.SearchCommandWithPage) (int64, interface{}, error)
Create(commandDto dto.CommandOperate) error
Update(id uint, upMap map[string]interface{}) error
Delete(ids []uint) error
@@ -37,14 +38,50 @@ func (u *CommandService) List() ([]dto.CommandInfo, error) {
return dtoCommands, err
}
func (u *CommandService) SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) {
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info))
func (u *CommandService) SearchForTree() ([]dto.CommandTree, error) {
cmdList, err := commandRepo.GetList()
if err != nil {
return nil, err
}
groups, err := groupRepo.GetList(commonRepo.WithByType("command"))
if err != nil {
return nil, err
}
var lists []dto.CommandTree
for _, group := range groups {
var data dto.CommandTree
data.ID = group.ID + 10000
data.Label = group.Name
for _, cmd := range cmdList {
if cmd.GroupID == group.ID {
data.Children = append(data.Children, dto.CommandInfo{ID: cmd.ID, Name: cmd.Name, Command: cmd.Command})
}
}
if len(data.Children) != 0 {
lists = append(lists, data)
}
}
return lists, err
}
func (u *CommandService) SearchWithPage(search dto.SearchCommandWithPage) (int64, interface{}, error) {
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info), commonRepo.WithByGroupID(search.GroupID))
if err != nil {
return 0, nil, err
}
groups, _ := groupRepo.GetList(commonRepo.WithByType("command"))
var dtoCommands []dto.CommandInfo
for _, command := range commands {
var item dto.CommandInfo
if err := copier.Copy(&item, &command); err != nil {
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
for _, group := range groups {
if command.GroupID == group.ID {
item.GroupBelong = group.Name
item.GroupID = group.ID
}
}
dtoCommands = append(dtoCommands, item)
}
return total, dtoCommands, err
+107 -45
View File
@@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"time"
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -52,9 +53,10 @@ type IContainerService interface {
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
ContainerListStats() ([]dto.ContainerListStats, error)
LoadResourceLimit() (*dto.ResourceLimit, error)
ContainerRename(req dto.ContainerRename) error
ContainerLogClean(req dto.OperationWithName) error
ContainerOperation(req dto.ContainerOperation) error
ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error
ContainerLogs(wsConn *websocket.Conn, containerType, container, since, tail string, follow bool) error
ContainerStats(id string) (*dto.ContainerStats, error)
Inspect(req dto.InspectReq) (string, error)
DeleteNetwork(req dto.BatchDelete) error
@@ -66,7 +68,6 @@ type IContainerService interface {
Prune(req dto.ContainerPrune) (dto.ContainerPruneReport, error)
LoadContainerLogs(req dto.OperationWithNameAndType) string
ComposeLogs(wsConn *websocket.Conn, composePath, since, tail string, follow bool) error
}
func NewIContainerService() IContainerService {
@@ -102,6 +103,17 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
}
}
}
if req.State != "all" {
length, count := len(list), 0
for count < length {
if list[count].State != req.State {
list = append(list[:count], list[(count+1):]...)
length--
} else {
count++
}
}
}
switch req.OrderBy {
case "name":
sort.Slice(list, func(i, j int) bool {
@@ -316,11 +328,6 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
return buserr.New(constant.ErrContainerName)
}
config, hostConf, networkConf, err := loadConfigInfo(true, req, nil)
if err != nil {
return err
}
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
if !checkImageExist(client, req.Image) || req.ForcePull {
if err := pullImages(ctx, client, req.Image); err != nil {
if !req.ForcePull {
@@ -329,6 +336,21 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
global.LOG.Errorf("force pull image %s failed, err: %v", req.Image, err)
}
}
imageInfo, _, err := client.ImageInspectWithRaw(ctx, req.Image)
if err != nil {
return err
}
if len(req.Entrypoint) == 0 {
req.Entrypoint = imageInfo.Config.Entrypoint
}
if len(req.Cmd) == 0 {
req.Cmd = imageInfo.Config.Cmd
}
config, hostConf, networkConf, err := loadConfigInfo(true, req, nil)
if err != nil {
return err
}
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
if err != nil {
_ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
@@ -493,6 +515,20 @@ func (u *ContainerService) ContainerUpgrade(req dto.ContainerUpgrade) error {
return nil
}
func (u *ContainerService) ContainerRename(req dto.ContainerRename) error {
ctx := context.Background()
client, err := docker.NewDockerClient()
if err != nil {
return err
}
newContainer, _ := client.ContainerInspect(ctx, req.NewName)
if newContainer.ContainerJSONBase != nil {
return buserr.New(constant.ErrContainerName)
}
return client.ContainerRename(ctx, req.Name, req.NewName)
}
func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error {
var err error
ctx := context.Background()
@@ -500,28 +536,24 @@ func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error
if err != nil {
return err
}
global.LOG.Infof("start container %s operation %s", req.Name, req.Operation)
switch req.Operation {
case constant.ContainerOpStart:
err = client.ContainerStart(ctx, req.Name, types.ContainerStartOptions{})
case constant.ContainerOpStop:
err = client.ContainerStop(ctx, req.Name, container.StopOptions{})
case constant.ContainerOpRestart:
err = client.ContainerRestart(ctx, req.Name, container.StopOptions{})
case constant.ContainerOpKill:
err = client.ContainerKill(ctx, req.Name, "SIGKILL")
case constant.ContainerOpPause:
err = client.ContainerPause(ctx, req.Name)
case constant.ContainerOpUnpause:
err = client.ContainerUnpause(ctx, req.Name)
case constant.ContainerOpRename:
newContainer, _ := client.ContainerInspect(ctx, req.NewName)
if newContainer.ContainerJSONBase != nil {
return buserr.New(constant.ErrContainerName)
for _, item := range req.Names {
global.LOG.Infof("start container %s operation %s", item, req.Operation)
switch req.Operation {
case constant.ContainerOpStart:
err = client.ContainerStart(ctx, item, types.ContainerStartOptions{})
case constant.ContainerOpStop:
err = client.ContainerStop(ctx, item, container.StopOptions{})
case constant.ContainerOpRestart:
err = client.ContainerRestart(ctx, item, container.StopOptions{})
case constant.ContainerOpKill:
err = client.ContainerKill(ctx, item, "SIGKILL")
case constant.ContainerOpPause:
err = client.ContainerPause(ctx, item)
case constant.ContainerOpUnpause:
err = client.ContainerUnpause(ctx, item)
case constant.ContainerOpRemove:
err = client.ContainerRemove(ctx, item, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
}
err = client.ContainerRename(ctx, req.Name, req.NewName)
case constant.ContainerOpRemove:
err = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
}
return err
}
@@ -560,11 +592,15 @@ func (u *ContainerService) ContainerLogClean(req dto.OperationWithName) error {
return nil
}
func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error {
func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType, container, since, tail string, follow bool) error {
defer func() { wsConn.Close() }()
if cmd.CheckIllegal(container, since, tail) {
return buserr.New(constant.ErrCmdIllegal)
}
command := fmt.Sprintf("docker logs %s", container)
if containerType == "compose" {
command = fmt.Sprintf("docker-compose -f %s logs", container)
}
if tail != "0" {
command += " --tail " + tail
}
@@ -576,6 +612,14 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, container, sinc
}
command += " 2>&1"
cmd := exec.Command("bash", "-c", command)
if !follow {
stdout, _ := cmd.CombinedOutput()
if err := wsConn.WriteMessage(websocket.TextMessage, stdout); err != nil {
global.LOG.Errorf("send message with log to ws failed, err: %v", err)
}
return nil
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
@@ -583,23 +627,40 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, container, sinc
if err := cmd.Start(); err != nil {
return err
}
defer func() {
_ = cmd.Process.Signal(syscall.SIGTERM)
_ = cmd.Wait()
}()
var exitCh chan struct{}
if follow {
go func() {
_, wsData, _ := wsConn.ReadMessage()
if string(wsData) == "close conn" {
exitCh <- struct{}{}
}
}()
}
buffer := make([]byte, 1024)
for {
n, err := stdout.Read(buffer)
if err != nil {
if err == io.EOF {
break
select {
case <-exitCh:
return nil
default:
n, err := stdout.Read(buffer)
if err != nil {
if err == io.EOF {
return err
}
global.LOG.Errorf("read bytes from log failed, err: %v", err)
continue
}
if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil {
global.LOG.Errorf("send message with log to ws failed, err: %v", err)
return err
}
global.LOG.Errorf("read bytes from container log failed, err: %v", err)
continue
}
if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil {
global.LOG.Errorf("send message with container log to ws failed, err: %v", err)
break
}
}
return nil
}
func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) {
@@ -987,28 +1048,29 @@ func simplifyPort(ports []types.Port) []string {
if start.PublicPort != 0 {
itemPortStr = fmt.Sprintf("%s:%v->%v/%s", start.IP, start.PublicPort, start.PrivatePort, start.Type)
}
datas = append(datas, itemPortStr)
datas = append(datas, strings.TrimPrefix(itemPortStr, ":"))
} else {
itemPortStr := fmt.Sprintf("%s:%v-%v/%s", start.IP, start.PrivatePort, ports[i-1].PrivatePort, start.Type)
if start.PublicPort != 0 {
itemPortStr = fmt.Sprintf("%s:%v-%v->%v-%v/%s", start.IP, start.PublicPort, ports[i-1].PublicPort, start.PrivatePort, ports[i-1].PrivatePort, start.Type)
}
datas = append(datas, itemPortStr)
datas = append(datas, strings.TrimPrefix(itemPortStr, ":"))
}
start = ports[i]
} else if i == len(ports)-1 {
}
if i == len(ports)-1 {
if ports[i].PrivatePort == start.PrivatePort {
itemPortStr := fmt.Sprintf("%s:%v/%s", start.IP, start.PrivatePort, start.Type)
if start.PublicPort != 0 {
itemPortStr = fmt.Sprintf("%s:%v->%v/%s", start.IP, start.PublicPort, start.PrivatePort, start.Type)
}
datas = append(datas, itemPortStr)
datas = append(datas, strings.TrimPrefix(itemPortStr, ":"))
} else {
itemPortStr := fmt.Sprintf("%s:%v-%v/%s", start.IP, start.PrivatePort, ports[i].PrivatePort, start.Type)
if start.PublicPort != 0 {
itemPortStr = fmt.Sprintf("%s:%v-%v->%v-%v/%s", start.IP, start.PublicPort, ports[i].PublicPort, start.PrivatePort, ports[i].PrivatePort, start.Type)
}
datas = append(datas, itemPortStr)
datas = append(datas, strings.TrimPrefix(itemPortStr, ":"))
}
}
}
-43
View File
@@ -4,7 +4,6 @@ import (
"bufio"
"errors"
"fmt"
"github.com/gorilla/websocket"
"io"
"os"
"os/exec"
@@ -262,45 +261,3 @@ func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
}
return nil
}
func (u *ContainerService) ComposeLogs(wsConn *websocket.Conn, composePath, since, tail string, follow bool) error {
if cmd.CheckIllegal(composePath, since, tail) {
return buserr.New(constant.ErrCmdIllegal)
}
command := fmt.Sprintf("docker-compose -f %s logs", composePath)
if tail != "0" {
command += " --tail " + tail
}
if since != "all" {
command += " --since " + since
}
if follow {
command += " -f"
}
command += " 2>&1"
cmd := exec.Command("bash", "-c", command)
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
return err
}
buffer := make([]byte, 1024)
for {
n, err := stdout.Read(buffer)
if err != nil {
if err == io.EOF {
break
}
global.LOG.Errorf("read bytes from compose log failed, err: %v", err)
continue
}
if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil {
global.LOG.Errorf("send message with compose log to ws failed, err: %v", err)
break
}
}
return nil
}
+5 -5
View File
@@ -19,7 +19,7 @@ func (u *ContainerService) PageVolume(req dto.SearchWithPage) (int64, interface{
if err != nil {
return 0, nil, err
}
list, err := client.VolumeList(context.TODO(), filters.NewArgs())
list, err := client.VolumeList(context.TODO(), volume.ListOptions{})
if err != nil {
return 0, nil, err
}
@@ -76,7 +76,7 @@ func (u *ContainerService) ListVolume() ([]dto.Options, error) {
if err != nil {
return nil, err
}
list, err := client.VolumeList(context.TODO(), filters.NewArgs())
list, err := client.VolumeList(context.TODO(), volume.ListOptions{})
if err != nil {
return nil, err
}
@@ -111,9 +111,9 @@ func (u *ContainerService) CreateVolume(req dto.VolumeCreate) error {
if err != nil {
return err
}
var array []filters.KeyValuePair
array = append(array, filters.Arg("name", req.Name))
vos, _ := client.VolumeList(context.TODO(), filters.NewArgs(array...))
arg := filters.NewArgs()
arg.Add("name", req.Name)
vos, _ := client.VolumeList(context.TODO(), volume.ListOptions{Filters: arg})
if len(vos.Volumes) != 0 {
for _, v := range vos.Volumes {
if v.Name == req.Name {
+2 -2
View File
@@ -46,7 +46,7 @@ func (u *CronjobService) SearchWithPage(search dto.SearchWithPage) (int64, inter
if err := copier.Copy(&item, &cronjob); err != nil {
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if item.Type == "app" || item.Type == "website" || item.Type == "database" || item.Type == "directory" || item.Type == "snapshot" {
if hasBackup(item.Type) {
backup, _ := backupRepo.Get(commonRepo.WithByID(uint(item.TargetDirID)))
if len(backup.Type) != 0 {
item.TargetDir = backup.Type
@@ -103,7 +103,7 @@ func (u *CronjobService) CleanRecord(req dto.CronjobClean) error {
if err != nil {
return err
}
if req.CleanData && (cronjob.Type == "app" || cronjob.Type == "database" || cronjob.Type == "website" || cronjob.Type == "directory" || cronjob.Type == "snapshot") {
if req.CleanData && hasBackup(cronjob.Type) {
cronjob.RetainCopies = 0
backup, err := backupRepo.Get(commonRepo.WithByID(uint(cronjob.TargetDirID)))
if err != nil {
+123
View File
@@ -64,6 +64,13 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
if err != nil {
global.LOG.Errorf("cut website log file failed, err: %v", err)
}
case "clean":
messageItem := ""
messageItem, err = u.handleSystemClean()
message = []byte(messageItem)
u.HandleRmExpired("LOCAL", "", "", cronjob, nil)
case "log":
record.File, err = u.handleSystemLog(*cronjob, record.StartTime)
}
if err != nil {
@@ -214,6 +221,7 @@ func handleTar(sourceDir, targetDir, name, exclusionRules string) error {
excludes := strings.Split(exclusionRules, ",")
excludeRules := ""
excludes = append(excludes, "*.sock")
for _, exclude := range excludes {
if len(exclude) == 0 {
continue
@@ -584,3 +592,118 @@ func (u *CronjobService) handleSnapshot(cronjob *model.Cronjob, startTime time.T
u.HandleRmExpired(backup.Type, backup.BackupPath, "", cronjob, client)
return message, path, nil
}
func (u *CronjobService) handleSystemClean() (string, error) {
return NewISettingService().SystemCleanForCronjob()
}
func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time) (string, error) {
backup, err := backupRepo.Get(commonRepo.WithByID(uint(cronjob.TargetDirID)))
if err != nil {
return "", err
}
pathItem := path.Join(global.CONF.System.BaseDir, "1panel/tmp/log", startTime.Format("20060102150405"))
websites, err := websiteRepo.List()
if err != nil {
return "", err
}
if len(websites) != 0 {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return "", err
}
webItem := path.Join(nginxInstall.GetPath(), "www/sites")
for _, website := range websites {
dirItem := path.Join(pathItem, "website", website.Alias)
if _, err := os.Stat(dirItem); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dirItem, os.ModePerm); err != nil {
return "", err
}
}
itemDir := path.Join(webItem, website.Alias, "log")
logFiles, _ := os.ReadDir(itemDir)
if len(logFiles) != 0 {
for i := 0; i < len(logFiles); i++ {
if !logFiles[i].IsDir() {
_ = cpBinary([]string{path.Join(itemDir, logFiles[i].Name())}, dirItem)
}
}
}
itemDir2 := path.Join(global.CONF.System.Backup, "log/website", website.Alias)
logFiles2, _ := os.ReadDir(itemDir2)
if len(logFiles2) != 0 {
for i := 0; i < len(logFiles2); i++ {
if !logFiles2[i].IsDir() {
_ = cpBinary([]string{path.Join(itemDir2, logFiles2[i].Name())}, dirItem)
}
}
}
}
global.LOG.Debug("backup website log successful!")
}
systemLogDir := path.Join(global.CONF.System.BaseDir, "1panel/log")
systemDir := path.Join(pathItem, "system")
if _, err := os.Stat(systemDir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(systemDir, os.ModePerm); err != nil {
return "", err
}
}
systemLogFiles, _ := os.ReadDir(systemLogDir)
if len(systemLogFiles) != 0 {
for i := 0; i < len(systemLogFiles); i++ {
if !systemLogFiles[i].IsDir() {
_ = cpBinary([]string{path.Join(systemLogDir, systemLogFiles[i].Name())}, systemDir)
}
}
}
global.LOG.Debug("backup system log successful!")
loginLogFiles, _ := os.ReadDir("/var/log")
loginDir := path.Join(pathItem, "login")
if _, err := os.Stat(loginDir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(loginDir, os.ModePerm); err != nil {
return "", err
}
}
if len(loginLogFiles) != 0 {
for i := 0; i < len(loginLogFiles); i++ {
if !loginLogFiles[i].IsDir() && (strings.HasPrefix(loginLogFiles[i].Name(), "secure") || strings.HasPrefix(loginLogFiles[i].Name(), "auth.log")) {
_ = cpBinary([]string{path.Join("/var/log", loginLogFiles[i].Name())}, loginDir)
}
}
}
global.LOG.Debug("backup ssh log successful!")
fileName := fmt.Sprintf("system_log_%s.tar.gz", startTime.Format("20060102150405"))
targetDir := path.Dir(pathItem)
if err := handleTar(pathItem, targetDir, fileName, ""); err != nil {
return "", err
}
defer func() {
os.RemoveAll(pathItem)
os.RemoveAll(path.Join(targetDir, fileName))
}()
client, err := NewIBackupService().NewClient(&backup)
if err != nil {
return "", err
}
targetPath := "log/" + fileName
if len(backup.BackupPath) != 0 {
targetPath = strings.TrimPrefix(backup.BackupPath, "/") + "/log/" + fileName
}
if _, err = client.Upload(path.Join(targetDir, fileName), targetPath); err != nil {
return "", err
}
u.HandleRmExpired(backup.Type, backup.BackupPath, "", &cronjob, client)
return targetPath, nil
}
func hasBackup(cronjobType string) bool {
return cronjobType == "app" || cronjobType == "database" || cronjobType == "website" || cronjobType == "directory" || cronjobType == "snapshot" || cronjobType == "log"
}
+70 -18
View File
@@ -2,10 +2,14 @@ package service
import (
"encoding/json"
"fmt"
"sort"
"strings"
"sync"
"time"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
@@ -20,11 +24,31 @@ type DashboardService struct{}
type IDashboardService interface {
LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error)
LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent
Restart(operation string) error
}
func NewIDashboardService() IDashboardService {
return &DashboardService{}
}
func (u *DashboardService) Restart(operation string) error {
if operation != "1panel" && operation != "system" {
return fmt.Errorf("handle restart operation %s failed, err: nonsupport such operation", operation)
}
itemCmd := fmt.Sprintf("%s 1pctl restart", cmd.SudoHandleCmd())
if operation == "system" {
itemCmd = fmt.Sprintf("%s reboot", cmd.SudoHandleCmd())
}
go func() {
stdout, err := cmd.Exec(itemCmd)
if err != nil {
global.LOG.Errorf("handle %s failed, err: %v", itemCmd, stdout)
}
}()
return nil
}
func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) {
var baseInfo dto.DashboardBase
hostInfo, err := host.Info()
@@ -151,7 +175,7 @@ type diskInfo struct {
func loadDiskInfo() []dto.DiskInfo {
var datas []dto.DiskInfo
stdout, err := cmd.Exec("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev")
stdout, err := cmd.ExecWithTimeOut("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev", 2*time.Second)
if err != nil {
return datas
}
@@ -185,24 +209,52 @@ func loadDiskInfo() []dto.DiskInfo {
mounts = append(mounts, diskInfo{Type: fields[1], Device: fields[0], Mount: fields[6]})
}
var (
wg sync.WaitGroup
mu sync.Mutex
)
wg.Add(len(mounts))
for i := 0; i < len(mounts); i++ {
state, err := disk.Usage(mounts[i].Mount)
if err != nil {
continue
}
var itemData dto.DiskInfo
itemData.Path = mounts[i].Mount
itemData.Type = mounts[i].Type
itemData.Device = mounts[i].Device
itemData.Total = state.Total
itemData.Free = state.Free
itemData.Used = state.Used
itemData.UsedPercent = state.UsedPercent
itemData.InodesTotal = state.InodesTotal
itemData.InodesUsed = state.InodesUsed
itemData.InodesFree = state.InodesFree
itemData.InodesUsedPercent = state.InodesUsedPercent
datas = append(datas, itemData)
go func(timeoutCh <-chan time.Time, mount diskInfo) {
defer wg.Done()
var itemData dto.DiskInfo
itemData.Path = mount.Mount
itemData.Type = mount.Type
itemData.Device = mount.Device
select {
case <-timeoutCh:
mu.Lock()
datas = append(datas, itemData)
mu.Unlock()
global.LOG.Errorf("load disk info from %s failed, err: timeout", mount.Mount)
default:
state, err := disk.Usage(mount.Mount)
if err != nil {
mu.Lock()
datas = append(datas, itemData)
mu.Unlock()
global.LOG.Errorf("load disk info from %s failed, err: %v", mount.Mount, err)
return
}
itemData.Total = state.Total
itemData.Free = state.Free
itemData.Used = state.Used
itemData.UsedPercent = state.UsedPercent
itemData.InodesTotal = state.InodesTotal
itemData.InodesUsed = state.InodesUsed
itemData.InodesFree = state.InodesFree
itemData.InodesUsedPercent = state.InodesUsedPercent
mu.Lock()
datas = append(datas, itemData)
mu.Unlock()
}
}(time.After(5*time.Second), mounts[i])
}
wg.Wait()
sort.Slice(datas, func(i, j int) bool {
return datas[i].Path < datas[j].Path
})
return datas
}
+2
View File
@@ -37,4 +37,6 @@ var (
snapshotRepo = repo.NewISnapshotRepo()
runtimeRepo = repo.NewIRunTimeRepo()
favoriteRepo = repo.NewIFavoriteRepo()
)
+83
View File
@@ -0,0 +1,83 @@
package service
import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/spf13/afero"
)
type FavoriteService struct {
}
type IFavoriteService interface {
Page(req dto.PageInfo) (int64, []response.FavoriteDTO, error)
Create(req request.FavoriteCreate) (*model.Favorite, error)
Delete(id uint) error
}
func NewIFavoriteService() IFavoriteService {
return &FavoriteService{}
}
func (f *FavoriteService) Page(req dto.PageInfo) (int64, []response.FavoriteDTO, error) {
total, favorites, err := favoriteRepo.Page(req.Page, req.PageSize)
if err != nil {
return 0, nil, err
}
var dtoFavorites []response.FavoriteDTO
for _, favorite := range favorites {
dtoFavorites = append(dtoFavorites, response.FavoriteDTO{
Favorite: favorite,
})
}
return total, dtoFavorites, nil
}
func (f *FavoriteService) Create(req request.FavoriteCreate) (*model.Favorite, error) {
exist, _ := favoriteRepo.GetFirst(favoriteRepo.WithByPath(req.Path))
if exist.ID > 0 {
return nil, buserr.New(constant.ErrFavoriteExist)
}
op := files.NewFileOp()
if !op.Stat(req.Path) {
return nil, buserr.New(constant.ErrLinkPathNotFound)
}
openFile, err := op.OpenFile(req.Path)
if err != nil {
return nil, err
}
fileInfo, err := openFile.Stat()
if err != nil {
return nil, err
}
favorite := &model.Favorite{
Name: fileInfo.Name(),
IsDir: fileInfo.IsDir(),
Path: req.Path,
}
if fileInfo.Size() <= 10*1024*1024 {
afs := &afero.Afero{Fs: op.Fs}
cByte, err := afs.ReadFile(req.Path)
if err == nil {
if len(cByte) > 0 && !files.DetectBinary(cByte) {
favorite.IsTxt = true
}
}
}
if err := favoriteRepo.Create(favorite); err != nil {
return nil, err
}
return favorite, nil
}
func (f *FavoriteService) Delete(id uint) error {
if err := favoriteRepo.Delete(commonRepo.WithByID(id)); err != nil {
return err
}
return nil
}
+38 -15
View File
@@ -29,10 +29,9 @@ type IFileService interface {
Create(op request.FileCreate) error
Delete(op request.FileDelete) error
BatchDelete(op request.FileBatchDelete) error
ChangeMode(op request.FileCreate) error
Compress(c request.FileCompress) error
DeCompress(c request.FileDeCompress) error
GetContent(op request.FileOption) (response.FileInfo, error)
GetContent(op request.FileContentReq) (response.FileInfo, error)
SaveContent(edit request.FileEdit) error
FileDownload(d request.FileDownload) (string, error)
DirSize(req request.DirSizeReq) (response.DirSizeRes, error)
@@ -40,6 +39,8 @@ type IFileService interface {
Wget(w request.FileWget) (string, error)
MvFile(m request.FileMove) error
ChangeOwner(req request.FileRoleUpdate) error
ChangeMode(op request.FileCreate) error
BatchChangeModeAndOwner(op request.FileRoleReq) error
}
func NewIFileService() IFileService {
@@ -133,11 +134,17 @@ func (f *FileService) Create(op request.FileCreate) error {
func (f *FileService) Delete(op request.FileDelete) error {
fo := files.NewFileOp()
if op.IsDir {
return fo.DeleteDir(op.Path)
} else {
return fo.DeleteFile(op.Path)
if op.ForceDelete {
if op.IsDir {
return fo.DeleteDir(op.Path)
} else {
return fo.DeleteFile(op.Path)
}
}
if err := NewIRecycleBinService().Create(request.RecycleBinCreate{SourcePath: op.Path}); err != nil {
return err
}
return favoriteRepo.Delete(favoriteRepo.WithByPath(op.Path))
}
func (f *FileService) BatchDelete(op request.FileBatchDelete) error {
@@ -160,11 +167,24 @@ func (f *FileService) BatchDelete(op request.FileBatchDelete) error {
func (f *FileService) ChangeMode(op request.FileCreate) error {
fo := files.NewFileOp()
if op.Sub {
return fo.ChmodR(op.Path, op.Mode)
} else {
return fo.Chmod(op.Path, fs.FileMode(op.Mode))
return fo.ChmodR(op.Path, op.Mode, op.Sub)
}
func (f *FileService) BatchChangeModeAndOwner(op request.FileRoleReq) error {
fo := files.NewFileOp()
for _, path := range op.Paths {
if !fo.Stat(path) {
return buserr.New(constant.ErrPathNotFound)
}
if err := fo.ChownR(path, op.User, op.Group, op.Sub); err != nil {
return err
}
if err := fo.ChmodR(path, op.Mode, op.Sub); err != nil {
return err
}
}
return nil
}
func (f *FileService) ChangeOwner(req request.FileRoleUpdate) error {
@@ -185,8 +205,11 @@ func (f *FileService) DeCompress(c request.FileDeCompress) error {
return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type))
}
func (f *FileService) GetContent(op request.FileOption) (response.FileInfo, error) {
info, err := files.NewFileInfo(op.FileOption)
func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo, error) {
info, err := files.NewFileInfo(files.FileOption{
Path: op.Path,
Expand: true,
})
if err != nil {
return response.FileInfo{}, err
}
@@ -223,17 +246,17 @@ func (f *FileService) MvFile(m request.FileMove) error {
return buserr.New(constant.ErrPathNotFound)
}
for _, path := range m.OldPaths {
if path == m.NewPath || strings.Contains(m.NewPath, path) {
if path == m.NewPath || strings.Contains(m.NewPath, filepath.Clean(path)+"/") {
return buserr.New(constant.ErrMovePathFailed)
}
}
if m.Type == "cut" {
return fo.Cut(m.OldPaths, m.NewPath)
return fo.Cut(m.OldPaths, m.NewPath, m.Name, m.Cover)
}
var errs []error
if m.Type == "copy" {
for _, src := range m.OldPaths {
if err := fo.Copy(src, m.NewPath); err != nil {
if err := fo.CopyAndReName(src, m.NewPath, m.Name, m.Cover); err != nil {
errs = append(errs, err)
global.LOG.Errorf("copy file [%s] to [%s] failed, err: %s", src, m.NewPath, err.Error())
}
+31 -16
View File
@@ -223,11 +223,11 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
req.Port = strings.ReplaceAll(req.Port, "-", ":")
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
return err
}
req.Port = strings.ReplaceAll(req.Port, ":", "-")
if err := u.addPortRecord(req); err != nil {
global.LOG.Errorf("add record %s/%s failed (strategy: %s, address: %s), err: %v", req.Port, req.Protocol, req.Strategy, req.Address, err)
return err
}
}
}
@@ -242,13 +242,13 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
}
req.Address = addr
if err := u.operatePort(client, req); err != nil {
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
return err
}
if len(req.Protocol) == 0 {
req.Protocol = "tcp/udp"
}
if err := u.addPortRecord(req); err != nil {
global.LOG.Errorf("add record %s/%s failed (strategy: %s, address: %s), err: %v", req.Port, req.Protocol, req.Strategy, req.Address, err)
return err
}
}
return nil
@@ -261,9 +261,11 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
req.Protocol = proto
req.Address = addr
if err := u.operatePort(client, req); err != nil {
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
return err
}
if err := u.addPortRecord(req); err != nil {
return err
}
_ = u.addPortRecord(req)
}
} else {
ports := strings.Split(itemPorts, ",")
@@ -276,9 +278,11 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
req.Port = port
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
return err
}
if err := u.addPortRecord(req); err != nil {
return err
}
_ = u.addPortRecord(req)
}
}
}
@@ -308,10 +312,12 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
}
fireInfo.Address = addressList[i]
if err := client.RichRules(fireInfo, req.Operation); err != nil {
global.LOG.Errorf("%s address %s failed (strategy: %s), err: %v", req.Operation, addressList[i], req.Strategy, err)
return err
}
req.Address = addressList[i]
_ = u.addAddressRecord(req)
if err := u.addAddressRecord(req); err != nil {
return err
}
}
if reload {
return client.Reload()
@@ -532,8 +538,10 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er
}
apps := u.loadPortByApp()
for _, app := range apps {
if err := client.Port(fireClient.FireInfo{Port: app.HttpPort, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err
if len(app.HttpPort) != 0 && app.HttpPort != "0" {
if err := client.Port(fireClient.FireInfo{Port: app.HttpPort, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err
}
}
}
@@ -545,26 +553,33 @@ func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
return hostRepo.DeleteFirewallRecord("port", req.Port, req.Protocol, req.Address, req.Strategy)
}
return hostRepo.SaveFirewallRecord(&model.Firewall{
if err := hostRepo.SaveFirewallRecord(&model.Firewall{
Type: "port",
Port: req.Port,
Protocol: req.Protocol,
Address: req.Address,
Strategy: req.Strategy,
Description: req.Description,
})
}); err != nil {
return fmt.Errorf("add record %s/%s failed (strategy: %s, address: %s), err: %v", req.Port, req.Protocol, req.Strategy, req.Address, err)
}
return nil
}
func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord("address", "", "", req.Address, req.Strategy)
}
return hostRepo.SaveFirewallRecord(&model.Firewall{
if err := hostRepo.SaveFirewallRecord(&model.Firewall{
Type: "address",
Address: req.Address,
Strategy: req.Strategy,
Description: req.Description,
})
}); err != nil {
return fmt.Errorf("add record failed (strategy: %s, address: %s), err: %v", req.Strategy, req.Address, err)
}
return nil
}
func listIpRules(strategy string) ([]string, error) {
+5
View File
@@ -62,6 +62,11 @@ func (u *GroupService) Delete(id uint) error {
if len(websites) > 0 {
return buserr.New(constant.ErrGroupIsUsed)
}
case "command":
commands, _ := commandRepo.GetList(commonRepo.WithByGroupID(id))
if len(commands) > 0 {
return buserr.New(constant.ErrGroupIsUsed)
}
case "host":
hosts, _ := hostRepo.GetList(commonRepo.WithByGroupID(id))
if len(hosts) > 0 {
+1 -1
View File
@@ -249,7 +249,7 @@ func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) {
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if req.GroupID == 0 {
group, err := groupRepo.Get(groupRepo.WithByIsDefault(true))
group, err := groupRepo.Get(groupRepo.WithByHostDefault())
if err != nil {
return nil, errors.New("get default group failed")
}
+3 -2
View File
@@ -19,6 +19,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/archive"
)
@@ -239,7 +240,7 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) {
}
options := types.ImagePullOptions{}
if repo.Auth {
authConfig := types.AuthConfig{
authConfig := registry.AuthConfig{
Username: repo.Username,
Password: repo.Password,
}
@@ -336,7 +337,7 @@ func (u *ImageService) ImagePush(req dto.ImagePush) (string, error) {
}
options := types.ImagePushOptions{}
if repo.Auth {
authConfig := types.AuthConfig{
authConfig := registry.AuthConfig{
Username: repo.Username,
Password: repo.Password,
}
+1 -1
View File
@@ -217,12 +217,12 @@ func (u *ImageRepoService) handleRegistries(newHost, delHost, handle string) err
case "create":
registries = common.RemoveRepeatElement(append(registries, newHost))
case "update":
registries = common.RemoveRepeatElement(append(registries, newHost))
for i, regi := range registries {
if regi == delHost {
registries = append(registries[:i], registries[i+1:]...)
}
}
registries = common.RemoveRepeatElement(append(registries, newHost))
case "delete":
for i, regi := range registries {
if regi == delHost {
+5 -2
View File
@@ -196,8 +196,11 @@ func opNginx(containerName, operate string) error {
if operate == constant.NginxCheck {
nginxCmd = fmt.Sprintf("docker exec -i %s %s", containerName, "nginx -t")
}
if out, err := cmd.ExecWithTimeOut(nginxCmd, 2*time.Second); err != nil {
return errors.New(out)
if out, err := cmd.ExecWithTimeOut(nginxCmd, 20*time.Second); err != nil {
if out != "" {
return errors.New(out)
}
return err
}
return nil
}
+208
View File
@@ -0,0 +1,208 @@
package service
import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/shirou/gopsutil/v3/disk"
"os"
"path"
"regexp"
"strconv"
"strings"
"time"
)
type RecycleBinService struct {
}
type IRecycleBinService interface {
Page(search dto.PageInfo) (int64, []response.RecycleBinDTO, error)
Create(create request.RecycleBinCreate) error
Reduce(reduce request.RecycleBinReduce) error
Clear() error
}
func NewIRecycleBinService() IRecycleBinService {
return &RecycleBinService{}
}
func (r RecycleBinService) Page(search dto.PageInfo) (int64, []response.RecycleBinDTO, error) {
var (
result []response.RecycleBinDTO
)
partitions, err := disk.Partitions(false)
if err != nil {
return 0, nil, err
}
op := files.NewFileOp()
for _, p := range partitions {
dir := path.Join(p.Mountpoint, ".1panel_clash")
if !op.Stat(dir) {
continue
}
clashFiles, err := os.ReadDir(dir)
if err != nil {
return 0, nil, err
}
for _, file := range clashFiles {
if strings.HasPrefix(file.Name(), "_1p_") {
recycleDTO, err := getRecycleBinDTOFromName(file.Name())
recycleDTO.IsDir = file.IsDir()
recycleDTO.From = dir
if err == nil {
result = append(result, *recycleDTO)
}
}
}
}
startIndex := (search.Page - 1) * search.PageSize
endIndex := startIndex + search.PageSize
if startIndex > len(result) {
return int64(len(result)), result, nil
}
if endIndex > len(result) {
endIndex = len(result)
}
return int64(len(result)), result[startIndex:endIndex], nil
}
func (r RecycleBinService) Create(create request.RecycleBinCreate) error {
op := files.NewFileOp()
if !op.Stat(create.SourcePath) {
return buserr.New(constant.ErrLinkPathNotFound)
}
clashDir, err := getClashDir(create.SourcePath)
if err != nil {
return err
}
paths := strings.Split(create.SourcePath, "/")
rNamePre := strings.Join(paths, "_1p_")
deleteTime := time.Now()
openFile, err := op.OpenFile(create.SourcePath)
if err != nil {
return err
}
fileInfo, err := openFile.Stat()
if err != nil {
return err
}
size := 0
if fileInfo.IsDir() {
sizeF, err := op.GetDirSize(create.SourcePath)
if err != nil {
return err
}
size = int(sizeF)
} else {
size = int(fileInfo.Size())
}
rName := fmt.Sprintf("_1p_%s%s_p_%d_%d", "file", rNamePre, size, deleteTime.Unix())
return op.Rename(create.SourcePath, path.Join(clashDir, rName))
}
func (r RecycleBinService) Reduce(reduce request.RecycleBinReduce) error {
filePath := path.Join(reduce.From, reduce.RName)
op := files.NewFileOp()
if !op.Stat(filePath) {
return buserr.New(constant.ErrLinkPathNotFound)
}
recycleBinDTO, err := getRecycleBinDTOFromName(reduce.RName)
if err != nil {
return err
}
if !op.Stat(path.Dir(recycleBinDTO.SourcePath)) {
return buserr.New("ErrSourcePathNotFound")
}
if op.Stat(recycleBinDTO.SourcePath) {
if err = op.RmRf(recycleBinDTO.SourcePath); err != nil {
return err
}
}
return op.Rename(filePath, recycleBinDTO.SourcePath)
}
func (r RecycleBinService) Clear() error {
partitions, err := disk.Partitions(false)
if err != nil {
return err
}
op := files.NewFileOp()
for _, p := range partitions {
dir := path.Join(p.Mountpoint, ".1panel_clash")
if !op.Stat(dir) {
continue
}
newDir := path.Join(p.Mountpoint, "1panel_clash")
if err := op.Rename(dir, newDir); err != nil {
return err
}
go func() {
_ = op.DeleteDir(newDir)
}()
}
return nil
}
func getClashDir(realPath string) (string, error) {
trimmedPath := strings.Trim(realPath, "/")
parts := strings.Split(trimmedPath, "/")
dir := ""
if len(parts) > 0 {
dir = parts[0]
partitions, err := disk.Partitions(false)
if err != nil {
return "", err
}
for _, p := range partitions {
if p.Mountpoint == dir {
if err = createClashDir(path.Join(p.Mountpoint, ".1panel_clash")); err != nil {
return "", err
}
return dir, nil
}
}
}
return constant.RecycleBinDir, createClashDir(constant.RecycleBinDir)
}
func createClashDir(clashDir string) error {
op := files.NewFileOp()
if !op.Stat(clashDir) {
if err := op.CreateDir(clashDir, 0755); err != nil {
return err
}
}
return nil
}
func getRecycleBinDTOFromName(filename string) (*response.RecycleBinDTO, error) {
r := regexp.MustCompile(`_1p_file_1p_(.+)_p_(\d+)_(\d+)`)
matches := r.FindStringSubmatch(filename)
if len(matches) != 4 {
return nil, fmt.Errorf("invalid filename format")
}
sourcePath := "/" + strings.ReplaceAll(matches[1], "_1p_", "/")
size, err := strconv.ParseInt(matches[2], 10, 64)
if err != nil {
return nil, err
}
deleteTime, err := strconv.ParseInt(matches[3], 10, 64)
if err != nil {
return nil, err
}
return &response.RecycleBinDTO{
Name: path.Base(sourcePath),
Size: int(size),
Type: "file",
DeleteTime: time.Unix(deleteTime, 0),
SourcePath: sourcePath,
RName: filename,
}, nil
}
+69 -3
View File
@@ -3,6 +3,7 @@ package service
import (
"context"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
@@ -20,6 +21,7 @@ import (
"github.com/subosito/gotenv"
"os"
"path"
"regexp"
"strconv"
"strings"
"time"
@@ -38,6 +40,7 @@ type IRuntimeService interface {
OperateRuntime(req request.RuntimeOperate) error
GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error)
OperateNodeModules(req request.NodeModuleOperateReq) error
SyncForRestart() error
}
func NewRuntimeService() IRuntimeService {
@@ -84,6 +87,11 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) {
if err = checkPortExist(create.Port); err != nil {
return err
}
for _, export := range create.ExposedPorts {
if err = checkPortExist(export.HostPort); err != nil {
return err
}
}
if containerName, ok := create.Params["CONTAINER_NAME"]; ok {
if err := checkContainerName(containerName.(string)); err != nil {
return err
@@ -286,7 +294,26 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
}
res.Params[k] = port
default:
res.Params[k] = v
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
if strings.Contains(k, "CONTAINER_PORT") {
r := regexp.MustCompile(`_(\d+)$`)
matches := r.FindStringSubmatch(k)
containerPort, err := strconv.Atoi(v)
if err != nil {
return nil, err
}
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
if err != nil {
return nil, err
}
res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
})
}
} else {
res.Params[k] = v
}
}
}
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
@@ -320,6 +347,11 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
}
runtime.Port = req.Port
}
for _, export := range req.ExposedPorts {
if err = checkPortExist(export.HostPort); err != nil {
return err
}
}
if containerName, ok := req.Params["CONTAINER_NAME"]; ok {
envs, err := gotenv.Unmarshal(runtime.Env)
if err != nil {
@@ -332,6 +364,24 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
}
}
}
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID))
if err != nil {
return err
}
app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId))
if err != nil {
return err
}
fileOp := files.NewFileOp()
appVersionDir := path.Join(constant.AppResourceDir, app.Resource, app.Key, appDetail.Version)
if !fileOp.Stat(appVersionDir) || appDetail.Update {
if err := downloadApp(app, appDetail, nil); err != nil {
return err
}
_ = fileOp.Rename(path.Join(runtime.GetPath(), "run.sh"), path.Join(runtime.GetPath(), "run.sh.bak"))
_ = fileOp.CopyFile(path.Join(appVersionDir, "run.sh"), runtime.GetPath())
}
}
projectDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
@@ -343,8 +393,9 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
CodeDir: req.CodeDir,
Version: req.Version,
NodeConfig: request.NodeConfig{
Port: req.Port,
Install: true,
Port: req.Port,
Install: true,
ExposedPorts: req.ExposedPorts,
},
}
composeContent, envContent, _, err := handleParams(create, projectDir)
@@ -515,3 +566,18 @@ func (r *RuntimeService) OperateNodeModules(req request.NodeModuleOperateReq) er
cmd += " " + req.Module
return cmd2.ExecContainerScript(containerName, cmd, 5*time.Minute)
}
func (r *RuntimeService) SyncForRestart() error {
runtimes, err := runtimeRepo.List()
if err != nil {
return err
}
for _, runtime := range runtimes {
if runtime.Status == constant.RuntimeBuildIng || runtime.Status == constant.RuntimeReCreating || runtime.Status == constant.RuntimeStarting || runtime.Status == constant.RuntimeCreating {
runtime.Status = constant.SystemRestart
runtime.Message = "System restart causing interrupt"
_ = runtimeRepo.Save(&runtime)
}
}
return nil
}
+59
View File
@@ -12,6 +12,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/pkg/errors"
"github.com/subosito/gotenv"
"gopkg.in/yaml.v3"
"io"
"net/http"
"os"
@@ -321,6 +322,11 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
create.Params["RUN_INSTALL"] = "0"
}
create.Params["CONTAINER_PACKAGE_URL"] = create.Source
composeContent, err = handleNodeCompose(env, composeContent, create, projectDir)
if err != nil {
return
}
}
newMap := make(map[string]string)
@@ -328,6 +334,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
for k, v := range newMap {
env[k] = v
}
envStr, err := gotenv.Marshal(env)
if err != nil {
return
@@ -339,6 +346,58 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
return
}
func handleNodeCompose(env gotenv.Env, composeContent []byte, create request.RuntimeCreate, projectDir string) (composeByte []byte, err error) {
existMap := make(map[string]interface{})
composeMap := make(map[string]interface{})
if err = yaml.Unmarshal(composeContent, &composeMap); err != nil {
return
}
services, serviceValid := composeMap["services"].(map[string]interface{})
if !serviceValid {
err = buserr.New(constant.ErrFileParse)
return
}
serviceName := ""
serviceValue := make(map[string]interface{})
for name, service := range services {
serviceName = name
serviceValue = service.(map[string]interface{})
_, ok := serviceValue["ports"].([]interface{})
if ok {
var ports []interface{}
ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${NODE_APP_PORT}")
for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
existMap[containerPortStr] = struct{}{}
existMap[hostPortStr] = struct{}{}
ports = append(ports, fmt.Sprintf("${HOST_IP}:${%s}:${%s}", hostPortStr, containerPortStr))
create.Params[containerPortStr] = port.ContainerPort
create.Params[hostPortStr] = port.HostPort
}
serviceValue["ports"] = ports
}
break
}
for k := range env {
if strings.Contains(k, "CONTAINER_PORT_") || strings.Contains(k, "HOST_PORT_") {
if _, ok := existMap[k]; !ok {
delete(env, k)
}
}
}
services[serviceName] = serviceValue
composeMap["services"] = services
composeByte, err = yaml.Marshal(composeMap)
if err != nil {
return
}
fileOp := files.NewFileOp()
_ = fileOp.SaveFile(path.Join(projectDir, "docker-compose.yml"), string(composeByte), 0644)
return
}
func checkContainerName(name string) error {
dockerCli, err := docker.NewClient()
if err != nil {
+39
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"encoding/pem"
"fmt"
"net"
"os"
"path"
"strconv"
@@ -30,10 +31,12 @@ type SettingService struct{}
type ISettingService interface {
GetSettingInfo() (*dto.SettingInfo, error)
LoadInterfaceAddr() ([]string, error)
LoadTimeZone() ([]string, error)
Update(key, value string) error
UpdatePassword(c *gin.Context, old, new string) error
UpdatePort(port uint) error
UpdateBindInfo(req dto.BindInfo) error
UpdateSSL(c *gin.Context, req dto.SSLUpdate) error
LoadFromCert() (*dto.SSLInfo, error)
HandlePasswordExpired(c *gin.Context, old, new string) error
@@ -41,6 +44,7 @@ type ISettingService interface {
SystemScan() dto.CleanData
SystemClean(req []dto.Clean)
SystemCleanForCronjob() (string, error)
}
func NewISettingService() ISettingService {
@@ -159,6 +163,41 @@ func (u *SettingService) SyncTime(req dto.SyncTime) error {
return nil
}
func (u *SettingService) LoadInterfaceAddr() ([]string, error) {
addrMap := make(map[string]struct{})
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
for _, addr := range addrs {
ipNet, ok := addr.(*net.IPNet)
if ok && ipNet.IP.To16() != nil {
addrMap[ipNet.IP.String()] = struct{}{}
}
}
var data []string
for key := range addrMap {
data = append(data, key)
}
return data, nil
}
func (u *SettingService) UpdateBindInfo(req dto.BindInfo) error {
if err := settingRepo.Update("Ipv6", req.Ipv6); err != nil {
return err
}
if err := settingRepo.Update("BindAddress", req.BindAddress); err != nil {
return err
}
go func() {
_, err := cmd.Exec("systemctl restart 1panel.service")
if err != nil {
global.LOG.Errorf("restart system with new bind info failed, err: %v", err)
}
}()
return nil
}
func (u *SettingService) UpdatePort(port uint) error {
if common.ScanPort(int(port)) {
return buserr.WithDetail(constant.ErrPortInUsed, port, nil)
+172 -63
View File
@@ -11,10 +11,28 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/google/uuid"
)
const (
upgradePath = "1panel/tmp/upgrade"
snapshotTmpPath = "1panel/tmp/system"
rollbackPath = "1panel/tmp"
cachePath = "1panel/cache"
oldOriginalPath = "original"
oldAppBackupPath = "1panel/resource/apps_bak"
oldDownloadPath = "1panel/tmp/download"
oldUpgradePath = "1panel/tmp"
tmpUploadPath = "1panel/tmp/upload"
uploadPath = "1panel/uploads"
downloadPath = "1panel/download"
logPath = "1panel/log"
dockerLogPath = "1panel/tmp/docker_logs"
taskPath = "1panel/task"
)
func (u *SettingService) SystemScan() dto.CleanData {
var (
SystemClean dto.CleanData
@@ -34,7 +52,7 @@ func (u *SettingService) SystemScan() dto.CleanData {
Children: loadTreeWithDir(true, "1panel_original", originalPath, fileOp),
})
upgradePath := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade")
upgradePath := path.Join(global.CONF.System.BaseDir, upgradePath)
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
treeData = append(treeData, dto.CleanTree{
ID: uuid.NewString(),
@@ -76,7 +94,7 @@ func (u *SettingService) SystemScan() dto.CleanData {
Children: rollBackTree,
})
cachePath := path.Join(global.CONF.System.BaseDir, "1panel/cache")
cachePath := path.Join(global.CONF.System.BaseDir, cachePath)
cacheSize, _ := fileOp.GetDirSize(cachePath)
treeData = append(treeData, dto.CleanTree{
ID: uuid.NewString(),
@@ -125,94 +143,94 @@ func (u *SettingService) SystemClean(req []dto.Clean) {
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel_original", item.Name))
case "upgrade":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, upgradePath, item.Name))
case "snapshot":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/system", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, snapshotTmpPath, item.Name))
dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name))
case "snapshot_tmp":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/system", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, snapshotTmpPath, item.Name))
case "snapshot_local":
dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name))
case "rollback":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/app"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/database"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/website"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "app"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "database"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "website"))
case "rollback_app":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/app", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "app", item.Name))
case "rollback_database":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/database", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "database", item.Name))
case "rollback_website":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/website", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, rollbackPath, "website", item.Name))
case "cache":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/cache", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, cachePath, item.Name))
restart = true
case "unused":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "original"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/download"))
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldOriginalPath))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldAppBackupPath))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldDownloadPath))
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath))
if len(files) == 0 {
continue
}
for _, file := range files {
if strings.HasPrefix(file.Name(), "upgrade_") {
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", file.Name()))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath, file.Name()))
}
}
case "old_original":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "original", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldOriginalPath, item.Name))
case "old_apps_bak":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldAppBackupPath, item.Name))
case "old_download":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/download", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldDownloadPath, item.Name))
case "old_upgrade":
if len(item.Name) == 0 {
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp"))
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath))
if len(files) == 0 {
continue
}
for _, file := range files {
if strings.HasPrefix(file.Name(), "upgrade_") {
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", file.Name()))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath, file.Name()))
}
}
} else {
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, oldUpgradePath, item.Name))
}
case "upload":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, item.Name))
if len(item.Name) == 0 {
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upload"))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, tmpUploadPath))
}
case "upload_tmp":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upload", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, tmpUploadPath, item.Name))
case "upload_app":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/app", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "app", item.Name))
case "upload_database":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/database", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "database", item.Name))
case "upload_website":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/website", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "website", item.Name))
case "upload_directory":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/directory", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, uploadPath, "directory", item.Name))
case "download":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, item.Name))
case "download_app":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/app", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "app", item.Name))
case "download_database":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/database", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "database", item.Name))
case "download_website":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/website", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "website", item.Name))
case "download_directory":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/directory", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, downloadPath, "directory", item.Name))
case "system_log":
if len(item.Name) == 0 {
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/log"))
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, logPath))
if len(files) == 0 {
continue
}
@@ -220,16 +238,16 @@ func (u *SettingService) SystemClean(req []dto.Clean) {
if file.Name() == "1Panel.log" {
continue
}
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/log", file.Name()))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, logPath, file.Name()))
}
} else {
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/log", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, logPath, item.Name))
}
case "docker_log":
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/docker_logs", item.Name))
dropFileOrDir(path.Join(global.CONF.System.BaseDir, dockerLogPath, item.Name))
case "task_log":
pathItem := path.Join(global.CONF.System.BaseDir, "1panel/task", item.Name)
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/task", item.Name))
pathItem := path.Join(global.CONF.System.BaseDir, taskPath, item.Name)
dropFileOrDir(path.Join(global.CONF.System.BaseDir, taskPath, item.Name))
if len(item.Name) == 0 {
files, _ := os.ReadDir(pathItem)
if len(files) == 0 {
@@ -258,9 +276,70 @@ func (u *SettingService) SystemClean(req []dto.Clean) {
}
}
func (u *SettingService) SystemCleanForCronjob() (string, error) {
logs := ""
size := int64(0)
fileCount := 0
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, "1panel_original"), &logs, &size, &fileCount)
upgradePath := path.Join(global.CONF.System.BaseDir, upgradePath)
upgradeFiles, _ := os.ReadDir(upgradePath)
if len(upgradeFiles) != 0 {
sort.Slice(upgradeFiles, func(i, j int) bool {
return upgradeFiles[i].Name() > upgradeFiles[j].Name()
})
for i := 0; i < len(upgradeFiles); i++ {
if i != 0 {
dropFileOrDirWithLog(path.Join(upgradePath, upgradeFiles[i].Name()), &logs, &size, &fileCount)
}
}
}
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, snapshotTmpPath), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.Backup, "system"), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, rollbackPath, "app"), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, rollbackPath, "website"), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, rollbackPath, "database"), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, oldOriginalPath), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, oldAppBackupPath), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, oldDownloadPath), &logs, &size, &fileCount)
oldUpgradePath := path.Join(global.CONF.System.BaseDir, oldUpgradePath)
oldUpgradeFiles, _ := os.ReadDir(oldUpgradePath)
if len(oldUpgradeFiles) != 0 {
for i := 0; i < len(oldUpgradeFiles); i++ {
dropFileOrDirWithLog(path.Join(oldUpgradePath, oldUpgradeFiles[i].Name()), &logs, &size, &fileCount)
}
}
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, tmpUploadPath), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, uploadPath), &logs, &size, &fileCount)
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, downloadPath), &logs, &size, &fileCount)
logPath := path.Join(global.CONF.System.BaseDir, logPath)
logFiles, _ := os.ReadDir(logPath)
if len(logFiles) != 0 {
for i := 0; i < len(logFiles); i++ {
if logFiles[i].Name() != "1Panel.log" {
dropFileOrDirWithLog(path.Join(logPath, logFiles[i].Name()), &logs, &size, &fileCount)
}
}
}
timeNow := time.Now().Format("2006-01-02 15:04:05")
dropFileOrDirWithLog(path.Join(global.CONF.System.BaseDir, dockerLogPath), &logs, &size, &fileCount)
logs += fmt.Sprintf("\n%s: total clean: %s, total count: %d", timeNow, common.LoadSizeUnit2F(float64(size)), fileCount)
_ = settingRepo.Update("LastCleanTime", timeNow)
_ = settingRepo.Update("LastCleanSize", fmt.Sprintf("%v", size))
_ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", fileCount))
return logs, nil
}
func loadSnapshotTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
path1 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/system")
path1 := path.Join(global.CONF.System.BaseDir, snapshotTmpPath)
list1 := loadTreeWithAllFile(true, path1, "snapshot_tmp", path1, fileOp)
if len(list1) != 0 {
size, _ := fileOp.GetDirSize(path1)
@@ -278,17 +357,17 @@ func loadSnapshotTree(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
path1 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/app")
path1 := path.Join(global.CONF.System.BaseDir, rollbackPath, "app")
list1 := loadTreeWithAllFile(true, path1, "rollback_app", path1, fileOp)
size1, _ := fileOp.GetDirSize(path1)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_app", Size: uint64(size1), Children: list1, Type: "rollback_app", IsRecommend: true})
path2 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/website")
path2 := path.Join(global.CONF.System.BaseDir, rollbackPath, "website")
list2 := loadTreeWithAllFile(true, path2, "rollback_website", path2, fileOp)
size2, _ := fileOp.GetDirSize(path2)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_website", Size: uint64(size2), Children: list2, Type: "rollback_website", IsRecommend: true})
path3 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/database")
path3 := path.Join(global.CONF.System.BaseDir, rollbackPath, "database")
list3 := loadTreeWithAllFile(true, path3, "rollback_database", path3, fileOp)
size3, _ := fileOp.GetDirSize(path3)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_database", Size: uint64(size3), Children: list3, Type: "rollback_database", IsRecommend: true})
@@ -298,28 +377,28 @@ func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadUnusedFile(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
path1 := path.Join(global.CONF.System.BaseDir, "original")
path1 := path.Join(global.CONF.System.BaseDir, oldOriginalPath)
list1 := loadTreeWithAllFile(true, path1, "old_original", path1, fileOp)
if len(list1) != 0 {
size, _ := fileOp.GetDirSize(path1)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_original", Size: uint64(size), Children: list1, Type: "old_original"})
}
path2 := path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak")
path2 := path.Join(global.CONF.System.BaseDir, oldAppBackupPath)
list2 := loadTreeWithAllFile(true, path2, "old_apps_bak", path2, fileOp)
if len(list2) != 0 {
size, _ := fileOp.GetDirSize(path2)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_apps_bak", Size: uint64(size), Children: list2, Type: "old_apps_bak"})
}
path3 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/download")
path3 := path.Join(global.CONF.System.BaseDir, oldDownloadPath)
list3 := loadTreeWithAllFile(true, path3, "old_download", path3, fileOp)
if len(list3) != 0 {
size, _ := fileOp.GetDirSize(path3)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_download", Size: uint64(size), Children: list3, Type: "old_download"})
}
path4 := path.Join(global.CONF.System.BaseDir, "1panel/tmp")
path4 := path.Join(global.CONF.System.BaseDir, oldUpgradePath)
list4 := loadTreeWithDir(true, "old_upgrade", path4, fileOp)
itemSize := uint64(0)
for _, item := range list4 {
@@ -334,32 +413,32 @@ func loadUnusedFile(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadUploadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
path0 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upload")
path0 := path.Join(global.CONF.System.BaseDir, tmpUploadPath)
list0 := loadTreeWithAllFile(true, path0, "upload_tmp", path0, fileOp)
size0, _ := fileOp.GetDirSize(path0)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_tmp", Size: uint64(size0), Children: list0, Type: "upload_tmp", IsRecommend: true})
path1 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/app")
path1 := path.Join(global.CONF.System.BaseDir, uploadPath, "app")
list1 := loadTreeWithAllFile(true, path1, "upload_app", path1, fileOp)
size1, _ := fileOp.GetDirSize(path1)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_app", Size: uint64(size1), Children: list1, Type: "upload_app", IsRecommend: true})
path2 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/website")
path2 := path.Join(global.CONF.System.BaseDir, uploadPath, "website")
list2 := loadTreeWithAllFile(true, path2, "upload_website", path2, fileOp)
size2, _ := fileOp.GetDirSize(path2)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_website", Size: uint64(size2), Children: list2, Type: "upload_website", IsRecommend: true})
path3 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/database")
path3 := path.Join(global.CONF.System.BaseDir, uploadPath, "database")
list3 := loadTreeWithAllFile(true, path3, "upload_database", path3, fileOp)
size3, _ := fileOp.GetDirSize(path3)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_database", Size: uint64(size3), Children: list3, Type: "upload_database", IsRecommend: true})
path4 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/directory")
path4 := path.Join(global.CONF.System.BaseDir, uploadPath, "directory")
list4 := loadTreeWithAllFile(true, path4, "upload_directory", path4, fileOp)
size4, _ := fileOp.GetDirSize(path4)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_directory", Size: uint64(size4), Children: list4, Type: "upload_directory", IsRecommend: true})
path5 := path.Join(global.CONF.System.BaseDir, "1panel/uploads")
path5 := path.Join(global.CONF.System.BaseDir, uploadPath)
uploadTreeData := loadTreeWithAllFile(true, path5, "upload", path5, fileOp)
treeData = append(treeData, uploadTreeData...)
@@ -368,27 +447,27 @@ func loadUploadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadDownloadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
path1 := path.Join(global.CONF.System.BaseDir, "1panel/download/app")
path1 := path.Join(global.CONF.System.BaseDir, downloadPath, "app")
list1 := loadTreeWithAllFile(true, path1, "download_app", path1, fileOp)
size1, _ := fileOp.GetDirSize(path1)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_app", Size: uint64(size1), Children: list1, Type: "download_app", IsRecommend: true})
path2 := path.Join(global.CONF.System.BaseDir, "1panel/download/website")
path2 := path.Join(global.CONF.System.BaseDir, downloadPath, "website")
list2 := loadTreeWithAllFile(true, path2, "download_website", path2, fileOp)
size2, _ := fileOp.GetDirSize(path2)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_website", Size: uint64(size2), Children: list2, Type: "download_website", IsRecommend: true})
path3 := path.Join(global.CONF.System.BaseDir, "1panel/download/database")
path3 := path.Join(global.CONF.System.BaseDir, downloadPath, "database")
list3 := loadTreeWithAllFile(true, path3, "download_database", path3, fileOp)
size3, _ := fileOp.GetDirSize(path3)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_database", Size: uint64(size3), Children: list3, Type: "download_database", IsRecommend: true})
path4 := path.Join(global.CONF.System.BaseDir, "1panel/download/directory")
path4 := path.Join(global.CONF.System.BaseDir, downloadPath, "directory")
list4 := loadTreeWithAllFile(true, path4, "download_directory", path4, fileOp)
size4, _ := fileOp.GetDirSize(path4)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_directory", Size: uint64(size4), Children: list4, Type: "download_directory", IsRecommend: true})
path5 := path.Join(global.CONF.System.BaseDir, "1panel/download")
path5 := path.Join(global.CONF.System.BaseDir, downloadPath)
uploadTreeData := loadTreeWithAllFile(true, path5, "download", path5, fileOp)
treeData = append(treeData, uploadTreeData...)
@@ -397,7 +476,7 @@ func loadDownloadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadLogTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
path1 := path.Join(global.CONF.System.BaseDir, "1panel/log")
path1 := path.Join(global.CONF.System.BaseDir, logPath)
list1 := loadTreeWithAllFile(true, path1, "system_log", path1, fileOp)
size := uint64(0)
for _, file := range list1 {
@@ -405,12 +484,12 @@ func loadLogTree(fileOp fileUtils.FileOp) []dto.CleanTree {
}
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "system_log", Size: uint64(size), Children: list1, Type: "system_log", IsRecommend: true})
path2 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/docker_logs")
path2 := path.Join(global.CONF.System.BaseDir, dockerLogPath)
list2 := loadTreeWithAllFile(true, path2, "docker_log", path2, fileOp)
size2, _ := fileOp.GetDirSize(path2)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "docker_log", Size: uint64(size2), Children: list2, Type: "docker_log", IsRecommend: true})
path3 := path.Join(global.CONF.System.BaseDir, "1panel/task")
path3 := path.Join(global.CONF.System.BaseDir, taskPath)
list3 := loadTreeWithAllFile(false, path3, "task_log", path3, fileOp)
size3, _ := fileOp.GetDirSize(path3)
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "task_log", Size: uint64(size3), Children: list3, Type: "task_log"})
@@ -506,3 +585,33 @@ func dropFileOrDir(itemPath string) {
global.LOG.Errorf("drop file %s failed, err %v", itemPath, err)
}
}
func dropFileOrDirWithLog(itemPath string, log *string, size *int64, count *int) {
itemSize := int64(0)
itemCount := 0
scanFile(itemPath, &itemSize, &itemCount)
*size += itemSize
*count += itemCount
if err := os.RemoveAll(itemPath); err != nil {
global.LOG.Errorf("drop file %s failed, err %v", itemPath, err)
*log += fmt.Sprintf("- drop file %s failed, err: %v \n\n", itemPath, err)
return
}
*log += fmt.Sprintf("+ drop file %s successful!, size: %s, count: %d \n\n", itemPath, common.LoadSizeUnit2F(float64(itemSize)), itemCount)
}
func scanFile(pathItem string, size *int64, count *int) {
files, _ := os.ReadDir(pathItem)
for _, f := range files {
if f.IsDir() {
scanFile(path.Join(pathItem, f.Name()), size, count)
} else {
fileInfo, err := f.Info()
if err != nil {
continue
}
*count++
*size += fileInfo.Size()
}
}
}
+1
View File
@@ -215,6 +215,7 @@ func handleSnapTar(sourceDir, targetDir, name, exclusionRules string) error {
exStr := ""
excludes := strings.Split(exclusionRules, ";")
excludes = append(excludes, "*.sock")
for _, exclude := range excludes {
if len(exclude) == 0 {
continue
+54 -21
View File
@@ -30,7 +30,7 @@ type ISSHService interface {
GetSSHInfo() (*dto.SSHInfo, error)
OperateSSH(operation string) error
UpdateByFile(value string) error
Update(key, value string) error
Update(req dto.SSHUpdate) error
GenerateSSH(req dto.GenerateSSH) error
AnalysisLog(req dto.SearchForAnalysis) (*dto.AnalysisRes, error)
LoadSSHSecret(mode string) (string, error)
@@ -45,6 +45,7 @@ func NewISSHService() ISSHService {
func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) {
data := dto.SSHInfo{
AutoStart: true,
Status: constant.StatusEnable,
Message: "",
Port: "22",
@@ -68,6 +69,17 @@ func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) {
}
}
out, err := systemctl.RunSystemCtl("is-enabled", serviceName)
if err != nil {
data.AutoStart = false
} else {
if out == "alias\n" {
data.AutoStart, _ = systemctl.IsEnable("ssh")
} else {
data.AutoStart = out == "enabled\n"
}
}
sshConf, err := os.ReadFile(sshPath)
if err != nil {
data.Message = err.Error()
@@ -98,22 +110,28 @@ func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) {
}
func (u *SSHService) OperateSSH(operation string) error {
if operation == "start" || operation == "stop" || operation == "restart" {
serviceName, err := loadServiceName()
if err != nil {
return err
}
sudo := cmd.SudoHandleCmd()
stdout, err := cmd.Execf("%s systemctl %s %s", sudo, operation, serviceName)
if err != nil {
return fmt.Errorf("%s %s failed, stdout: %s, err: %v", operation, serviceName, stdout, err)
}
return nil
serviceName, err := loadServiceName()
if err != nil {
return err
}
return fmt.Errorf("not support such operation: %s", operation)
sudo := cmd.SudoHandleCmd()
if operation == "enable" || operation == "disable" {
serviceName += ".service"
}
stdout, err := cmd.Execf("%s systemctl %s %s", sudo, operation, serviceName)
if err != nil {
if strings.Contains(stdout, "alias name or linked unit file") {
stdout, err := cmd.Execf("%s systemctl %s ssh", sudo, operation)
if err != nil {
return fmt.Errorf("%s ssh(alias name or linked unit file) failed, stdout: %s, err: %v", operation, stdout, err)
}
}
return fmt.Errorf("%s %s failed, stdout: %s, err: %v", operation, serviceName, stdout, err)
}
return nil
}
func (u *SSHService) Update(key, value string) error {
func (u *SSHService) Update(req dto.SSHUpdate) error {
serviceName, err := loadServiceName()
if err != nil {
return err
@@ -124,10 +142,7 @@ func (u *SSHService) Update(key, value string) error {
return err
}
lines := strings.Split(string(sshConf), "\n")
newFiles := updateSSHConf(lines, key, value)
if err := settingRepo.Update(key, value); err != nil {
return err
}
newFiles := updateSSHConf(lines, req.Key, req.NewValue)
file, err := os.OpenFile(sshPath, os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
return err
@@ -137,10 +152,28 @@ func (u *SSHService) Update(key, value string) error {
return err
}
sudo := cmd.SudoHandleCmd()
if key == "Port" {
if req.Key == "Port" {
stdout, _ := cmd.Execf("%s getenforce", sudo)
if stdout == "Enforcing\n" {
_, _ = cmd.Execf("%s semanage port -a -t ssh_port_t -p tcp %s", sudo, value)
_, _ = cmd.Execf("%s semanage port -a -t ssh_port_t -p tcp %s", sudo, req.NewValue)
}
ruleItem := dto.PortRuleUpdate{
OldRule: dto.PortRuleOperate{
Operation: "remove",
Port: req.OldValue,
Protocol: "tcp",
Strategy: "accept",
},
NewRule: dto.PortRuleOperate{
Operation: "add",
Port: req.NewValue,
Protocol: "tcp",
Strategy: "accept",
},
}
if err := NewIFirewallService().UpdatePortRule(ruleItem); err != nil {
global.LOG.Errorf("reset firewall rules %s -> %s failed, err: %v", req.OldValue, req.OldValue, err)
}
}
@@ -625,7 +658,7 @@ func loadFailedSecureDatas(line string) dto.SSHHistory {
return data
}
index := 0
if strings.Contains("line", " invalid user") {
if strings.Contains(line, " invalid user") {
index = 2
}
data = dto.SSHHistory{
+42 -99
View File
@@ -19,7 +19,6 @@ import (
"time"
"github.com/1Panel-dev/1Panel/backend/i18n"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/spf13/afero"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
@@ -59,7 +58,7 @@ type IWebsiteService interface {
UpdateWebsite(req request.WebsiteUpdate) error
DeleteWebsite(req request.WebsiteDelete) error
GetWebsite(id uint) (response.WebsiteDTO, error)
CreateWebsiteDomain(create request.WebsiteDomainCreate) (model.WebsiteDomain, error)
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
DeleteWebsiteDomain(domainId uint) error
@@ -171,67 +170,35 @@ func (w WebsiteService) GetWebsites() ([]response.WebsiteDTO, error) {
}
func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) {
if exist, _ := websiteRepo.GetBy(websiteRepo.WithDomain(create.PrimaryDomain)); len(exist) > 0 {
primaryDomainArray := strings.Split(create.PrimaryDomain, ":")
primaryDomain := primaryDomainArray[0]
if exist, _ := websiteRepo.GetBy(websiteRepo.WithDomain(primaryDomain)); len(exist) > 0 {
return buserr.New(constant.ErrDomainIsExist)
}
if exist, _ := websiteRepo.GetBy(websiteRepo.WithAlias(create.Alias)); len(exist) > 0 {
return buserr.New(constant.ErrAliasIsExist)
}
if exist, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomain(create.PrimaryDomain)); len(exist) > 0 {
return buserr.New(constant.ErrDomainIsExist)
}
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
defaultHttpPort := nginxInstall.HttpPort
primaryDomainArray := strings.Split(create.PrimaryDomain, ":")
primaryDomain := primaryDomainArray[0]
var (
domains []model.WebsiteDomain
ports = make(map[int]struct{})
otherDomains []model.WebsiteDomain
domains []model.WebsiteDomain
)
domainArray := strings.Split(create.OtherDomains, "\n")
domainArray = append(domainArray, create.PrimaryDomain)
for _, domain := range domainArray {
if domain == "" {
continue
}
domainModel, err := getDomain(domain, defaultHttpPort)
if err != nil {
return err
}
if reflect.DeepEqual(domainModel, model.WebsiteDomain{}) {
continue
}
domains = append(domains, domainModel)
if domainModel.Port != defaultHttpPort {
ports[domainModel.Port] = struct{}{}
}
domains, _, _, err = getWebsiteDomains(create.PrimaryDomain, defaultHttpPort, 0)
if err != nil {
return err
}
for port := range ports {
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
errMap := make(map[string]interface{})
errMap["port"] = port
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
if appInstall.ID > 0 {
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
errMap["name"] = appInstall.Name
return buserr.WithMap("ErrPortExist", errMap, nil)
}
runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port))
if runtime != nil {
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
errMap["name"] = runtime.Name
return buserr.WithMap("ErrPortExist", errMap, nil)
}
if common.ScanPort(create.Port) {
return buserr.WithDetail(constant.ErrPortInUsed, create.Port, nil)
}
}
otherDomains, _, _, err = getWebsiteDomains(create.OtherDomains, defaultHttpPort, 0)
if err != nil {
return err
}
domains = append(domains, otherDomains...)
defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
website := &model.Website{
@@ -481,58 +448,34 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
return nil
}
func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) (model.WebsiteDomain, error) {
func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) {
var (
domainModel model.WebsiteDomain
ports []int
domains []string
domainModels []model.WebsiteDomain
addPorts []int
addDomains []string
)
httpPort, _, err := getAppInstallPort(constant.AppOpenresty)
if err != nil {
return domainModel, err
return nil, err
}
if create.Port != httpPort {
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(create.Port)); len(existPorts) == 0 {
if existAppInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(create.Port)); existAppInstall.ID > 0 {
return domainModel, buserr.WithMap(constant.ErrPortInOtherApp, map[string]interface{}{"port": create.Port, "apps": existAppInstall.App.Name}, nil)
}
if common.ScanPort(create.Port) {
return domainModel, buserr.WithDetail(constant.ErrPortInUsed, create.Port, nil)
}
}
}
if existDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomain(create.Domain), websiteDomainRepo.WithPort(create.Port)); len(existDomains) > 0 {
return domainModel, buserr.WithDetail(constant.ErrDomainIsExist, create.Domain, nil)
}
website, err := websiteRepo.GetFirst(commonRepo.WithByID(create.WebsiteID))
if err != nil {
return domainModel, err
}
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(create.WebsiteID), websiteDomainRepo.WithPort(create.Port)); len(oldDomains) == 0 {
ports = append(ports, create.Port)
return nil, err
}
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(create.WebsiteID), websiteDomainRepo.WithDomain(create.Domain)); len(oldDomains) == 0 {
domains = append(domains, create.Domain)
domainModels, addPorts, addDomains, err = getWebsiteDomains(create.Domains, httpPort, create.WebsiteID)
if err != nil {
return nil, err
}
go func() {
_ = OperateFirewallPort(nil, addPorts)
}()
if err := addListenAndServerName(website, addPorts, addDomains); err != nil {
return nil, err
}
if err := addListenAndServerName(website, ports, domains); err != nil {
return domainModel, err
}
domainModel = model.WebsiteDomain{
Domain: create.Domain,
Port: create.Port,
WebsiteID: create.WebsiteID,
}
if create.Port != httpPort {
go func() {
_ = OperateFirewallPort(nil, []int{create.Port})
}()
}
return domainModel, websiteDomainRepo.Create(context.TODO(), &domainModel)
return domainModels, websiteDomainRepo.BatchCreate(context.TODO(), domainModels)
}
func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error) {
@@ -1306,6 +1249,7 @@ func (w WebsiteService) ChangePHPVersion(req request.WebsitePHPVersionReq) error
fpmConfDir = path.Join(confDir, "php-fpm.conf")
phpDir = path.Join(constant.RuntimeDir, runtime.Type, runtime.Name, "php")
oldFmContent, _ = fileOp.GetContent(fpmConfDir)
newComposeByte []byte
)
envParams := make(map[string]string, len(envs))
handleMap(envs, envParams)
@@ -1325,7 +1269,13 @@ func (w WebsiteService) ChangePHPVersion(req request.WebsitePHPVersionReq) error
if busErr = env.Write(envParams, envPath); busErr != nil {
return busErr
}
if busErr = fileOp.WriteFile(composePath, strings.NewReader(appDetail.DockerCompose), 0775); busErr != nil {
newComposeByte, busErr = changeServiceName(composePath, appInstall.ServiceName)
if busErr != nil {
return err
}
if busErr = fileOp.WriteFile(composePath, bytes.NewReader(newComposeByte), 0775); busErr != nil {
return busErr
}
if !req.RetainConfig {
@@ -1355,7 +1305,7 @@ func (w WebsiteService) ChangePHPVersion(req request.WebsitePHPVersionReq) error
appInstall.AppDetailId = runtime.AppDetailID
appInstall.AppId = appDetail.AppId
appInstall.Version = appDetail.Version
appInstall.DockerCompose = appDetail.DockerCompose
appInstall.DockerCompose = string(newComposeByte)
_ = appInstallRepo.Save(context.Background(), &appInstall)
website.RuntimeID = req.RuntimeID
@@ -2143,15 +2093,8 @@ func (w WebsiteService) OperateRedirect(req request.NginxRedirectReq) (err error
})
}
case "404":
if req.KeepPath && !req.RedirectRoot {
target = req.Target + "$request_uri"
}
if req.RedirectRoot {
target = "/"
} else {
if req.KeepPath {
target = req.Target + "$request_uri"
}
}
block = &components.Block{
Directives: []components.IDirective{
@@ -2166,7 +2109,7 @@ func (w WebsiteService) OperateRedirect(req request.NginxRedirectReq) (err error
Directives: []components.IDirective{
&components.Directive{
Name: "return",
Parameters: []string{"301", target},
Parameters: []string{req.Redirect, target},
},
},
},
+59
View File
@@ -11,6 +11,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/1Panel-dev/1Panel/backend/utils/ssl"
"path"
"strconv"
@@ -30,6 +31,7 @@ type IWebsiteSSLService interface {
GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error)
Delete(id uint) error
Update(update request.WebsiteSSLUpdate) error
Upload(req request.WebsiteSSLUpload) error
}
func NewIWebsiteSSLService() IWebsiteSSLService {
@@ -289,3 +291,60 @@ func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error {
websiteSSL.AutoRenew = update.AutoRenew
return websiteSSLRepo.Save(websiteSSL)
}
func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
newSSL := &model.WebsiteSSL{
Provider: constant.Manual,
}
if req.Type == "local" {
fileOp := files.NewFileOp()
if !fileOp.Stat(req.PrivateKeyPath) {
return buserr.New("ErrSSLKeyNotFound")
}
if !fileOp.Stat(req.CertificatePath) {
return buserr.New("ErrSSLCertificateNotFound")
}
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil {
return err
} else {
newSSL.PrivateKey = string(content)
}
if content, err := fileOp.GetContent(req.CertificatePath); err != nil {
return err
} else {
newSSL.Pem = string(content)
}
} else {
newSSL.PrivateKey = req.PrivateKey
newSSL.Pem = req.Certificate
}
privateKeyCertBlock, _ := pem.Decode([]byte(newSSL.PrivateKey))
if privateKeyCertBlock == nil {
return buserr.New("ErrSSLKeyFormat")
}
certBlock, _ := pem.Decode([]byte(newSSL.Pem))
if certBlock == nil {
return buserr.New("ErrSSLCertificateFormat")
}
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return err
}
newSSL.ExpireDate = cert.NotAfter
newSSL.StartDate = cert.NotBefore
newSSL.Type = cert.Issuer.CommonName
if len(cert.Issuer.Organization) > 0 {
newSSL.Organization = cert.Issuer.Organization[0]
} else {
newSSL.Organization = cert.Issuer.CommonName
}
if len(cert.DNSNames) > 0 {
newSSL.PrimaryDomain = cert.DNSNames[0]
newSSL.Domains = strings.Join(cert.DNSNames, ",")
}
return websiteSSLRepo.Create(context.Background(), newSSL)
}
+108 -1
View File
@@ -3,9 +3,13 @@ package service
import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/i18n"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/nginx/components"
"gopkg.in/yaml.v3"
"path"
"reflect"
"strconv"
"strings"
"time"
@@ -36,7 +40,10 @@ func getDomain(domainStr string, defaultPort int) (model.WebsiteDomain, error) {
portStr := domainArray[1]
portN, err := strconv.Atoi(portStr)
if err != nil {
return model.WebsiteDomain{}, err
return model.WebsiteDomain{}, buserr.WithName("ErrTypePort", portStr)
}
if portN <= 0 || portN > 65535 {
return model.WebsiteDomain{}, buserr.New("ErrTypePortRange")
}
domain.Port = portN
return domain, nil
@@ -641,3 +648,103 @@ func chownRootDir(path string) error {
}
return nil
}
func changeServiceName(composePath, newServiceName string) (composeByte []byte, err error) {
composeMap := make(map[string]interface{})
fileOp := files.NewFileOp()
composeContent, _ := fileOp.GetContent(composePath)
if err = yaml.Unmarshal(composeContent, &composeMap); err != nil {
return
}
value, ok := composeMap["services"]
if !ok {
err = buserr.New(constant.ErrFileParse)
return
}
servicesMap := value.(map[string]interface{})
index := 0
serviceName := ""
for k := range servicesMap {
serviceName = k
if index > 0 {
continue
}
index++
}
if newServiceName != serviceName {
servicesMap[newServiceName] = servicesMap[serviceName]
delete(servicesMap, serviceName)
}
return yaml.Marshal(composeMap)
}
func getWebsiteDomains(domains string, defaultPort int, websiteID uint) (domainModels []model.WebsiteDomain, addPorts []int, addDomains []string, err error) {
var (
ports = make(map[int]struct{})
)
domainArray := strings.Split(domains, "\n")
for _, domain := range domainArray {
if domain == "" {
continue
}
if !common.IsValidDomain(domain) {
err = buserr.WithName("ErrDomainFormat", domain)
return
}
var domainModel model.WebsiteDomain
domainModel, err = getDomain(domain, defaultPort)
if err != nil {
return
}
if reflect.DeepEqual(domainModel, model.WebsiteDomain{}) {
continue
}
domainModel.WebsiteID = websiteID
domainModels = append(domainModels, domainModel)
if domainModel.Port != defaultPort {
ports[domainModel.Port] = struct{}{}
}
if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domainModel.Domain), websiteDomainRepo.WithWebsiteId(websiteID)); exist.ID == 0 {
addDomains = append(addDomains, domainModel.Domain)
}
}
for _, domain := range domainModels {
if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domain.Domain), websiteDomainRepo.WithPort(domain.Port)); exist.ID > 0 {
website, _ := websiteRepo.GetFirst(commonRepo.WithByID(exist.WebsiteID))
err = buserr.WithName(constant.ErrDomainIsUsed, website.PrimaryDomain)
return
}
}
for port := range ports {
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
errMap := make(map[string]interface{})
errMap["port"] = port
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
if appInstall.ID > 0 {
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
errMap["name"] = appInstall.Name
err = buserr.WithMap("ErrPortExist", errMap, nil)
return
}
runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port))
if runtime != nil {
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
errMap["name"] = runtime.Name
err = buserr.WithMap("ErrPortExist", errMap, nil)
return
}
if common.ScanPort(port) {
err = buserr.WithDetail(constant.ErrPortInUsed, port, nil)
return
}
}
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID), websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
addPorts = append(addPorts, port)
}
}
return
}
+11
View File
@@ -76,3 +76,14 @@ func WithNameAndErr(Key string, name string, err error) BusinessError {
Err: err,
}
}
func WithName(Key string, name string) BusinessError {
paramMap := map[string]interface{}{}
if name != "" {
paramMap["name"] = name
}
return BusinessError{
Msg: Key,
Map: paramMap,
}
}
+2
View File
@@ -2,6 +2,8 @@ package configs
type System struct {
Port string `mapstructure:"port"`
Ipv6 string `mapstructure:"ipv6"`
BindAddress string `mapstructure:"bindAddress"`
SSL string `mapstructure:"ssl"`
DbFile string `mapstructure:"db_file"`
DbPath string `mapstructure:"db_path"`
+3 -3
View File
@@ -6,13 +6,13 @@ const (
Error = "Error"
Stopped = "Stopped"
Installing = "Installing"
Syncing = "Syncing"
DownloadErr = "DownloadErr"
DirNotFound = "DirNotFound"
Upgrading = "Upgrading"
UpgradeErr = "UpgradeErr"
PullErr = "PullErr"
Rebuilding = "Rebuilding"
Syncing = "Syncing"
SyncSuccess = "SyncSuccess"
SyncErr = "SyncErr"
ContainerPrefix = "1Panel-"
+2
View File
@@ -4,4 +4,6 @@ type DBContext string
const (
DB DBContext = "db"
SystemRestart = "systemRestart"
)

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