Compare commits

..
Author SHA1 Message Date
ssongliu 79eb0288b4 fix: Fix the problem that the terminal exit fails (#8189) 2025-03-19 03:43:21 +00:00
蘭 99775e1eb4 fix: Fix some issues (#8178) 2025-03-18 17:16:23 +08:00
zhengkunwang db848b41d2 feat: update buildx and containerd version (#8183) 2025-03-18 17:13:36 +08:00
david082321 b5b11dff86 Update tw.ts (#8161) 2025-03-17 10:58:19 +08:00
zhengkunwang 9cf4bfc606 feat: update golang.org/x/net version to v0.37.0 (#8146) 2025-03-13 18:30:25 +08:00
ThinkStu 221162d44f Update zh.ts (#8136)
correct typos
2025-03-12 22:43:20 +08:00
蘭 617970a1f8 fix: license setting data (#8132) 2025-03-12 16:25:32 +08:00
ssongliu 5610c73d67 fix: Fix the problem that services exit unexpectedly when the contain… (#8127) 2025-03-12 03:19:03 +00:00
ssongliu 51fe02661f fix: Fix the problem of incorrect calculation of container memory res… (#8125)
Refs #8033
2025-03-12 02:13:03 +00:00
lm379andlm379 8f491b2933 feat: allow tencent cloud cos dual stack domain (#8123)
Co-authored-by: lm379 <lm379@qq.com>
2025-03-11 23:58:23 +08:00
王贺 b7e16bd6d5 Update .goreleaser.yaml (#8118) 2025-03-11 13:50:48 +08:00
ssongliu 38ca2ddd01 fix(container): Fix cpu surge when the container terminal executes exit (#8115) 2025-03-10 23:47:50 +08:00
ssongliu 402b41100b fix(container): Fix cpu surge when the container terminal executes exit (#8096)
Refs #7574
2025-03-07 11:06:59 +00:00
ssongliu 766beae4e1 fix(container): Fix the problem that a container cannot create a read… (#8095)
Refs #8074
2025-03-07 07:44:59 +00:00
maninhill 05f72e9dcf chore: Update README.md 2025-03-06 11:40:56 +08:00
igophper 23553c68ae fix(fail2ban): fix the issue of set fail2ban log path err (#8076)
Refs #8075
2025-03-06 09:44:48 +08:00
zhengkunwang 4dd1eb7a1e feat: Modify Swagger route response for unauthenticated access (#8057) 2025-03-04 05:48:57 +00:00
蘭 db307732c6 feat: Adjust license (#8056) 2025-03-03 14:32:56 +00:00
igophperandssongliu 33d4ade1d4 refactor(container): optimize memory calculation and concurrent data handling (#8038)
* refactor(container): optimize memory calculation and concurrent data handling

Refs #8033

* Update container.go

---------

Co-authored-by: ssongliu <73214554+ssongliu@users.noreply.github.com>
2025-03-03 17:38:32 +08:00
igophper 186075ff9a style: optimize code editor file path style (#8039)
Refs #8015
2025-03-03 10:23:24 +08:00
zhengkunwang 34df745d1c style: Change wget page style (#8016) 2025-02-26 10:16:54 +00:00
zhengkunwang ec363ac157 feat: update default app.yaml (#8011) 2025-02-26 15:35:54 +08:00
蘭 193b0f3cd4 fix: Update swagger docs (#8002)
Refs #8001
2025-02-26 10:55:40 +08:00
zhengkunwang 67c1bf2924 feat: Add certificate validation when creating AI Proxy (#7994) 2025-02-25 15:21:16 +08:00
ssongliu b1373ff77e feat: Support gpu of schema v11 (#7988) 2025-02-25 14:16:34 +08:00
dependabot[bot] 55d0e27212 chore(deps): bump github.com/go-jose/go-jose/v4 from 4.0.4 to 4.0.5
Bumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.0.4 to 4.0.5.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Changelog](https://github.com/go-jose/go-jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-jose/go-jose/compare/v4.0.4...v4.0.5)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-25 09:34:14 +08:00
zhengkunwang 1c052b7c13 fix: Fix the issue with AI proxy certificate res error (#7983) 2025-02-24 22:24:51 +08:00
蘭 6c8d48c2dc feat: API interface IP whitelist supports IPv6 (#7981)
Refs #7836
2025-02-24 10:05:13 +00:00
ssongliu b61dae638b fix(forward): Fix the problem of duplicate creation of port forwardin… (#7975)
Refs #7969
2025-02-24 09:21:14 +00:00
zhengkunwang 872a93aa07 fix: Fix the issue with the homepage route refresh (#7974) 2025-02-24 15:00:20 +08:00
igophper b1f337020c fix(container/log): enable close-on-click-modal and wrap log update in nextTick (#7960)
Refs #7547
2025-02-24 13:34:51 +08:00
maninhill 56858dd74c chore: Update README.md 2025-02-24 10:54:05 +08:00
Johannes Plunien 358415f737 feat: Support freemyip.com DNS provider (#7958) 2025-02-24 10:21:37 +08:00
david082321 5e73260103 feat: Update zh-Hant translation (#7966) 2025-02-22 23:16:38 +08:00
zhengkunwang e169f46784 fix: Fixed the issue of no echo after binding the SSL to the AI. (#7953) 2025-02-21 09:29:51 +00:00
ssongliu 39416abd47 fix: Fix the issue of inconsistent deletion status for the ollama model (#7950)
Refs #7948
2025-02-21 08:51:51 +00:00
wanghe-fit2cloud 640a0ca815 chore: Optimize some command outputs 2025-02-21 16:45:56 +08:00
ssongliu 8e54cd5162 style: Adjust the width display of the model list (#7946) 2025-02-21 07:54:29 +00:00
ssongliu 0f0099accb fix: Fix the issue of loading errors for editing container port data (#7945)
Refs #7938
2025-02-21 04:01:49 +00:00
ssongliu 718ebeb203 fix: Modify help information about Ollama pull (#7935) 2025-02-20 15:21:50 +08:00
ssongliu 4101bf691d style: Fix the issue of inconsistent menu spacing. (#7932) 2025-02-20 13:45:48 +08:00
蘭 a97deb3dca feat: API timestamp verification (#7927)
* feat: API timestamp verification

* feat: API timestamp verification
2025-02-20 13:29:26 +08:00
zhengkunwang 10203d5c0c fix: Resolve the issue of local application label loss (#7926) 2025-02-20 13:29:04 +08:00
maninhill a357d6697d chore: Update README.md 2025-02-19 22:58:06 +08:00
ssongliu 555b0aa999 fix: Optimize status display. (#7920) 2025-02-19 22:54:34 +08:00
蘭 6dd0dbe2c3 feat: Improve international language (#7918) 2025-02-19 13:35:39 +00:00
zhengkunwang c31bbae768 feat: Optimized the display when no certificate is present. (#7917) 2025-02-19 11:03:39 +00:00
ssongliu 2bb0f15973 fix: Fix the loading method of slow logs in MySQL and MariaDB (#7915)
Refs #6353
2025-02-19 09:48:36 +00:00
zhengkunwang be229551e3 feat: AI tool Added quick jump functionality (#7913) 2025-02-19 08:26:31 +00:00
蘭 6283eb4c69 feat: Add language translation and icons (#7912) 2025-02-19 08:14:32 +00:00
ssongliu c329fb6599 feat: Support for terminal operation with the Ollama model (#7907) 2025-02-19 14:07:05 +08:00
zhengkunwang223 c3685f6b74 feat: Adjusted the position of the quick jump button. 2025-02-18 20:25:31 +08:00
maninhill f4f5a36475 chore: Update README.md 2025-02-18 20:25:04 +08:00
zhengkunwang ea1261b48e feat: Added partial prompt messages (#7900) 2025-02-18 10:08:52 +00:00
wanghe-fit2cloud 0c68f16a66 feat: Modify some translations 2025-02-18 17:09:13 +08:00
ssongliu 33e5c9230f fix: Optimized ollama model status display (#7899) 2025-02-18 17:06:20 +08:00
zhengkunwang 96eefab36f feat: Added underscore support for website default documents (#7898) 2025-02-18 17:06:10 +08:00
zhengkunwang b0b6bf458f feat: Added display of ollama proxy address (#7897) 2025-02-18 15:00:33 +08:00
zhengkunwang f3d85d1309 fix: Fixed the issue where local application descriptions were not di… (#7896)
Refs https://github.com/1Panel-dev/1Panel/issues/7886
2025-02-18 06:17:11 +00:00
ssongliu 39385ea0a0 fix: Adjust the synchronization method for the Ollama model (#7895) 2025-02-18 06:09:10 +00:00
zhengkunwang e492c6573c feat: Modified the logic for AI Tool (#7894) 2025-02-18 05:59:10 +00:00
wanghe-fit2cloud 10a7fb3be2 feat: Update the official website URL for the international version 2025-02-18 10:31:38 +08:00
王贺 8bc7cfade3 Update README.md (#7891) 2025-02-17 22:26:29 +08:00
ssongliu ea044d6c32 fix: change the AI routing interface (#7887) 2025-02-17 15:33:57 +08:00
zhengkunwang f6ee3dc75b feat: Added streaming transmission configuration (#7875) 2025-02-15 12:59:38 +00:00
ssongliu 367a74503f fix: Fix the problem of duplicate content display in the model list (#7872) 2025-02-14 09:10:05 +00:00
蘭 53b1a7af4c feat: Copy and move files with the same name file processing (#7871) 2025-02-14 06:28:06 +00:00
zhengkunwang 078d7fbe1e feat: Add AI-enhanced configuration (#7870) 2025-02-14 06:26:05 +00:00
ssongliu c709e48ceb feat: support load ollama model details (#7867) 2025-02-13 14:56:24 +00:00
endymx 0741f60896 fix(iptables): 复杂环境下转发删除端口错误 (#7868) 2025-02-13 22:56:09 +08:00
ssongliu af8eef4a91 feat: Support Ollama model management (#7866) 2025-02-13 15:28:29 +08:00
zhengkunwang f233ef7069 feat: Adding GPU acceleration configuration to some applications (#7865) 2025-02-13 07:02:08 +00:00
蘭 1c199bd3d7 style: Optimize app store style and layout (#7858)
Refs #7846
2025-02-12 21:56:52 +08:00
ssongliu 036c973fec fix: Fix the security entry verification error issue. (#7854)
Refs #7853
2025-02-11 10:13:49 +00:00
蘭 8bb225d272 feat: Check for duplicate files before uploading (#7849)
Refs #5893
2025-02-11 10:11:48 +00:00
zhengkunwang ab932ae154 fix: Fixed the issue where application labels were not displayed after updating. (#7834) 2025-02-10 11:17:24 +08:00
david082321 89f969ec6e feat: Update zh-Hant translation (#7830) 2025-02-09 22:01:02 +08:00
ssongliu afa8cf22b1 feat: Add function backups by default for MySQL and MariaDB databases. (#7823) 2025-02-08 22:56:46 +08:00
ssongliu 67aa8471dc fix: Remove some comments. (#7822) 2025-02-08 08:41:27 +00:00
zhengkunwang 0617b81b3b feat: The appstore has added support for the Korean language (#7818) 2025-02-07 13:07:20 +00:00
ssongliu 98c535a12c fix: improve the backend verification for security entry settings (#7810)
Refs #7657
2025-02-06 10:15:06 +00:00
ssongliu ec46518936 feat: Improve the name of the professional version (#7807) 2025-02-06 10:13:03 +00:00
ssongliu a7b034387f fix: fix some internationalization formats (#7803) 2025-02-05 14:41:59 +00:00
endymx 7905dd00a6 fix(firewall): 删除复杂转发规则时报错 (#7791) 2025-02-05 18:37:42 +08:00
zhengkunwang 74583aa1aa feat: fix anti-leech is not work on proxy website (#7801)
Refs https://github.com/1Panel-dev/1Panel/issues/7752
2025-02-05 10:07:16 +00:00
dependabot[bot] 4be9d71edf chore(deps): bump github.com/golang/glog from 1.2.2 to 1.2.4 (#7787) 2025-01-31 13:08:01 +08:00
zhengkunwang 57bfc38eb8 feat: Application details have been enhanced with tags. (#7777)
Refs https://github.com/1Panel-dev/1Panel/issues/7774
2025-01-27 11:04:26 +00:00
zhengkunwang aaaa5980b5 feat: Added password encryption for login functionality (#7764) 2025-01-23 18:09:12 +08:00
蘭 4f57dfc76e feat: Unify the response body of the API interface (#7761) 2025-01-23 08:28:04 +00:00
wanghe-fit2cloud 2c31ffc66b feat: Enhance app redirection messages 2025-01-23 15:32:11 +08:00
王贺 b104a13b71 Update README.md (#7747) 2025-01-20 22:48:29 +08:00
maninhill 28633d2fef chore: Update README.md 2025-01-20 22:33:20 +08:00
蘭 9052386c83 feat: Korean language support (#7727)
Refs #7363
2025-01-15 10:26:30 +00:00
maninhill 7bc45f2d77 chore: Update README.md 2025-01-15 15:24:20 +08:00
wanghe-fit2cloud 2ef6ecb951 chore: Update the README.md 2025-01-15 10:40:22 +08:00
zhengkunwang ca0dc71338 feat: Enable Multi-Language Support for Application Installation Forms (#7717) 2025-01-14 19:03:22 +08:00
zhengkunwang 04a1ec9a9a feat: Add Multi-Language Support for Application Labels (#7714) 2025-01-14 16:00:09 +08:00
蘭 999e5a779a feat: Update swagger docs (#7710) 2025-01-13 15:10:04 +00:00
zhengkunwang 99f62b7230 fix(website):Fix Reverse Proxy Deletion Failure in Certain Scenarios (#7709)
Refs https://github.com/1Panel-dev/1Panel/issues/7701
2025-01-13 15:08:04 +00:00
zhengkunwang 4dee4e1cc2 feat: Update Application Name Restrictions (#7706) 2025-01-13 07:56:03 +00:00
maninhill 539addc656 chore: Update README.md 2025-01-10 23:07:15 +08:00
BugKing 1a35b307fa docs: add introduction of 1Panel Pro in README (#7699) 2025-01-10 22:32:02 +08:00
蘭 a04f4a8b96 feat: Improve international language and style (#7697)
Refs #7696
2025-01-10 10:57:45 +00:00
ssongliu 6b88e1adf2 fix: Remove redundant code (#7694) 2025-01-10 15:06:18 +08:00
蘭 99bc8177d4 feat: Save custom theme color scheme (#7690) 2025-01-10 04:13:44 +00:00
ssongliu cf2a1372f2 style: Optimize some internationalization styles (#7689) 2025-01-10 04:11:44 +00:00
蘭 42c30f324a feat: Improve international language (#7687) 2025-01-10 02:21:44 +00:00
蘭 dab83fee20 feat: Modify international version functions (#7686) 2025-01-10 02:19:44 +00:00
蘭 6f3c5586fc feat: Update international address (#7685) 2025-01-10 02:17:43 +00:00
ssongliu aab8df6abc fix: Fix the issue of database cover exception display. (#7682) 2025-01-09 13:59:41 +00:00
蘭 b9be79b05a feat: Menu enables vue-router mode (#7681) 2025-01-09 12:15:42 +00:00
zhengkunwang ec3024f2c3 feat: Change AppDto to AppItem (#7680) 2025-01-09 12:13:41 +00:00
ssongliu 070f61e229 fix: Fix the issue of pagination errors in the backup list (#7673) 2025-01-09 03:07:40 +00:00
蘭 a82a4ebfc5 style: Optimize style and layout (#7671) 2025-01-08 10:19:37 +00:00
蘭 87009ddb27 feat: Modify the copyright (#7670) 2025-01-08 07:39:37 +00:00
蘭 3650ff27b3 feat: Dealing with Sass version compatibility issues and removing debugger from build (#7669) 2025-01-08 07:21:38 +00:00
ssongliu 6c08a3114a fix: Fix the issue of interface returning internationalization failure (#7668) 2025-01-08 07:19:37 +00:00
蘭 381cb61185 feat: Internationalization language order (#7666) 2025-01-08 03:33:37 +00:00
蘭 8d69da7702 feat: Break long menu items into multiple lines (#7665) 2025-01-08 03:31:36 +00:00
ssongliu 8922395fdc fix: Fix the issue of frontend packaging errors (#7661) 2025-01-07 06:47:35 +00:00
ssongliu 83db40e261 feat: Support for asynchronously obtaining the backup file size (#7660) 2025-01-07 06:35:33 +00:00
zhengkunwang 95ec6c62ef feat(system): Fix Issue Allowing Access via Old Secure Entry After Mo… (#7659)
Refs https://github.com/1Panel-dev/1Panel/issues/7658
2025-01-07 06:09:32 +00:00
蘭 56fc9ea428 feat: Improve international language proficiency (#7656) 2025-01-07 04:19:33 +00:00
蘭 88c6fc050b feat: Upgrade package version (#7655) 2025-01-07 04:03:33 +00:00
蘭 2392f91567 feat: Panel aliases support common special characters (#7654)
Refs #6909
2025-01-07 04:01:33 +00:00
蘭 5f0c740eb0 feat: Improve and format language files (#7645) 2025-01-06 05:48:21 +00:00
Lucas Pedro 120d0dd7c6 Traducao pt br (#7624) 2025-01-06 10:57:34 +08:00
liuchang_cloud 2844f6db7f feat: Support Japanese by Google Translate (#7437) 2025-01-06 10:39:49 +08:00
王贺 570074f92d Update README.md 2025-01-04 10:56:43 +08:00
Anye a13047c855 Update Default PHP Extensions (#7637) 2025-01-04 10:44:41 +08:00
蘭 ca0d24bf56 feat: Improve and format language files (#7634) 2025-01-03 08:52:09 +00:00
Pisyek K. 2b18251360 chore: add bahasa melayu translation (#7623)
* chore: add bahasa melayu translation
2025-01-03 11:42:13 +08:00
蘭 f7c875acda feat: Save the theme color scheme to the client (#7626)
Refs #7074
2025-01-03 02:30:07 +00:00
ssongliu a291a50c9f feat: Support for license import in the international version (#7625) 2025-01-02 15:00:05 +00:00
蘭 5bc7bc6aac fix: Fix missing response types in Swagger API endpoints (#7611)
Refs #7607
2024-12-31 09:57:55 +00:00
zhengkunwang 9c376300ff feat(ssl): Add Support for Rain Yun in DNS Account (#7613)
Refs https://github.com/1Panel-dev/1Panel/issues/7115
2024-12-31 09:55:54 +00:00
Ryan Wang 5187b20252 fix: correct Swagger API definitions (#7606)
Signed-off-by: Ryan Wang <i@ryanc.cc>
2024-12-31 10:32:47 +08:00
ssongliu fc401ffd8f fix: Optimize image deletion error return (#7602)
Refs #7068
2024-12-30 09:17:49 +00:00
zhengkunwang 667ee5256e fix: Fix Application Startup Failure Caused by Case-Sensitive Applica… (#7601)
Refs https://github.com/1Panel-dev/1Panel/issues/7600
2024-12-30 09:15:49 +00:00
wanghe-fit2cloud f8356de93c Modify the copyright 2024-12-30 16:38:54 +08:00
endymx 55bb997d51 feat(iptables): Support forwarding for complex networks (#7598)
* feat(iptables): 支持对复杂网络的转发

* refactor(iptables): 提供更完善的接口和报错
2024-12-30 13:55:53 +08:00
ssongliu 7c46f54e15 fix: Fix the issue of failure to retrieve firewall status (#7597)
Refs #7527
2024-12-30 05:37:49 +00:00
ssongliu 6dbb6d2247 fix: Fix the issue of backup failure due to complex passwords in the pg (#7596) 2024-12-30 13:36:51 +08:00
ssongliu 9d0ae45edc feat: Optimize the display of scheduled task execution cycles (#7595) 2024-12-30 05:35:49 +00:00
蘭 b467dfa3b2 feat: Add expiration time setting for API key (#7584) 2024-12-30 05:33:49 +00:00
蘭 c13387bc70 style: Optimize the display of status cards on the overview page (#7562)
* style: Optimize the display of status cards on the overview page
2024-12-27 14:01:02 +08:00
BugKing 41b2523750 docs: replace Discord link in readme (#7573) 2024-12-26 18:32:50 +08:00
zhengkunwang afe82bd4be feat: Remove Default Configuration for Reverse Proxy Cache (#7566) 2024-12-26 10:16:07 +08:00
JB-SelfCompany 0f296fb70b Update README for Russian language (#7560) 2024-12-25 16:37:06 +08:00
JB-SelfCompanyandBubblegum d96ccd06a3 Russian language support. (#7554)
* Add Russian language

* Use prettier

---------

Co-authored-by: Bubblegum <jack_benq@selfhosted.lan>
2024-12-25 09:34:50 +08:00
BugKing 14095affa9 docs: add discord badge in readme (#7544) 2024-12-24 14:03:05 +08:00
Anye ed60565bc9 Update cache.conf (#7516)
Remove `proxy_cache ` from the global config to prevent it from being enabled for sites that don't need caching.
2024-12-23 11:21:23 +08:00
david082321 8313912c4f fix: Update zh-Hant translation (#7515) 2024-12-21 20:34:24 +08:00
wolf 6274015d06 fix: Optimize some translations (#7495) 2024-12-20 18:45:45 +08:00
蘭 d195ce9155 feat: Login to access Swagger documentation (#7496) 2024-12-20 18:37:59 +08:00
Flyum cd0cd8a152 fix: Modify some English translations (#7494) 2024-12-20 18:06:44 +08:00
liuboF2candliubo 1f45ed6b06 fix: Correct English internationalization translations (#7493)
Co-authored-by: liubo <liubo@fit2cloud.com>
2024-12-20 18:05:58 +08:00
zhengkunwang 7f6ad89edf feat: Optimize some translations (#7492) 2024-12-20 17:48:52 +08:00
liuboF2candliubo 5cdea288e2 fix: 修正英文国际化翻译 (#7491)
Co-authored-by: liubo <liubo@fit2cloud.com>
2024-12-20 17:29:43 +08:00
wanghe-fit2cloud e56feaf826 docs: Optimize README 2024-12-20 16:35:23 +08:00
zhengkunwang 1288a09647 fix: Optimize some translations (#7490) 2024-12-20 16:33:35 +08:00
wanghe-fit2cloud 0cdaafa1c0 docs: Optimize README 2024-12-20 16:21:23 +08:00
Frist soulful 0b3334253c Update zh-Hant.yaml (#7489) 2024-12-20 16:20:31 +08:00
Yuki Guo 10f72f12d2 docs: Update tw.ts (#7487) 2024-12-20 16:08:07 +08:00
feng626 01643b2816 perf: Optimize FTP sync function for better performance and readability (#7479) 2024-12-20 15:45:05 +08:00
zrfit 56e0da4fe3 docs: Update README.tr.md (#7486) 2024-12-20 15:41:27 +08:00
song-cc-rock 144c397bf4 fix: update zh-hant spell 2024-12-20 15:34:57 +08:00
ZhaoJiSen e06541984f Add ImportMeta type definition (#7481) 2024-12-20 15:32:58 +08:00
zhengkunwang ea7e92db84 feat: Remove Redundant Code (#7484) 2024-12-20 07:32:25 +00:00
wxg 8d48640c1d fix: Update zh-Hant.yaml (#7483) 2024-12-20 15:31:25 +08:00
zrfit cfe5cb4b6b Add File README.tr.md (#7480) 2024-12-20 15:25:53 +08:00
9527 05c4d7dd38 docs: Add German README (#7482) 2024-12-20 15:20:45 +08:00
wangyicheng 13c6e0df99 docs: Update README.es.md (#7477) 2024-12-20 15:11:10 +08:00
MignonZhang dafd6ba71e fix: fix typos (#7478) 2024-12-20 15:09:26 +08:00
莫鹍 2751c37716 refactor(i18n): fix spelling error (#7476) 2024-12-20 15:08:22 +08:00
蘭 50c01762e7 feat: Open international professional features (#7472) 2024-12-20 07:04:26 +00:00
w940853815 a77ebd3eb6 fix: Typo in hostname save function and button click (#7475) 2024-12-20 15:02:30 +08:00
gerry-f2c d84f0b5597 style: Optimize the backup account style code (#7474) 2024-12-20 15:00:14 +08:00
Slooop a3cdf87ea2 style: Optimize the backup account style code (#7473) 2024-12-20 14:59:57 +08:00
Chenyang Shen 8ab3c16b3d Update zh-Hant.yaml 2024-12-20 14:54:24 +08:00
Shenguobin0102 18e943fd06 fix: Modified the RTL format to right-align the first sentence of the body (#7470) 2024-12-20 14:52:53 +08:00
zyyfit 3b7a067dda Create README.fr.md (#7469) 2024-12-20 14:24:09 +08:00
ZhaoQian1222 4636ba815b fix: Corrected some internationalization translations (#7468) 2024-12-20 14:22:30 +08:00
Shenguobin0102 317fad2a28 docs: Update README.ar.md (#7467) 2024-12-20 14:18:31 +08:00
MatataYou 0ae28a1dd9 Update README.es.md (#7466) 2024-12-20 14:05:28 +08:00
Anye bbfe5f1d96 style: Modify some styles to improve the appearance of the version button (#7464) 2024-12-20 13:59:02 +08:00
zhengkunwang b713f20b66 style: Optimize OpenResty Warnings Displayed During Zooming (#7465)
Refs https://github.com/1Panel-dev/1Panel/issues/7452
2024-12-20 05:50:25 +00:00
Shenguobin0102 3eb7a5adc5 docs: Add Arabic README (#7463) 2024-12-20 13:49:23 +08:00
MatataYou 956af78749 docs: Add Spanish Language README (#7461) 2024-12-20 13:43:55 +08:00
zhengkunwang 69ad01687e feat: Optimize Location Information Display in System Login Logs (#7459) 2024-12-20 04:16:25 +00:00
Anye e83d07e88e style: Modify some styles to improve the appearance of the version button (#7462) 2024-12-20 12:03:49 +08:00
zhengkunwang 6683696032 fix(system): Fix Cloudflare Proxy Access Issue with 1Panel When Secure Entry Is Enabled (#7458) 2024-12-20 11:03:49 +08:00
zhengkunwang 3396a5ffea go: upgraded golang.org/x/crypto v0.28.0 => v0.31.0 (#7456) 2024-12-20 02:26:24 +00:00
zhengkunwang 18a14d3b75 go: upgraded golang.org/x/net v0.30.0 => v0.33.0 (#7455) 2024-12-20 02:14:23 +00:00
王贺 2b13352004 chore: Add Indonesian language (#7445) 2024-12-19 23:20:48 +08:00
maninhill 94e5d7e642 chore: Update README.md 2024-12-19 22:42:35 +08:00
maninhill 001b4dbada docs: Create README.id.md 2024-12-19 22:41:22 +08:00
BugKing 1192dec689 docs: Add Product Hunt badge (#7434) 2024-12-19 11:55:18 +08:00
蘭 956d47f9da refactor: Demo server, prohibit operation (#7433) 2024-12-19 02:06:19 +00:00
John Niang 063a071228 Fix invalid postion of before content in home page in Firefox Linux (#7429) 2024-12-18 18:33:59 +08:00
Ryan Wang c54a7de827 docs: add Korean README documentation (#7427)
Signed-off-by: Ryan Wang <i@ryanc.cc>
2024-12-18 17:15:10 +08:00
老广 0410e48aad docs: Add README.pt-br.md (#7425) 2024-12-18 16:29:44 +08:00
liuchang_cloud a4d95737d3 docs: Update README.md (#7424) 2024-12-18 16:16:14 +08:00
jianneng-fit2cloud bc64d83ab2 style: Container style (#7422) 2024-12-18 15:32:30 +08:00
蘭 87616e388b style: Optimize style (#7414)
Refs #7419
2024-12-18 06:44:14 +00:00
taojinlongandtaojinlong 3f35f90fc2 fix: fix typos (#7413)
Co-authored-by: taojinlong <jinlong@fit2cloud.com>
2024-12-18 14:06:00 +08:00
王嘉豪 c3ba69814c Update fa.yaml (#7411) 2024-12-18 14:05:46 +08:00
wisonic-s 66a517e58d fix: fix typos (#7407) 2024-12-18 14:05:24 +08:00
Bryan 3108c927af fix: typos (#7405) 2024-12-18 14:04:51 +08:00
Junjun 5738cceac9 fix typos (#7404) 2024-12-18 14:04:17 +08:00
dataeaseShu db2f648bce fix: fix typos (#7403) 2024-12-18 14:04:06 +08:00
fit2cloud-chenyw 6012a6cf9f fix: datas should be dataList (#7402) 2024-12-18 14:03:56 +08:00
ulleo a4dcbc90e6 fix: fix typos (#7401) 2024-12-18 14:03:40 +08:00
BugKing 955ecce952 docs: Update README.md (#7416) 2024-12-18 13:34:56 +08:00
maninhill 91fba21ed3 chore: Update README.md 2024-12-18 11:55:20 +08:00
wanghe-fit2cloud 490e2934b8 chore: Optimize the README file 2024-12-18 11:54:06 +08:00
wanghe-fit2cloud cb6d3d4fc3 chore: Optimize the README file 2024-12-18 11:52:05 +08:00
xuwei-fit2cloud 7f2a09eab3 fix: fix typos 2024-12-18 10:25:43 +08:00
John Niang c522a308b9 Refine English translation and UI style (#7399) 2024-12-18 10:24:00 +08:00
ssongliu dde686d55f style: Increase the height of the script input box (#7398) 2024-12-18 02:12:14 +00:00
maninhill 2f0b4888de chore: Update README_EN.md 2024-12-18 09:37:56 +08:00
ssongliu 35e7b11709 style: Increase the height of the script input box (#7396) 2024-12-17 15:42:11 +00:00
ssongliu 6cf3f158c7 fix: Improve cache cleaning for internationalization (#7395) 2024-12-17 15:10:11 +00:00
蘭 4944e705dc fix: Fix the issue of clearing cache title judgment (#7394) 2024-12-17 15:02:11 +00:00
蘭 3b38b9d86b feat: Optimize style and description (#7393) 2024-12-17 12:46:11 +00:00
zhengkunwang 6275eec918 style: change some label (#7392) 2024-12-17 12:44:11 +00:00
zhengkunwang ad652ca6f5 style: change some label (#7387) 2024-12-17 08:50:09 +00:00
zhengkunwang 7029d985c6 style: change some column width (#7385) 2024-12-17 06:44:08 +00:00
ssongliu 9539fd40eb fix: Fix the issue of compose name validation errors (#7382)
Refs #7380
2024-12-17 04:16:12 +00:00
蘭 4c03a482bd feat: Modify document address (#7381) 2024-12-17 02:28:12 +00:00
蘭 f58ed5614e feat: Optimize style and description (#7378) 2024-12-16 14:16:10 +00:00
zhengkunwang 198e78e0b4 feat: change default language (#7377) 2024-12-16 11:04:10 +00:00
wanghe-fit2cloud 1f16e09daa chore: Optimize the prompt messages on some pages 2024-12-16 18:27:15 +08:00
蘭 16f47f8664 fix: Fix the issue of incorrect display of prompts on the English language login page (#7376) 2024-12-16 09:40:10 +00:00
蘭 40604c7880 feat: Optimize international document addresses (#7372) 2024-12-16 09:38:09 +00:00
ssongliu fa86c4f39a fix: Fixed an issue where the language pack initialization download f… (#7375) 2024-12-16 09:00:10 +00:00
zhengkunwang 7f3cc784cd feat: Fix Application Store Style Issue Under Poor Network Conditions (#7374)
Refs https://github.com/1Panel-dev/1Panel/issues/7370
2024-12-16 08:58:09 +00:00
zhengkunwang 836f6c3520 feat: Fix Translation Issue in Input Field Placeholder on First Login (#7369) 2024-12-16 05:46:09 +00:00
蘭 2ff1e3a245 style: Optimize international style layout (#7368) 2024-12-16 05:44:08 +00:00
wanghe-fit2cloud f7078a6140 chore: Update the overview image 2024-12-16 11:42:49 +08:00
ssongliu 141786e4e9 fix: FIx the issue of container editing not opening successfully (#7360) 2024-12-13 14:35:56 +00:00
蘭 2d098f8078 style: Optimize layout style (#7359) 2024-12-13 14:33:56 +00:00
John Niang 229254e3d3 Replace whitelist and blacklist with allowlist and blocklist (#7358) 2024-12-13 22:33:07 +08:00
刘瑞斌 96329967ba feat: CornJob shell script syntax highlighting (#7357) 2024-12-13 21:31:58 +08:00
ssongliu 0d988bbd6a pref(system): Optimize and upgrade related internationalization translations. (#7356) 2024-12-12 15:57:50 +00:00
蘭 1ff4f33ceb style: Optimize layout style (#7354) 2024-12-12 22:20:21 +08:00
John Niang c95d61397d Refine English translation again and again (#7353) 2024-12-12 18:46:01 +08:00
蘭 590238dc13 style: Optimize layout style (#7352) 2024-12-12 10:19:50 +00:00
蘭 ed1b2613f2 style: Code Style Format (#7351) 2024-12-12 09:33:49 +00:00
蘭 c0e0db670c feat: Adjust the empty status prompt layout (#7350) 2024-12-12 09:03:50 +00:00
蘭 9132a2c4a9 fix: Fixed the bug of displaying prompt information for first-time login (#7348) 2024-12-12 09:01:51 +00:00
蘭 5e880ba25e feat: Language pack content adjustment (#7349) 2024-12-12 08:59:50 +00:00
蘭 5a1928bee6 feat: Optimize English description and layout (#7346) 2024-12-12 07:23:49 +00:00
ssongliu 82e9e72c70 feat: Fix the initialization errors of GeoIP (#7345) 2024-12-12 06:55:49 +00:00
ssongliu c35f55f70c pref: Optimize the button style for database connection information (#7342) 2024-12-12 03:53:48 +00:00
ssongliu 0542b39373 pref: Optimize the button style for database connection information (#7341) 2024-12-12 02:37:49 +00:00
igophper 013cf21863 fix: fixed the issue of abnormal log request (#7338)
Refs #7339
2024-12-12 10:36:41 +08:00
dependabot[bot] c648f9b14a build(deps): bump golang.org/x/crypto from 0.28.0 to 0.31.0 (#7340)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.28.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-12 10:36:01 +08:00
igophper d9407c425f fix: correct typos in typescript interface names (#7337) 2024-12-12 09:51:21 +08:00
igophper 2c8dad980b refactor(init): run docker network creation and firewall setup in a goroutine (#7336) 2024-12-11 22:33:37 +08:00
zhengkunwang 75d94f5b89 feat: Fix 500 Error After Setting Authorized IP (#7334) 2024-12-11 10:47:45 +00:00
蘭 4d760d3019 feat: Some adjustments to internationalization (#7332) 2024-12-11 10:45:45 +00:00
ssongliu 20c9230291 feat(init): Add support for geo ip pack initialization (#7333) 2024-12-11 18:44:18 +08:00
liqiang-fit2cloud 02c3a34f13 build: try another LLM for code review. 2024-12-11 17:27:52 +08:00
Meng Zhuo c2dadc2b92 fix: typo in makefile (#7327) 2024-12-11 16:07:26 +08:00
ssongliu f5de005ad7 feat: Add YAML format to CodeMirror (#7326)
Refs #7274
2024-12-11 07:47:43 +00:00
zhengkunwang 335a82332f feat: Handle HTTP 444 Status Code (#7325) 2024-12-11 06:57:43 +00:00
wanghe-fit2cloud a81cb5c1ab chore: Remove some unused variables 2024-12-11 14:31:59 +08:00
ssongliu aaf1d86a55 fix(database-pg): Fixed the issue of PostgreSQL not being able to back up. (#7324) 2024-12-11 06:25:43 +00:00
蘭 cbad4dd172 style: Optimize the layout of app operation buttons (#7322) 2024-12-11 06:23:43 +00:00
蘭 932da58759 fix: i18n file enhancement (#7321) 2024-12-11 06:21:43 +00:00
John Niang 01defdf0f6 Refine pluralization of some English words (#7318)
* Refine plural translation of English words

* Remove useless i18n modifier
2024-12-11 09:23:37 +08:00
王贺 b33cce3059 chore: Include the GeoIP.mmdb file when building the installation package (#7317) 2024-12-10 19:04:08 +08:00
ssongliu 17ef66aa49 feat(init): add support for international language pack initialization (#7315) 2024-12-10 18:36:53 +08:00
zhengkunwang f01d770fec feat: Fix Missing CPU and Memory Limit Warnings When Editing Installe… (#7313) 2024-12-10 09:55:39 +00:00
wanghe-fit2cloud 06cc7fcc02 chore: Include language packs when building the installation package 2024-12-10 17:50:49 +08:00
zhengkunwang 4635047004 feat: Remove Unused Components (#7311) 2024-12-10 08:21:38 +00:00
蘭 88b70eba53 style: Improve password action buttons styling in database connection info (#7309)
Refs #7284
2024-12-10 07:59:38 +00:00
蘭 6ad48250f8 style: Optimize input to disable background color (#7308) 2024-12-10 07:57:38 +00:00
ssongliu 9ac9f76a1d fix(container): Fix the issue of container command parsing failure (#7307) 2024-12-10 07:55:39 +00:00
igophper b7702daea3 fix: 解决控制台报错问题 (#7299) 2024-12-10 15:08:58 +08:00
zhengkunwang db7180a761 feat: Add Return Pages for Unauthorized Domains and IPs (#7306) 2024-12-10 11:58:32 +08:00
蘭 dbe62082ff style: Adjusted some English layouts (#7305) 2024-12-10 03:49:37 +00:00
蘭 06bf2bbc2f fix: Fix alert setting issue (#7304) 2024-12-10 03:17:38 +00:00
zhengkunwang 162a0c543c feat: Fix Issue with DNS Account Deletion After Certificate Update Ap… (#7303)
Refs https://github.com/1Panel-dev/1Panel/issues/7300
2024-12-10 03:15:38 +00:00
蘭 2bc07c91df pref: Improve Swagger authentication (#7298) 2024-12-09 09:57:34 +00:00
蘭 3d84a5589f fix: Dealing with API interface issues (#7295) 2024-12-09 07:29:33 +00:00
BugKing b88438a0a3 chore: refile English translation (#7283) 2024-12-06 18:53:52 +08:00
王贺 b73dcc9388 Modify the issues-translate-action token (#7281) 2024-12-06 17:21:01 +08:00
Ryan Wang 12ad08a619 chore: fix phantom dependency issue (#7279)
Signed-off-by: Ryan Wang <i@ryanc.cc>
2024-12-06 17:16:19 +08:00
王贺 0c000a4994 fix: Modify the default open source license in Swagger (#7277)
Refs #7275
2024-12-06 08:57:20 +00:00
蘭 d2da7e2ea5 pref: Improve the API interface process (#7272) 2024-12-06 08:19:19 +00:00
蘭 873bba92db Fix: Postgres fails to connect when using special characters (#7269) 2024-12-06 10:19:41 +08:00
zhengkunwang 3e14186d3d feat: Add .NET Runtime Environment for Websites (#7266) 2024-12-05 10:05:14 +00:00
Cookie 5be325405d Fix: Postgres fails to connect when using special characters (#7262)
* Update client.go

* Update remote.go

* Update client.go
2024-12-05 16:00:52 +08:00
ssongliu 5b92b75090 feat(cmd): Add internationalization for the output of the 1pctl version (#7263) 2024-12-05 07:43:14 +00:00
ssongliu 7202de6f4c feat: Add pt-BR support for i18n (#7261) 2024-12-05 06:43:15 +00:00
zhengkunwang e6a772ebfd feat: Add System Version Restrictions for Applications (#7260) 2024-12-05 06:41:14 +00:00
John Niang f320492164 Refine English translation (#7247) 2024-12-04 21:32:59 +08:00
zhengkunwang d8fd430856 fix: Fix Issue with Podman Unable to Create PHP Runtime Website (#7253) 2024-12-03 11:01:05 +00:00
zhengkunwang 8e3a06b07f feat: Internationalize Certain Files (#7252) 2024-12-03 10:17:05 +00:00
maninhill b6f65f278d chore: Create README_CN.md 2024-12-03 18:04:15 +08:00
maninhill 3e8dfb6841 chore: Update README.md 2024-12-03 17:44:40 +08:00
maninhill ffeb47eaac chore: Update README_EN.md 2024-12-03 17:37:36 +08:00
maninhill 4cffe1d6bc chore: Update README_EN.md 2024-12-03 17:35:53 +08:00
wanghe-fit2cloud 49b3b6ded5 feat: Improve system language translations 2024-12-03 15:31:27 +08:00
BugKing f294130746 chore: fix typo for CloudDNS (#7243) 2024-12-03 15:28:29 +08:00
wanghe-fit2cloud 1910f1b78a feat: 1pctl command supports more languages 2024-12-03 15:27:34 +08:00
wanghe-fit2cloud cc1d2f1eae chore: Update app.yaml 2024-12-03 13:51:06 +08:00
wanghe-fit2cloud 048121a936 chore: Update workflows 2024-12-02 14:24:01 +08:00
John Niang e41e74d730 Refine English translation (#7232) 2024-12-01 22:14:44 +08:00
蘭 0ef1a26e95 pref: Remove Swagger description information (#7214) 2024-11-30 11:44:50 +00:00
zhengkunwang 00701a3999 feat(website): Translate Chinese Parts of Website Default Files (#7213) 2024-11-30 11:42:51 +00:00
wanghe-fit2cloud 8453e60609 chore: Streamline some issue templates 2024-11-29 22:51:42 +08:00
wanghe-fit2cloud d139073948 chore: Update workflows 2024-11-29 22:21:35 +08:00
王贺 f6e6f9cbfb chore: Create issue-translator.yml 2024-11-29 19:51:11 +08:00
wanghe-fit2cloud 66e4af2be5 chore: Update Security policy 2024-11-29 15:30:41 +08:00
wanghe-fit2cloud 7327ee3ff8 feat: Optimize the CI script 2024-11-29 15:11:13 +08:00
zhengkunwang 23087bdb6f feat(logs): Change IP Database to Support Internationalization (#7212)
change ip database from qqwry to geoip
2024-11-29 03:46:44 +00:00
zhengkunwang 5e9a69d8f3 Update README_EN.md (#7210) 2024-11-29 10:09:07 +08:00
zhengkunwang 3e96e83c3c feat(appstore): Handle Requests After Application Installation (#7206) 2024-11-28 10:42:40 +00:00
蘭 83ce744fb2 feat: Adapt to internationalization (#7205) 2024-11-28 10:40:39 +00:00
zhengkunwang ae03b85a97 fix(website): Fix Issue with Switching PHP Runtime Environment (#7203)
Refs https://github.com/1Panel-dev/1Panel/issues/7097
2024-11-28 07:26:38 +00:00
ssongliu 53e91a87b0 fix(container-command): Fix the issue of container command parsing failure. (#7200) 2024-11-27 17:27:50 +08:00
ssongliu 519c6bca66 feat(cmd): Add support for internationalization of 1Panel commands (#7192) 2024-11-27 08:02:35 +00:00
John Niang f7dcacab92 Fix lint error when building frontend (#7198) 2024-11-27 16:00:43 +08:00
蘭 00c6466423 feat(alert): Add alert settings (#7196)
Refs #6357
Refs #7005
2024-11-27 07:14:33 +00:00
zhengkunwang b8d8867ebb feat(appstore): Restrict application updates based on the app's suppo… (#7174) 2024-11-25 08:18:24 +00:00
zhengkunwang 7b1d746ce7 feat(website): Optimize website error_log configuration (#7173)
Refs **https://github.com/1Panel-dev/1Panel/issues/7161**
2024-11-25 08:16:25 +00:00
igophper 7dc0a2f664 fix: 解决更新端口不更新防火墙规则的问题 (#7169) 2024-11-25 16:12:52 +08:00
zhengkunwang 52f7df0350 feat(runtime): correct typo in variable name (#7172) 2024-11-25 12:05:42 +08:00
zhengkunwang 38d1cac5d9 feat(runtime): Add .NET runtime (#7155) 2024-11-24 09:11:23 +08:00
zhengkunwang c3565f72c4 feat(system-security): Support Hot Reloading of System Certificates (#7152)
Refs https://github.com/1Panel-dev/1Panel/issues/7129
2024-11-22 09:48:13 +00:00
ssongliu 7fdb0a5078 fix: Fixed the fault in determining the firewall port forwarding version (#7150) 2024-11-22 02:16:14 +00:00
liqiang-fit2cloud ce30a7d5cd Update llm-code-review.yml 2024-11-22 10:11:16 +08:00
蘭 28597721f2 feat: Add API interface authentication function (#7146) 2024-11-21 22:09:00 +08:00
zhengkunwang c2fd02ac48 feat(system-security): Added 444 and 500 responses for unauthenticated settings (#7143) 2024-11-21 17:46:13 +08:00
ssongliu a8aa1f87f2 fix: Fixed the fault in determining the firewall port forwarding version (#7141) 2024-11-21 09:30:10 +00:00
zhengkunwang 2ba17d89ef feat(system-security): Optimized unauthenticated settings to enhance system security (#7142) 2024-11-21 16:31:07 +08:00
wanghe-fit2cloud aaae8a5d3b fix: Remove the build cache 2024-11-20 12:08:35 +08:00
wanghe-fit2cloud 5ca91157ca chore: modify question templates. 2024-11-19 18:12:11 +08:00
wanghe-fit2cloud bad1b0b105 perf: Update related workflows 2024-11-19 18:08:58 +08:00
wanghe-fit2cloud d14a149c57 Remove .vscode folder from the repository 2024-11-19 18:06:57 +08:00
吴小白 9c6c77615e build(deps): bump goreleaser from v2.4.5 to latest (#7122)
#### What this PR does / why we need it?
- https://github.com/goreleaser/goreleaser/issues/5292
- https://github.com/goreleaser/goreleaser/commit/700889269f740f659c9f3867f2b79fed677b74b0

#### 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.
2024-11-19 03:56:05 +00:00
吴小白 913e64bb75 perf: remove go cache (#7114)
#### 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.
2024-11-18 08:02:03 +00:00
蘭 fd8ef545e8 style: 主题样式优化 (#7113) 2024-11-18 07:42:03 +00:00
ssongliu d068cc40f0 fix: 修改未激活状态下信息内容 (#7112) 2024-11-18 06:58:03 +00:00
ssongliu ee0e17a496 fix: 解决数据库切换版本不正确的问题 (#7111) 2024-11-18 06:16:04 +00:00
吴小白 f1afc0f4d9 build(deps): bump goreleaser from v2 to v2.4.5 (#7110)
#### 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.
2024-11-18 06:14:03 +00:00
吴小白 ea1afe7610 build(deps): bump golang from 1.22 to 1.23 (#7109) 2024-11-18 11:33:25 +08:00
ssongliu 4ade175a3d fix: 统一 xpack 失联接口返回内容 (#7106) 2024-11-18 02:30:03 +00:00
igophper c6ea06153a fix: 解决编辑端口规则不能保存的问题 (#7100) 2024-11-17 22:52:02 +08:00
ssongliu eb36a0f8cb fix: 优化许可证错误信息 (#7094) 2024-11-16 13:00:02 +00:00
ssongliu 3087c1a6e8 fix: 完善 license 同步失联逻辑 (#7090) 2024-11-15 15:22:01 +00:00
蘭 e5b0a1c591 feat: Echarts 组件适配主题颜色 (#7087) 2024-11-15 20:14:34 +08:00
igophper af41e8e429 feat: 增加DNS服务商CloudDNS (#7081)
Refs #7038
2024-11-15 16:46:45 +08:00
蘭 7e677ee9fa fix: 获取告警短信使用量 (#7077) 2024-11-15 08:06:02 +00:00
蘭 eea4cf68ad fix: 修复许可证失效主题切换错误问题 (#7075) 2024-11-15 07:24:01 +00:00
刘瑞斌 3a400dd15a feat: 增加火山引擎DNS (#7006) 2024-11-15 11:27:41 +08:00
maninhill fbbbd52d72 chore: Update README_EN.md 2024-11-15 06:58:19 +08:00
maninhill 27664c7dce chore: Update README.md 2024-11-14 22:56:36 +08:00
蘭 e1bdd215b1 fix: 编辑计划任务和病毒扫描告警问题处理 (#7058) 2024-11-14 21:52:37 +08:00
蘭 d04a35565e feat: 主题样式优化 (#7053) 2024-11-14 09:32:01 +00:00
蘭 7aad2cf4af fix: 客户端缓存导致界面设置 Logo 不能正常显示 (#7048)
Refs #7020
2024-11-14 08:18:02 +00:00
蘭 bfa667584a fix: 编辑计划任务和病毒扫描告警问题处理 (#7047)
Refs #7039
2024-11-14 16:15:47 +08:00
ssongliu 1858cb4df8 fix: 导入恢复限制文件数量 (#7045) 2024-11-14 06:20:01 +00:00
ssongliu dc30a3d1c3 fix: 解决 vue 组件未兼容繁体的问题 (#7044)
Refs #7033
2024-11-14 06:18:02 +00:00
蘭 6e690cc6f2 style: 主题样式优化 (#7037) 2024-11-13 14:16:01 +00:00
蘭 911b4076f5 feat: 主题色保存/恢复增加确认提示 (#7036) 2024-11-13 14:14:01 +00:00
蘭 4c01b1e542 fix: 删除目录校验 (#7035) 2024-11-13 14:12:01 +00:00
蘭 ec372dbb98 fix: 删除目录校验是否为禁止删除的目录 (#7031) 2024-11-13 07:10:00 +00:00
蘭 0b87025c52 feat: 面板目录禁止删除 (#7029)
Refs #7008
2024-11-13 06:52:02 +00:00
蘭 7d4230ecfb fix: 关闭代理同时更新 Docker 代理 (#7028) 2024-11-13 06:50:00 +00:00
ssongliu d06583773a fix: 优化概览页磁盘显示 (#7023) 2024-11-13 06:46:01 +00:00
ssongliu 67c1fbd07a fix: 优化登陆页面特征信息 (#7027)
Refs #7000
2024-11-13 06:44:00 +00:00
蘭 5c7fab8f01 style: 面板样式优化 (#7026) 2024-11-13 06:30:00 +00:00
ssongliu 06554375cb fix: 修改面板证书显示域名信息 (#7019) 2024-11-12 23:04:00 +08:00
蘭 e65329e7b3 perf: 优化 docker 代理 (#7016) 2024-11-12 11:18:00 +00:00
蘭 f5435c581b perf: 优化主题色及样式 (#7015) 2024-11-12 10:32:00 +00:00
ssongliu 5e8b23db6a fix: 快照恢复忽略应用恢复失败问题 (#7012) 2024-11-12 17:34:23 +08:00
蘭 f2849aa6ec perf: 优化主题色及样式 (#7009) 2024-11-12 13:48:49 +08:00
Xiao TanandBH1XAQ ee947b6468 fix: 修复 pure-ftpd 上传缓慢问题 (#6994)
* fix: 修复 pure-ftpd 上传缓慢问题

* fix: 修复 pure-ftpd 修改密码用户名的判断依据

---------

Co-authored-by: BH1XAQ <tanxiao@16iot.cn>
2024-11-12 09:27:21 +08:00
蘭 49c072b40d perf: 优化主题色及样式 (#7002) 2024-11-11 22:46:27 +08:00
蘭 204f9f1fbc feat: 面板代理服务器提供 docker 代理 (#6986) 2024-11-08 18:19:48 +08:00
zhengkunwang cccbaafd1b feat: 修改应用安装超时时间 (#6983) 2024-11-08 06:55:21 +00:00
BugKing 7bc06bb6b1 docs: Update README.md 2024-11-08 09:25:05 +08:00
BugKing c16d5190c6 docs: Update README.md
增加专业版简要说明。
2024-11-08 09:25:05 +08:00
蘭 ffdd9b9d79 feat: 增加自定义主题颜色,调整默认暗色主题配色 (#6964) 2024-11-06 09:39:20 +00:00
ssongliu 8d35c54672 fix: 优化防火墙端口转发错误信息 (#6967) 2024-11-06 08:31:19 +00:00
ssongliu eb0164907c fix: 解决面板证书信息获取失败的问题 (#6962)
Refs #6863
2024-11-06 06:37:19 +00:00
wanghe 478d44885c Update OWNERS (#6963) 2024-11-06 14:33:34 +08:00
dependabot[bot] 541bc456be build(deps): bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 (#6959)
Bumps [github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md)
- [Commits](https://github.com/golang-jwt/jwt/compare/v4.5.0...v4.5.1)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt/v4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-06 10:22:52 +08:00
liqiang-fit2cloud 5ce75992a3 Update llm-code-review.yml 2024-11-05 14:57:12 +08:00
蘭 c8b3ba7f6c style: 组件样式调整 (#6943) 2024-11-04 10:50:53 +00:00
liqiang-fit2cloud d92ce86bb8 build: add code review action. 2024-11-04 17:59:28 +08:00
ssongliu f7b4c8cd28 fix: 优化容器创建提示信息 (#6925) 2024-11-01 14:27:10 +00:00
YaKun9 24c063b106 feat: 概览-状态,磁盘数量多过时默认收起 (#6918)
Refs https://github.com/1Panel-dev/1Panel/issues/6917
feat: 概览-状态,磁盘数量多过时默认收起
2024-11-01 14:25:10 +00:00
igophper e478d2e624 fix: 解决清空网站日志时的闪烁问题 (#6905)
Refs #6904
2024-10-31 10:19:36 +08:00
ssongliu dc0f726029 fix: 解决操作日志打印错误的问题 (#6899) 2024-10-30 17:02:19 +08:00
ssongliu 784b8da7af fix: 解决远程数据库无法切换的问题 (#6893)
Refs #6883
2024-10-30 08:14:41 +00:00
ssongliu 79e9dc9914 fix: 解决全屏切换直接关闭后菜单不显示的问题 (#6894)
Refs #6889
2024-10-30 08:12:39 +00:00
wanghe 4849c6b42d Update README.md 2024-10-30 13:51:35 +08:00
wanghe 024d142c8d Update README.md 2024-10-28 15:58:12 +08:00
ssongliu 126aea931c fix: 解决容器编排路径为空时无法删除的问题 (#6862) 2024-10-27 15:18:02 +00:00
ssongliu 2372281d5e fix: 解决容器镜像仓库编辑失败的问题 (#6845)
Refs #6839
2024-10-25 14:11:55 +00:00
ssongliu 376d6609f2 fix: 补全进程守护 watch 引用 (#6836) 2024-10-24 15:00:18 +08:00
ssongliu 96ab4c53af fix: 解决计划任务告警误报的问题 (#6825) 2024-10-23 14:08:19 +00:00
ssongliu 96cf46d834 fix: 解决低版本 dockerd 命令不兼容的问题 (#6824) 2024-10-23 10:34:19 +00:00
ssongliu 208414704d style: 容器样式调整 (#6822)
Refs #6819
2024-10-23 09:32:19 +00:00
zhengkunwang 7f453aa145 feat: 启动运行环境增加默认网络检测 (#6820) 2024-10-23 09:08:20 +00:00
蘭 123997fa13 feat: 面板重启导致计划任务失败时进行短信告警 (#6817) 2024-10-23 03:46:19 +00:00
zhengkunwang 7faef2f8a7 feat: 创建运行环境网站增加 Python 选项 (#6815) 2024-10-23 02:52:16 +00:00
ssongliu f93cf3b996 fix: 解决快照列表排序的问题 (#6816)
Refs #6810
2024-10-23 02:46:17 +00:00
zhengkunwang df5b69756c feat: 创建运行环境网站增加默认网络创建 (#6807) 2024-10-22 11:24:34 +00:00
蘭 745bb98abe fix: 完善短信告警国际化 (#6806) 2024-10-22 11:20:32 +00:00
ssongliu cf1d02771f fix: 解决 Docker 重启失败的问题 (#6805) 2024-10-22 09:42:28 +00:00
zhengkunwang 52377b0042 fix: 解决 Python 运行环境编辑报错的问题 (#6801) 2024-10-22 08:10:28 +00:00
蘭 270501a237 fix: 文件夹选择控件,选择文件时不默认选择当前目录 (#6799)
Refs #6012
2024-10-22 07:40:29 +00:00
zhengkunwang 2e5283b8d3 fix: 解决 Mysql 特定版本忽略升级失效的问题 (#6800)
Refs https://github.com/1Panel-dev/1Panel/issues/6796
2024-10-22 07:34:29 +00:00
ssongliu 8cad47b29e feat: 修改容器操作超时时间 (#6798)
Refs #6747
2024-10-22 07:20:28 +00:00
Ludovic Fernandez 2458d60d80 fix: otel dependencies (#6793) 2024-10-22 07:39:07 +08:00
ssongliu 9a79dc4cdd feat: SSL 配置增加重启选项 (#6792) 2024-10-21 22:47:14 +08:00
Ludovic Fernandez e531b509d6 fix: huawei cloud (#6791) 2024-10-21 22:15:32 +08:00
蘭 d287fc1186 fix: 解析病毒扫描内容格式处理 (#6790) 2024-10-21 14:06:20 +00:00
zhengkunwang f47f7c7361 fix: 解决创建运行环境报名称存在的问题 (#6785) 2024-10-21 08:50:22 +00:00
zhengkunwang 7a6c99d57d fix: 解决证书自动续签日志报错的问题 (#6784) 2024-10-21 07:10:20 +00:00
zhengkunwang 5105114321 fix: 解决网站开启 HTTPS 之后 404 配置丢失的问题 (#6775) 2024-10-18 09:17:38 +00:00
zhengkunwang 60beebcb4c style: 日志样式调整 (#6774) 2024-10-18 08:55:38 +00:00
ssongliu fa03b4226a fix: 解决容器编排跳转路径错误的问题 (#6773) 2024-10-18 08:43:37 +00:00
蘭 b047a053c5 fix: 解决移动端主机文件批量删除错误 (#6765) 2024-10-18 03:29:36 +00:00
ssongliu 42907cd228 feat: postgresql 远程数据库支持 17.x 版本 (#6759) 2024-10-17 13:37:32 +00:00
蘭 425892cfc4 refactor: 调整包引用 (#6758) 2024-10-17 13:35:32 +00:00
ssongliu 16fd804e93 feat: 优化数据库切换效果 (#6757)
Refs #6755
2024-10-17 10:05:32 +00:00
John Bro 2f147dde13 fix: 容器部分操作动态修改执行命令 (#6750)
Refs #3242
2024-10-17 10:03:31 +00:00
蘭 0d04f07f2a fix: Switch 组件 small 尺寸样式修复 (#6752) 2024-10-17 07:31:30 +00:00
蘭 96485218b7 feat: 病毒扫描定时扫描和短信告警合并提示许可证绑定 (#6751) 2024-10-17 07:29:31 +00:00
蘭 227cc57426 feat: 计划任务失败告警支持全类型告警 (#6749) 2024-10-17 07:27:31 +00:00
zhengkunwang b99061777a feat: PHP 镜像 build 增加超时时间 (#6744) 2024-10-17 04:13:30 +00:00
zhengkunwang 8749dc649a style: 优化一些样式 (#6740) 2024-10-16 09:37:27 +00:00
zhengkunwang 65da51a478 style: 优化应用升级文件对比样式 (#6733) 2024-10-16 04:07:26 +00:00
蘭 0c31ba1c5f feat: 文件夹选择控件,默认选中当前目录 (#6720)
Refs #6012
2024-10-15 10:21:22 +00:00
蘭 acf94b052b feat: 增加病毒扫描和计划任务告警 (#6709) 2024-10-14 09:51:17 +00:00
蘭 556441d811 style: 解决 Alert 提示组件标题存在链接时文字错位问题 (#6711) 2024-10-14 09:41:17 +00:00
zhengkunwang efcf17e47c style: 优化登录页软件许可协议提示语样式 (#6712) 2024-10-14 09:31:18 +00:00
zhengkunwang 02b7744995 pref: 优化网站日志读取 (#6710)
Refs https://github.com/1Panel-dev/1Panel/issues/6642
2024-10-14 09:29:17 +00:00
ssongliu c86947b69c style: 修改按钮组边框宽度不一致的问题 (#6706)
Refs #6704
2024-10-14 06:41:16 +00:00
ssongliu 839b8c2844 feat: 修改容器列表应用商店容器默认显示 (#6705) 2024-10-14 06:29:16 +00:00
John Bro e4a634e6e8 fix: 容器重启前增加校验操作 (#6696) 2024-10-14 10:36:55 +08:00
wild_pointer eb99c10ad0 fix: 修复“修改文件权限时,文件所属用户和用户组不显示”问题 (#6698) 2024-10-14 10:24:48 +08:00
zzzandzengzz01 175b7b89e4 feat:firewalld和ufw同时存在时,不进行操作 (#6688)
Co-authored-by: zengzz01 <zengzz01@mingyuanyun.com>
2024-10-11 18:03:33 +08:00
zhengkunwang 5374afb226 feat: 增加华为云申请证书 (#6687)
Refs https://github.com/1Panel-dev/1Panel/issues/6047
2024-10-11 06:41:05 +00:00
John Bro 1a44f48fad fix: 日志查看统一改成网页全屏以及样式调整 (#6682)
Refs #5873
2024-10-10 10:55:02 +00:00
zhengkunwang 50dbe7cfc0 feat: 增加 Python 运行环境 (#6681) 2024-10-10 18:49:13 +08:00
ssongliu c7e576c879 fix: 概览页磁盘显示排除 overlay 类型 (#6672)
Refs #6637
2024-10-10 03:07:00 +00:00
ssongliu a3e4847744 feat: 快照列表改为异步获取大小 (#6670)
Refs #6540
2024-10-10 03:05:00 +00:00
ssongliu 903f8ed5a7 feat: 容器列表缓存是否显示应用商店容器 (#6667)
Refs #5885
2024-10-10 02:38:59 +00:00
zhengkunwang b091c7f364 feat: 反向代理文本替换增加 sub_filter_types 参数 (#6661)
Refs https://github.com/1Panel-dev/1Panel/issues/6490
2024-10-09 07:02:56 +00:00
zhengkunwang e069db3c45 feat: 反代回源 SNI 支持设置 proxy_ssl_name (#6659)
Refs https://github.com/1Panel-dev/1Panel/issues/5960
2024-10-09 06:42:56 +00:00
see-more 047264dbbc chore;删除error_code组件的body标签 (#6656) 2024-10-09 10:24:47 +08:00
ssongliu 0c216ba87a feat: 支持离线版许可证 (#6651) 2024-10-08 13:56:55 +00:00
ssongliu 31cdc28143 fix: 修改上传恢复提示信息 (#6647) 2024-10-08 02:58:52 +00:00
zhengkunwang e03b728240 feat: 自签证书支持 ipv6 (#6627)
Refs https://github.com/1Panel-dev/1Panel/issues/6623
2024-09-29 10:25:47 +00:00
ssongliu 4c275ba52f style: 修改许可证即将过期样式 (#6616) 2024-09-29 06:37:45 +00:00
ssongliu 2ac9a888a8 feat: 移除编排删除后跳转 (#6613) 2024-09-29 02:15:45 +00:00
Anye f9bdcf8938 feat: 新增 BookStack 的 PHP 扩展模板 (#6611) 2024-09-29 10:01:55 +08:00
ssongliu c3bef26ae6 feat: 调整编排删除逻辑 (#6610) 2024-09-28 22:29:08 +08:00
ssongliu 634849c347 feat: Compose 环境变量编辑增加是否 1Panel 创建校验 (#6605) 2024-09-28 01:37:40 +00:00
John Bro c557b737f6 fix: 重构容器编排环境变量设置逻辑 (#6600) 2024-09-27 14:25:37 +00:00
zhengkunwang 1d326afa93 feat: 优化日志加载 (#6593) 2024-09-26 14:37:32 +00:00
wanghe-fit2cloud cb6c58cb5d Revert "style:优化概览界面的布局 (#6491)"
This reverts commit 7f06c7e92e.
2024-09-25 10:24:33 +08:00
John Bro ec4d708569 feat: 容器编排列表增加编排目录并支持跳转 (#6565)
Refs #3579
2024-09-24 14:25:23 +00:00
John Bro 05b19cefa5 feat: 容器日志下载只支持全量下载 (#6559)
Refs #2399
2024-09-24 14:23:24 +00:00
John Broandzhoujunhong fdd57d0801 feat: 容器编排及模板列表支持排序 (#6566)
Co-authored-by: zhoujunhong <1298308460@qq.com>
2024-09-24 22:21:28 +08:00
Kataick c16d6d1644 flx: 修复会默认出现水平滚动条的问题 (#6564) 2024-09-24 16:01:05 +08:00
John Bro 656b39c880 fix: 添加国际化及样式修改 (#6555) 2024-09-23 10:11:14 +00:00
John Bro 753c996291 fix: 编排模板列表日期格式化 (#6551) 2024-09-23 06:33:15 +00:00
ssongliu dcdd0cc2bb fix: 解决服务包含 .socket 时起停失败的问题 (#6553)
Refs #6524
2024-09-23 06:31:14 +00:00
ssongliu 2f32df16d9 fix: 解决部分浏览器无法打开文件菜单的问题 (#6537) 2024-09-19 10:56:55 +00:00
John Bro 9caa9c47b4 feat: 容器编排显示容器状态,编排模板样式优化 (#6534)
Refs #4404
2024-09-19 10:54:56 +00:00
蘭 55bec8a911 fix: 解决图片/视频预览时,重命名文件名导致浏览器缓存文件内容问题 (#6533)
Refs #6505
2024-09-19 06:00:54 +00:00
John Bro 43f95fd40e fix: 创建和编辑 compose 文件支持设置环境变量 (#6503) 2024-09-18 06:00:49 +00:00
Anye 641812e7c1 fix: 调整Logo长宽比,防止显示被拉伸 (#6510)
* fix: 调整Logo长宽比,防止显示被拉伸
2024-09-17 12:52:58 +08:00
zhengkunwang 95d3e75425 feat: demo 环境增加首页状态接口过滤 (#6498) 2024-09-14 10:12:32 +00:00
see-more 7f06c7e92e style:优化概览界面的布局 (#6491)
* fix: <body> cannot be child of <div>

* style:优化概览界面的布局
2024-09-14 13:43:52 +08:00
ssongliu 0e6fdffeec feat: S3 备份账号支持 Path Style (#6489)
Refs #4553
2024-09-13 10:42:27 +00:00
endymx f77681b9c9 feat(ssl证书): 实现华为云dns (#6407) 2024-09-13 10:53:06 +08:00
John Bro 535d4bbe1b fix: 删除容器后 compose 记录保存以便后续处理 (#6447)
Refs https://github.com/1Panel-dev/1Panel/issues/5099
2024-09-12 10:06:22 +00:00
zhengkunwang 1dfbca3d5b feat: 删除多余代码 (#6463) 2024-09-11 23:10:15 +08:00
zhengkunwang d2ca265cc2 perf: 优化首页加载速度 (#6461) 2024-09-11 14:12:16 +00:00
ssongliu fc70345fcd fix: 优化移动端运行时样式 (#6460) 2024-09-11 22:02:11 +08:00
ssongliu 6ae9b982a9 fix: 优化移动端样式 (#6455) 2024-09-11 10:22:15 +00:00
蘭 0122b4c6ce fix: 解决主机文件压缩解压特殊字符问题 (#6451) 2024-09-11 08:20:15 +00:00
ssongliu 08c0faa20e feat: 优化概览页内存单位 (#6450) 2024-09-11 07:38:15 +00:00
ssongliu ab7efea8c5 style: 优化移动端样式 (#6448) 2024-09-11 07:24:15 +00:00
zhengkunwang f4623664d5 feat: 日志页面增加加载状态 (#6446) 2024-09-11 03:48:14 +00:00
ssongliu df147435c5 fix: 移除重复样式 (#6445) 2024-09-11 03:16:14 +00:00
see-more 71c1c5ae83 style:优化设置移动端界面 (#6443)
* style:优化设置移动端界面

* style:设置-安全界面样式

* style:修复设置-备份账号服务器磁盘移动端无法剧中

* style:优化移动端设置界面
2024-09-11 10:30:46 +08:00
see-more 0ea142d6db style:优化日志审计页面样式 (#6441) 2024-09-11 10:16:02 +08:00
ssongliu f88a3059be fix: 修改移动端样式 (#6440) 2024-09-10 14:04:12 +00:00
蘭 48281ddf86 fix: 主机文件解压文件 mimetype 类型增加 (#6437) 2024-09-10 14:02:11 +00:00
zhengkunwang 7cdcf9b757 feat: 增加 Intel Arc 显卡 适配 (#6435) 2024-09-10 18:55:29 +08:00
ssongliu ef0bb12fbd fix: 处理代码格式问题 (#6433) 2024-09-10 07:40:09 +00:00
蘭 a0857f86b2 fix: 主机文件打开软链接优化 (#6432) 2024-09-10 07:26:10 +00:00
wangdan-fit2cloud 2219b3f47b perf: 优化工具栏样式 (#6431)
#### 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.
2024-09-10 07:18:10 +00:00
蘭 b6c873f22d fix: 主机文件的路径栏路径 Bug 解决 (#6428)
Refs #6310
2024-09-10 03:46:08 +00:00
蘭 64bc92a7fd fix: 限制二进制文件解压的类型 (#6425)
Refs #6113
2024-09-10 02:14:08 +00:00
ssongliu 6c4c0f7595 fix: 解决服务器重启按钮被遮住的样式问题 (#6424) 2024-09-09 22:56:14 +08:00
蘭 2d9c977805 fix: 解决文件编辑器行号问题 (#6423)
Refs #5918

升级了编辑器版本,调整了编辑器的主题,需要整体测试一下编辑器的样式!
2024-09-09 10:08:04 +00:00
ssongliu dff0375848 fix: 解决容器端口的显示问题 (#6417) 2024-09-09 07:26:04 +00:00
ssongliu ab825a1a70 feat: 防火墙操作支持 ipv6 网段 (#6415) 2024-09-09 11:19:29 +08:00
Anye 466617847f fix: 创建CA机构生成的应为证书而非证书签名请求 (#6404) 2024-09-07 21:56:38 +08:00
蘭 a53fff2416 fix: 解决软连接被识别为文件问题 (#6400)
Refs #5879
2024-09-06 09:37:52 +00:00
zhengkunwang dd1430dbbf feat: 反向代理配置文件统一 (#6396)
Refs https://github.com/1Panel-dev/1Panel/issues/6395
2024-09-06 06:33:50 +00:00
蘭 5aad16968b perf: 优化文件管理器终端命令 (#6393)
Refs #5891
2024-09-06 03:51:50 +00:00
see-more f2d3acb650 style:更新所有移动端container路径下样式 (#6387)
* style:更新所有移动端container路径下样式

* style:修复el-button的默认margin
2024-09-06 10:00:53 +08:00
see-more 666f8c813d style:移动端文件页面样式和防火墙页面样式 (#6386)
* style:移动端端文件页面样式

* style:修改防火墙页面样式

* style:手机端ssl界面和数据库界面调整
2024-09-06 10:00:39 +08:00
ssongliu e87fb7b50e fix: 备份账号 bucket 支持手动输入 (#6381)
Refs #6378
2024-09-05 13:53:48 +00:00
蘭 75612879c7 fix: 解决部分情况下缓存目录导致启动失败的问题 (#6382) 2024-09-05 09:23:47 +00:00
蘭 94e0c80d47 refactor: 调整主机监控任务时间为整分钟执行 (#6379) 2024-09-05 08:41:48 +00:00
蘭 feb6f4cbe0 fix: 概览页获取 CPU 精度问题 (#6380)
Refs #6309
2024-09-05 08:39:48 +00:00
ssongliu 1173bbf628 fix: 解决备份恢复弹窗打开后无法关闭的问题 (#6376)
Refs #6355
2024-09-05 07:11:48 +00:00
ssongliu 1cdc2e93ad fix: 解决 FreshClam 操作失败的问题 (#6374)
Refs #6372
2024-09-05 07:09:46 +00:00
see-more 3356bd8825 fix:移动端网站页面和数据库页面样式 (#6360)
* fix:移动端网站页面和数据库页面样式

* style:修改database页面样式

* style:修改databse页面手机端搜索框与按钮间距
2024-09-05 11:46:57 +08:00
ssongliu decc7a4a1e fix: 解决停止状态容器端口获取不正确的问题 (#6370)
Refs #6333
2024-09-05 03:45:46 +00:00
zhengkunwang a397cab61c fix: 解决部分情况下缓存目录导致启动失败的问题 (#6364)
Refs https://github.com/1Panel-dev/1Panel/issues/6362
2024-09-04 09:21:43 +00:00
trom 228e3d9ae3 style:优化container界面的布局 (#6348) 2024-09-03 13:46:37 +08:00
zhengkunwang 051f670453 fix: 修复域名删除导致网站访问被 WAF 拦截的问题 (#6337)
Refs https://github.com/1Panel-dev/1Panel/issues/6336
2024-09-02 10:23:37 +00:00
trom cf8aa86a67 fix:修复文件路径bug (#6313)
* fix:修复文件路径bug

* fix:修改文件路径逻辑
2024-09-02 10:35:32 +08:00
ssongliu 5b00286e65 fix: 修改 PostgreSQL 容器内部端口 (#6275)
Refs #6274
2024-08-28 08:45:22 +00:00
ssongliu 6597caaf05 fix: 解决快照套接字忽略失败的问题 (#6273) 2024-08-28 06:41:22 +00:00
ssongliu 5851124dee fix: 解决备份套接字忽略不完的问题 (#6272) 2024-08-28 05:45:22 +00:00
trom b18689a0d6 feat:显示当前ip,系统网络代理地址 (#6251) 2024-08-27 13:39:36 +08:00
蘭 a5e7f78a1f pref: 完善告警通知任务 (#6263) 2024-08-27 13:39:18 +08:00
ssongliu a1d394fbc2 fix: 解决容器端口范围太大时,编辑打开失败的问题 (#6249)
Refs #6245
2024-08-26 08:07:13 +00:00
wanghe-fit2cloud 5e82bda666 Revert commit 3d5580a: feat:显示当前ip,系统网络代理地址 2024-08-26 15:55:07 +08:00
trom 3d5580ad9d feat:显示当前ip,系统网络代理地址 (#6235) 2024-08-26 11:25:03 +08:00
ssongliu c83cfbe8b0 fix: 解决备份导入失败的问题 (#6228) 2024-08-23 14:58:59 +00:00
蘭 00cc1b62ef pref: 完善告警通知 (#6227) 2024-08-23 13:53:00 +00:00
ssongliu e782f75863 fix: 解决容器配置修改后未重启的问题 (#6225)
Refs #6226
2024-08-23 10:24:58 +00:00
zhengkunwang f5f379465f feat: 创建运行环境网站,校验 PHP 镜像是否存在 (#6220) 2024-08-23 09:37:00 +00:00
ssongliu 70a8fda449 feat: 优化数据库备份页面样式 (#6221) 2024-08-23 17:36:21 +08:00
ssongliu ca14302191 fix: 优化部分频繁打印的日志操作 (#6219) 2024-08-23 06:40:58 +00:00
ssongliu 7297c2626f fix: 优化防火墙启动时自动添加端口功能 (#6216)
Refs #6215
2024-08-23 03:54:57 +00:00
蘭 92a3982f21 feat: 告警通知功能完善 (#6211) 2024-08-22 14:22:56 +00:00
蘭 626f5efdcd style: 优化 switch 组件 small 尺寸样式 (#6210) 2024-08-22 14:20:55 +00:00
ssongliu 24e780b984 fix: 压缩增加 *.socket 排除规则 (#6196) 2024-08-21 07:12:50 +00:00
zhengkunwang 596d4aceb6 fix: 解决删除 PHP 运行环境之后,删除其他网站提示错误的问题 (#6192) 2024-08-21 02:50:50 +00:00
蘭 e770254b65 feat: 增加短信告警功能 (#6184) 2024-08-20 22:11:13 +08:00
wanghe-fit2cloud 7901c26d32 feat: 修改 snapshot 参数 2024-08-20 18:47:49 +08:00
zhengkunwang fc65f8f689 feat: 修复代码警告 (#6190) 2024-08-20 10:36:47 +00:00
zhengkunwang e0a5e14978 feat: 修改非 PHP 运行环境网站的删除提示 (#6189) 2024-08-20 09:42:47 +00:00
zhengkunwang 07562c203a feat: 优化已安装应用的参数显示 (#6188) 2024-08-20 09:40:48 +00:00
ssongliu 8187a19e6e fix: 修改版本号复制方式 (#6187) 2024-08-20 09:38:47 +00:00
zhengkunwang 32cd684307 fix: 解决路由菜单文字丢失的问题 (#6185) 2024-08-20 06:46:46 +00:00
ssongliu 3a72fc95d9 style: 处理代码警告 (#6183) 2024-08-20 03:38:47 +00:00
ssongliu 64405fba3d fix: 统一时区获取方法 (#6175) 2024-08-19 10:30:42 +00:00
zhengkunwang cc7981229c fix: 解决 redis 没有密码情况下安装应用没有关联的问题 (#6173)
Refs #6174
2024-08-19 10:06:42 +00:00
zhengkunwang 3ec208dc85 perf: 优化运行环境日志卡顿情况 (#6172) 2024-08-19 10:04:43 +00:00
ssongliu 1b92b6cbfa fix: mysql 绑定用户增加输入校验 (#6149) 2024-08-16 06:00:31 +00:00
trom 779addfcb4 fix:mysql升级到8.4后查询会出错,容器的command回显使用 text area (#6147)
* style:容器的command参数回显应该使用 text area而不是text input,且不应该过滤'\n'

* chore:prettier格式化

* fix:mysql升级到8.4后,数据库管理 - 当前状态 查询会出错

* chore:修改逻辑判断
2024-08-16 11:23:44 +08:00
ssongliu 7da5f7a884 fix: 修改镜像拉取校验规则 (#6145)
Refs #5740
2024-08-15 15:18:32 +00:00
ssongliu 34e14636d4 fix: 解决 ClamAV 卸载后定时任务无法停止的问题 (#6143)
Refs #6100
2024-08-15 15:16:30 +00:00
ssongliu aa222aac31 fix: 解决计划任务备份内容允许为空的校验问题 (#6142)
Refs #6099
2024-08-15 09:42:28 +00:00
zhengkunwang 5134caa103 fix: 解决部分应用参数数据库显示错误的问题 (#6136) 2024-08-15 07:12:28 +00:00
zhengkunwang dca3c92d72 fix: 解决 PHP 运行环境版本过期之后下载安装包失败的问题 (#6125) 2024-08-14 10:29:59 +00:00
zhengkunwang a85d5bad46 feat: 优化 mysql 版本升级 (#6119) 2024-08-13 10:48:56 +00:00
zhengkunwang 716613a4db feat: 应用升级备份保留 3 份 (#6116)
Refs https://github.com/1Panel-dev/1Panel/issues/6107
2024-08-13 07:28:55 +00:00
zhengkunwang 12eaa66bc5 style: 去掉应用列表中的更新应用列表按钮 (#6105) 2024-08-12 18:40:10 +08:00
zhengkunwang a6af97e3c1 style: 优化文件属性页面显示 (#6104)
Refs https://github.com/1Panel-dev/1Panel/issues/5855
2024-08-12 10:02:53 +00:00
zhengkunwang d561c86c68 feat: 优化网站日志在每行数据量大情况下的读取 (#6103)
Refs https://github.com/1Panel-dev/1Panel/issues/6102
2024-08-12 09:58:52 +00:00
dependabot[bot] f243d1c9b4 chore(deps): bump github.com/docker/docker (#6093) 2024-08-12 13:43:47 +08:00
trom 1cc2cc6400 feat:更新应用列表上移 #6035 (#6084) 2024-08-12 10:26:16 +08:00
trom 15f4c05772 chore:点击复制版本号(#5894) (#6077) 2024-08-09 18:25:53 +08:00
trom c9a204b7a7 fix: 搜索框加长(#6063) 回收站时间排序(#5957) hoer状态撑高界面(#5929) (#6070) 2024-08-09 10:22:29 +08:00
trom 3d0018c0bd chore:新建文件夹支持添加空格,登录页鼠标悬浮样式 (#6058) 2024-08-08 10:27:06 +08:00
zhengkunwang d639e46bc7 fix: 解决 PHP 运行环境网站删除之后没有删除应用的问题 (#6036) 2024-08-06 03:34:29 +00:00
dependabot[bot] fa633bf419 chore(deps): bump github.com/docker/docker (#5989)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.0.2+incompatible to 26.1.4+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v26.0.2...v26.1.4)

---
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>
2024-07-31 19:05:05 +08:00
zhengkunwang 40f7ef90b3 feat: 修改反向代理默认 Connection 请求头 (#5951)
Refs https://github.com/1Panel-dev/1Panel/issues/5937
2024-07-26 07:01:40 +00:00
zhengkunwang 50efe607d4 feat: 优化泛域名申请证书手动解析值 (#5950)
Refs https://github.com/1Panel-dev/1Panel/issues/4609
2024-07-26 06:59:40 +00:00
igophper 3b057f2c27 feat: 2FA支持前一个验证码 (#5942)
Refs #5940
2024-07-26 11:15:53 +08:00
maninhill d3d018bd44 chore: Update README.md 2024-07-24 17:01:38 +08:00
maninhill 1378609aa2 chore: Update README.md 2024-07-24 16:58:59 +08:00
zhengkunwang 001c896eed fix: 解决上传文件夹权限没改的问题 (#5919) 2024-07-23 17:52:30 +08:00
ssongliu 1cf3a0143c fix: 解决系统日志解析错误的问题 (#5917) 2024-07-23 07:57:32 +00:00
zhengkunwang f04be521e5 feat: 回滚代码 (#5914) 2024-07-23 14:42:06 +08:00
ssongliu 2873632a40 pref: 移除部分废弃代码 (#5910) 2024-07-23 02:31:32 +00:00
zhengkunwang 075879b5b5 fix: 解决应用商店 Go 和 Java 安装跳转错误的问题 (#5909)
Refs https://github.com/1Panel-dev/1Panel/issues/5900
2024-07-23 02:29:32 +00:00
zhengkunwang 9b12930376 fix: 解决安装 gitea 跳转到 postgres 报错的问题 (#5908)
Refs https://github.com/1Panel-dev/1Panel/issues/5902
2024-07-23 02:27:31 +00:00
zhengkunwang 3339ba9bad fix: 解决潜在的 SQL 注入漏洞 (#5906)
影响范围:操作日志
2024-07-22 14:41:31 +00:00
zhengkunwang 68922676fc fix: 解决从网站上传的证书状态显示异常的问题 (#5869)
Refs https://github.com/1Panel-dev/1Panel/issues/5867
2024-07-19 07:41:28 +00:00
zhengkunwang dcf2afb4a6 feat: 上传文件使用父目录用户和用户组 (#5868)
Refs https://github.com/1Panel-dev/1Panel/issues/5866
2024-07-19 07:33:28 +00:00
ssongliu 16a35141dd fix: 解决病毒定时扫描校验国际化的问题 (#5856) 2024-07-18 03:27:28 +00:00
John Bro f6c334bdad feat: 计划任务备份应用/网站/数据库支持多选 (#5849) 2024-07-17 13:35:27 +00:00
蘭 cbb119117b fix: 多个文件同时计算大小,计算状态独自显示 (#5851) 2024-07-17 11:09:30 +00:00
ssongliu cae0a6118f pref: 优化远程数据库解绑提示信息 (#5850) 2024-07-17 09:53:28 +00:00
1451 changed files with 134680 additions and 194296 deletions
+1 -1
View File
@@ -47,4 +47,4 @@ body:
- type: textarea
attributes:
label: "Additional Information"
description: "If you have any additional information to provide, you can include it here (screenshots, videos, etc., are welcome)."
description: "If you have any additional information to provide, you can include it here (screenshots, videos, etc., are welcome)."
+1 -1
View File
@@ -2,4 +2,4 @@ blank_issues_enabled: false
contact_links:
- name: Questions & Discussions
url: https://github.com/1Panel-dev/1Panel/discussions
about: Raise questions about the installation, deployment, use and other aspects of the project.
about: Raise questions about the installation, deployment, use and other aspects of the project.
-1
View File
@@ -1,4 +1,3 @@
name: General PR Handling for 1Panel
on: pull_request
permissions:
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.19.0'
node-version: '20.2'
- name: Build Web
run: |
cd frontend && npm install && npm run build:pro
@@ -44,4 +44,4 @@ jobs:
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
ossutil-version: '1.7.18'
- name: Upload Assets to OSS
run: ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir --force
run: ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir --force
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22.19.0'
node-version: '20.2'
- name: Build Web
run: |
cd frontend && npm install && npm run build:pro
@@ -42,4 +42,4 @@ jobs:
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to Cloudflare R2
run: |
rclone copy dist/ cloudflare_r2:package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --progress
rclone copy dist/ cloudflare_r2:package/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --progress
+1 -1
View File
@@ -11,4 +11,4 @@ jobs:
- uses: usthe/issues-translate-action@v2.7
with:
IS_MODIFY_TITLE: true
BOT_GITHUB_TOKEN: ${{ secrets.ISSUE_TRANSLATOR_TOKEN }}
BOT_GITHUB_TOKEN: ${{ secrets.ISSUE_TRANSLATOR_TOKEN }}
+1 -1
View File
@@ -22,4 +22,4 @@ jobs:
# max_tokens: 10000
MAX_PATCH_LENGTH: 10000
IGNORE_PATTERNS: "/node_modules,*.md,/dist,/.github"
FILE_PATTERNS: "*.java,*.go,*.py,*.vue,*.ts,*.js,*.css,*.scss,*.html"
FILE_PATTERNS: "*.java,*.go,*.py,*.vue,*.ts,*.js,*.css,*.scss,*.html"
+1 -1
View File
@@ -17,4 +17,4 @@ jobs:
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+1 -1
View File
@@ -12,4 +12,4 @@ jobs:
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
dst_token: ${{ secrets.GITEE_TOKEN }}
static_list: "1Panel"
force_update: true
force_update: true
+1 -1
View File
@@ -8,4 +8,4 @@ jobs:
- name: Checkout Actions Repository
uses: actions/checkout@v2
- name: Check spelling
uses: crate-ci/typos@master
uses: crate-ci/typos@master
+7 -21
View File
@@ -4,8 +4,7 @@
*.dll
*.so
*.dylib
build/1panel-agent
build/1panel-core
build/1panel
# Mac
.DS_Store
@@ -15,7 +14,6 @@ build/1panel-core
.vscode
*.project
*.factorypath
__debug*
# IntelliJ IDEA
.idea/*
@@ -24,7 +22,6 @@ __debug*
*.iml
*.ipr
# Test binary, built with `go test -c`
*.test
@@ -34,23 +31,15 @@ __debug*
# Dependency directories
/pkg/
backend/__debug_bin
core/cmd/server/__debug_bin
core/cmd/server/web/assets
core/cmd/server/web/monacoeditorwork
core/cmd/server/web/index.html
cmd/server/__debug_bin
cmd/server/web/assets
cmd/server/web/monacoeditorwork
cmd/server/web/index.html
frontend/auto-imports.d.ts
frontend/components.d.ts
frontend/src/xpack
agent/xpack
agent/router/entry_xpack.go
agent/server/init_xpack.go
agent/utils/xpack/xpack_xpack.go
core/xpack
core/router/entry_xpack.go
core/server/init_xpack.go
core/utils/xpack/xpack_xpack.go
xpack
backend/xpack
*_xpack.go
.history/
dist/
1pctl
@@ -60,6 +49,3 @@ quick_start.sh
cmd/server/fileList.txt
.fileList.txt
1Panel.code-workspace
core/.golangci.yml
agent/.golangci.yml
+4 -37
View File
@@ -9,12 +9,11 @@ before:
- chmod +x ./ci/script.sh
- ./ci/script.sh
- sed -i 's@ORIGINAL_VERSION=.*@ORIGINAL_VERSION=v{{ .Version }}@g' 1pctl
- go mod tidy
builds:
- id: agent
dir: agent
main: cmd/server/main.go
binary: 1panel-agent
- main: ./cmd/server/main.go
binary: 1panel
flags:
- -tags=xpack
- -trimpath
@@ -32,46 +31,14 @@ builds:
- arm
- ppc64le
- s390x
- riscv64
hooks:
post:
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
- id: core
dir: core
main: cmd/server/main.go
binary: 1panel-core
flags:
- -tags=xpack
- -trimpath
ldflags:
- -w -s
env:
- CGO_ENABLED=0
goos:
- linux
goarm:
- 7
goarch:
- amd64
- arm64
- arm
- ppc64le
- s390x
- riscv64
hooks:
post:
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
archives:
- formats: [ 'tar.gz' ]
ids: [core, agent]
name_template: "1panel-v{{ .Version }}-{{ .Os }}-{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}"
wrap_in_directory: true
files:
- 1pctl
- 1panel-core.service
- 1panel-agent.service
- 1panel.service
- install.sh
- GeoIP.mmdb
- lang/*
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

-3
View File
@@ -1,3 +0,0 @@
{
"ansible.python.interpreterPath": "/opt/homebrew/bin/python3"
}
+14 -29
View File
@@ -2,48 +2,33 @@ GOCMD=go
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOARCH=$(shell go env GOARCH)
GOOS=$(shell go env GOOS )
GOOS=$(shell go env GOOS)
BASE_PATH := $(shell pwd)
BUILD_PATH = $(BASE_PATH)/build
WEB_PATH=$(BASE_PATH)/frontend
ASSERT_PATH= $(BASE_PATH)/core/cmd/server/web/assets
CORE_PATH=$(BASE_PATH)/core
CORE_MAIN=$(CORE_PATH)/cmd/server/main.go
CORE_NAME=1panel-core
AGENT_PATH=$(BASE_PATH)/agent
AGENT_MAIN=$(AGENT_PATH)/cmd/server/main.go
AGENT_NAME=1panel-agent
SERVER_PATH=$(BASE_PATH)/backend
MAIN= $(BASE_PATH)/cmd/server/main.go
APP_NAME=1panel
ASSERT_PATH= $(BASE_PATH)/cmd/server/web/assets
clean_assets:
rm -rf $(ASSERT_PATH)
upx_bin:
upx $(BUILD_PATH)/$(CORE_NAME)
upx $(BUILD_PATH)/$(AGENT_NAME)
upx $(BUILD_PATH)/$(APP_NAME)
build_frontend:
cd $(WEB_PATH) && npm install && npm run build:pro
build_core_on_linux:
cd $(CORE_PATH) \
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
build_backend_on_linux:
cd $(SERVER_PATH) \
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(APP_NAME) $(MAIN)
build_agent_on_linux:
cd $(AGENT_PATH) \
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_backend_on_darwin:
cd $(SERVER_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(APP_NAME) $(MAIN)
build_core_on_darwin:
cd $(CORE_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
build_all: build_frontend build_backend_on_linux
build_agent_on_darwin:
cd $(AGENT_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_all: build_frontend build_core_on_linux build_agent_on_linux
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin upx_bin
build_on_local: clean_assets build_frontend build_backend_on_darwin upx_bin
+4 -2
View File
@@ -61,7 +61,9 @@ Please refer to our [documentation](https://docs.1panel.pro/quick_start/) for mo
## Pro Edition
Compared to the OSS Edition, 1Panel Pro Edition provides users with a wealth of enhanced features and technical support services. Enhanced features include WAF enhancement, website tamper protection, website monitoring, GPU monitoring, custom logo and theme color, etc. [Click to view the detailed introduction of the Pro Edition](https://1panel.pro/pricing).
Compared to the OSS Edition, 1Panel Pro Edition provides users with a wealth of enhanced features and technical support services. Enhanced features include WAF enhancement, Website monitoring, Mobile APP, custom logo and theme, etc.
[Click to see Pro Edition details](https://1panel.pro/pricing).
## Security Information
@@ -73,4 +75,4 @@ Licensed under The GNU General Public License version 3 (GPLv3) (the "License")
<https://www.gnu.org/licenses/gpl-3.0.html>
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-200
View File
@@ -1,200 +0,0 @@
package v2
import (
"errors"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
)
func (b *BaseApi) PageAlert(c *gin.Context) {
var req dto.AlertSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, alerts, err := alertService.PageAlert(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: alerts,
})
}
func (b *BaseApi) GetAlerts(c *gin.Context) {
alerts, err := alertService.GetAlerts()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, alerts)
}
func (b *BaseApi) CreateAlert(c *gin.Context) {
var req dto.AlertCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := alertService.CreateAlert(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) DeleteAlert(c *gin.Context) {
var req dto.DeleteRequest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := alertService.DeleteAlert(req.ID)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) UpdateAlert(c *gin.Context) {
var req dto.AlertUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := alertService.UpdateAlert(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) GetAlert(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, errors.New("no such id in request param"))
return
}
alert, err := alertService.GetAlert(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, alert)
}
func (b *BaseApi) UpdateAlertStatus(c *gin.Context) {
var req dto.AlertUpdateStatus
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := alertService.UpdateStatus(req.ID, req.Status); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) GetDisks(c *gin.Context) {
alerts, err := alertService.GetDisks()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, alerts)
}
func (b *BaseApi) PageAlertLogs(c *gin.Context) {
var req dto.AlertLogSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, alertLogs, err := alertService.PageAlertLogs(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: alertLogs,
})
}
func (b *BaseApi) CleanAlertLogs(c *gin.Context) {
if err := alertService.CleanAlertLogs(); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) GetClams(c *gin.Context) {
clams, err := alertService.GetClams()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, clams)
}
func (b *BaseApi) GetCronJobs(c *gin.Context) {
var req dto.CronJobReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
cronJobs, err := alertService.GetCronJobs(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, cronJobs)
}
func (b *BaseApi) GetAlertConfig(c *gin.Context) {
config, err := alertService.GetAlertConfig()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, config)
}
func (b *BaseApi) UpdateAlertConfig(c *gin.Context) {
var req dto.AlertConfigUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := alertService.UpdateAlertConfig(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) DeleteAlertConfig(c *gin.Context) {
var req dto.DeleteRequest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := alertService.DeleteAlertConfig(req.ID)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) TestAlertConfig(c *gin.Context) {
var req dto.AlertConfigTest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
flag, err := alertService.TestAlertConfig(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, flag)
}
-66
View File
@@ -1,66 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/gin-gonic/gin"
)
// @Tags App
// @Summary List Upgrade Ignored App
// @Accept json
// @Success 200 {array} model.AppIgnoreUpgrade
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/ignored/detail [get]
func (b *BaseApi) ListAppIgnored(c *gin.Context) {
res, err := appIgnoreUpgradeService.List()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags App
// @Summary Ignore Upgrade App
// @Accept json
// @Param request body request.AppIgnoreUpgradeReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/ignore [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"忽略应用升级","formatEN":"Ignore application upgrade"}
func (b *BaseApi) IgnoreAppUpgrade(c *gin.Context) {
var req request.AppIgnoreUpgradeReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appIgnoreUpgradeService.CreateAppIgnore(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// 写一个去掉忽略的接口
// @Tags App
// @Summary Cancel Ignore Upgrade App
// @Accept json
// @Param request body request.ReqWithID true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/ignored/cancel [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"取消忽略应用升级","formatEN":"Cancel ignore application upgrade"}
func (b *BaseApi) CancelIgnoreAppUpgrade(c *gin.Context) {
var req request.ReqWithID
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := appIgnoreUpgradeService.Delete(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
-201
View File
@@ -1,201 +0,0 @@
package v2
import (
"errors"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
)
// @Tags Dashboard
// @Summary Load os info
// @Accept json
// @Success 200 {object} dto.OsInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/base/os [get]
func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) {
data, err := dashboardService.LoadOsInfo()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load app launcher
// @Accept json
// @Success 200 {Array} dto.AppLauncher
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/app/launcher [get]
func (b *BaseApi) LoadAppLauncher(c *gin.Context) {
data, err := dashboardService.LoadAppLauncher(c)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load app launcher options
// @Accept json
// @Param request body dto.SearchByFilter true "request"
// @Success 200 {Array} dto.LauncherOption
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/app/launcher/option [post]
func (b *BaseApi) LoadAppLauncherOption(c *gin.Context) {
var req dto.SearchByFilter
if err := helper.CheckBind(&req, c); err != nil {
return
}
data, err := dashboardService.ListLauncherOption(req.Filter)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Update app Launcher
// @Accept json
// @Param request body dto.SettingUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/app/launcher/show [post]
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"首页应用 [key] => 显示:[value]","formatEN":"app launcher [key] => show: [value]"}
func (b *BaseApi) UpdateAppLauncher(c *gin.Context) {
var req dto.SettingUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := dashboardService.ChangeShow(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Dashboard
// @Summary Load quick jump options
// @Success 200 {Array} dto.QuickJump
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/quick/option [get]
func (b *BaseApi) LoadQuickOption(c *gin.Context) {
helper.SuccessWithData(c, dashboardService.LoadQuickOptions())
}
// @Tags Dashboard
// @Summary Update quick jump
// @Accept json
// @Param request body dto.ChangeQuicks true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/quick/change [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"切换快速跳转","formatEN":"change quick jump"}
func (b *BaseApi) UpdateQuickJump(c *gin.Context) {
var req dto.ChangeQuicks
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := dashboardService.ChangeQuick(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Dashboard
// @Summary Load dashboard base info
// @Accept json
// @Param ioOption path string true "request"
// @Param netOption path string true "request"
// @Success 200 {object} dto.DashboardBase
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/base/:ioOption/:netOption [get]
func (b *BaseApi) LoadDashboardBaseInfo(c *gin.Context) {
ioOption, ok := c.Params.Get("ioOption")
if !ok {
helper.BadRequest(c, errors.New("error ioOption in path"))
return
}
netOption, ok := c.Params.Get("netOption")
if !ok {
helper.BadRequest(c, errors.New("error ioOption in path"))
return
}
data, err := dashboardService.LoadBaseInfo(ioOption, netOption)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load dashboard current info for node
// @Success 200 {object} dto.NodeCurrent
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/current/node [get]
func (b *BaseApi) LoadCurrentInfoForNode(c *gin.Context) {
data := dashboardService.LoadCurrentInfoForNode()
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary Load dashboard current info
// @Accept json
// @Param ioOption path string true "request"
// @Param netOption path string true "request"
// @Success 200 {object} dto.DashboardCurrent
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/current/:ioOption/:netOption [get]
func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
ioOption, ok := c.Params.Get("ioOption")
if !ok {
helper.BadRequest(c, errors.New("error ioOption in path"))
return
}
netOption, ok := c.Params.Get("netOption")
if !ok {
helper.BadRequest(c, errors.New("error netOption in path"))
return
}
data := dashboardService.LoadCurrentInfo(ioOption, netOption)
helper.SuccessWithData(c, data)
}
// @Tags Dashboard
// @Summary System restart
// @Accept json
// @Param operation path string true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/system/restart/:operation [post]
func (b *BaseApi) SystemRestart(c *gin.Context) {
operation, ok := c.Params.Get("operation")
if !ok {
helper.BadRequest(c, errors.New("error operation in path"))
return
}
if err := dashboardService.Restart(operation); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
-99
View File
@@ -1,99 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/gin-gonic/gin"
)
// @Tags Disk Management
// @Summary Get complete disk information
// @Description Get information about all disks including partitioned and unpartitioned disks
// @Produce json
// @Success 200 {object} response.CompleteDiskInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/disks [get]
func (b *BaseApi) GetCompleteDiskInfo(c *gin.Context) {
diskInfo, err := diskService.GetCompleteDiskInfo()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, diskInfo)
}
// @Tags Disk Management
// @Summary Partition disk
// @Description Create partition and format disk with specified filesystem
// @Accept json
// @Param request body request.DiskPartitionRequest true "partition request"
// @Success 200 {string} string "Partition created successfully"
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/disks/partition [post]
// @x-panel-log {"bodyKeys":["device", "filesystem", "mountPoint"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"对磁盘 [device] 进行分区,文件系统 [filesystem],挂载点 [mountPoint]","formatEN":"Partition disk [device] with filesystem [filesystem], mount point [mountPoint]"}
func (b *BaseApi) PartitionDisk(c *gin.Context) {
var req request.DiskPartitionRequest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
result, err := diskService.PartitionDisk(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, result)
}
// @Tags Disk Management
// @Summary Mount disk
// @Description Mount partition to specified mount point
// @Accept json
// @Param request body request.DiskMountRequest true "mount request"
// @Success 200 {string} string "Disk mounted successfully"
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/disks/mount [post]
// @x-panel-log {"bodyKeys":["device", "mountPoint"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"挂载磁盘 [device] 到 [mountPoint]","formatEN":"Mount disk [device] to [mountPoint]"}
func (b *BaseApi) MountDisk(c *gin.Context) {
var req request.DiskMountRequest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := diskService.MountDisk(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Disk Management
// @Summary Unmount disk
// @Description Unmount partition from mount point
// @Accept json
// @Param request body request.DiskUnmountRequest true "unmount request"
// @Success 200 {string} string "Disk unmounted successfully"
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/disks/unmount [post]
// @x-panel-log {"bodyKeys":["device", "mountPoint"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"卸载磁盘 [device] 从 [mountPoint]","formatEN":"Unmount disk [device] from [mountPoint]"}
func (b *BaseApi) UnmountDisk(c *gin.Context) {
var req request.DiskUnmountRequest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := diskService.UnmountDisk(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
-10
View File
@@ -1,10 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/gin-gonic/gin"
)
func (b *BaseApi) CheckHealth(c *gin.Context) {
helper.Success(c)
}
-126
View File
@@ -1,126 +0,0 @@
package helper
import (
"context"
"fmt"
"net/http"
"strconv"
"github.com/1Panel-dev/1Panel/agent/global"
"gorm.io/gorm"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)
func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) {
res := dto.Response{
Code: code,
Message: "",
}
res.Message = i18n.GetMsgWithDetail(msgKey, err.Error())
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}
func InternalServer(ctx *gin.Context, err error) {
ErrorWithDetail(ctx, http.StatusInternalServerError, "ErrInternalServer", err)
}
func BadRequest(ctx *gin.Context, err error) {
ErrorWithDetail(ctx, http.StatusBadRequest, "ErrInvalidParams", err)
}
func SuccessWithData(ctx *gin.Context, data interface{}) {
if data == nil {
data = gin.H{}
}
res := dto.Response{
Code: http.StatusOK,
Data: data,
}
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}
func Success(ctx *gin.Context) {
res := dto.Response{
Code: http.StatusOK,
Message: "success",
}
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}
func SuccessWithMsg(ctx *gin.Context, msg string) {
res := dto.Response{
Code: http.StatusOK,
Message: msg,
}
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}
func GetParamID(c *gin.Context) (uint, error) {
idParam, ok := c.Params.Get("id")
if !ok {
return 0, errors.New("error id in path")
}
intNum, _ := strconv.Atoi(idParam)
return uint(intNum), nil
}
func GetIntParamByKey(c *gin.Context, key string) (uint, error) {
idParam, ok := c.Params.Get(key)
if !ok {
return 0, fmt.Errorf("error %s in path", key)
}
intNum, _ := strconv.Atoi(idParam)
return uint(intNum), nil
}
func GetStrParamByKey(c *gin.Context, key string) (string, error) {
idParam, ok := c.Params.Get(key)
if !ok {
return "", fmt.Errorf("error %s in path", key)
}
return idParam, nil
}
func GetTxAndContext() (tx *gorm.DB, ctx context.Context) {
tx = global.DB.Begin()
ctx = context.WithValue(context.Background(), constant.DB, tx)
return
}
func CheckBindAndValidate(req interface{}, c *gin.Context) error {
if err := c.ShouldBindJSON(req); err != nil {
ErrorWithDetail(c, http.StatusBadRequest, "ErrInvalidParams", err)
return err
}
if err := global.VALID.Struct(req); err != nil {
ErrorWithDetail(c, http.StatusBadRequest, "ErrInvalidParams", err)
return err
}
return nil
}
func CheckBind(req interface{}, c *gin.Context) error {
if err := c.ShouldBindJSON(&req); err != nil {
ErrorWithDetail(c, http.StatusBadRequest, "ErrInvalidParams", err)
return err
}
return nil
}
func GetParamInt32(paramName string, c *gin.Context) (int32, error) {
idParam, ok := c.Params.Get(paramName)
if !ok {
return 0, errors.New("error id in path")
}
intNum, _ := strconv.Atoi(idParam)
return int32(intNum), nil
}
-22
View File
@@ -1,22 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/gin-gonic/gin"
)
// @Tags Logs
// @Summary Load system log files
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/system/files [get]
func (b *BaseApi) GetSystemFiles(c *gin.Context) {
data, err := logService.ListSystemLogFile()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
-166
View File
@@ -1,166 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/gin-gonic/gin"
)
// @Tags McpServer
// @Summary List mcp servers
// @Accept json
// @Param request body request.McpServerSearch true "request"
// @Success 200 {object} response.McpServersRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/search [post]
func (b *BaseApi) PageMcpServers(c *gin.Context) {
var req request.McpServerSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list := mcpServerService.Page(req)
helper.SuccessWithData(c, list)
}
// @Tags McpServer
// @Summary Create mcp server
// @Accept json
// @Param request body request.McpServerCreate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server [post]
func (b *BaseApi) CreateMcpServer(c *gin.Context) {
var req request.McpServerCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := mcpServerService.Create(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags McpServer
// @Summary Update mcp server
// @Accept json
// @Param request body request.McpServerUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server/update [post]
func (b *BaseApi) UpdateMcpServer(c *gin.Context) {
var req request.McpServerUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := mcpServerService.Update(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags McpServer
// @Summary Delete mcp server
// @Accept json
// @Param request body request.McpServerDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server/del [post]
func (b *BaseApi) DeleteMcpServer(c *gin.Context) {
var req request.McpServerDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := mcpServerService.Delete(req.ID)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags McpServer
// @Summary Operate mcp server
// @Accept json
// @Param request body request.McpServerOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server/op [post]
func (b *BaseApi) OperateMcpServer(c *gin.Context) {
var req request.McpServerOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := mcpServerService.Operate(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags McpServer
// @Summary Bind Domain for mcp server
// @Accept json
// @Param request body request.McpBindDomain true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/domain/bind [post]
func (b *BaseApi) BindMcpDomain(c *gin.Context) {
var req request.McpBindDomain
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := mcpServerService.BindDomain(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags McpServer
// @Summary Update bind Domain for mcp server
// @Accept json
// @Param request body request.McpBindDomainUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/domain/update [post]
func (b *BaseApi) UpdateMcpBindDomain(c *gin.Context) {
var req request.McpBindDomainUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := mcpServerService.UpdateBindDomain(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags McpServer
// @Summary Get bin Domain for mcp server
// @Accept json
// @Success 200 {object} response.McpBindDomainRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/domain/get [get]
func (b *BaseApi) GetMcpBindDomain(c *gin.Context) {
res, err := mcpServerService.GetBindDomain()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
-107
View File
@@ -1,107 +0,0 @@
package v2
import (
"sort"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v4/disk"
"github.com/shirou/gopsutil/v4/net"
)
// @Tags Monitor
// @Summary Load monitor data
// @Param request body dto.MonitorSearch true "request"
// @Success 200 {array} dto.MonitorData
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/monitor/search [post]
func (b *BaseApi) LoadMonitor(c *gin.Context) {
var req dto.MonitorSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := monitorService.LoadMonitorData(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Monitor
// @Summary Clean monitor data
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/monitor/clean [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"}
func (b *BaseApi) CleanMonitor(c *gin.Context) {
if err := monitorService.CleanData(); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Monitor
// @Summary Load monitor setting
// @Success 200 {object} dto.MonitorSetting
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/monitor/setting [get]
func (b *BaseApi) LoadMonitorSetting(c *gin.Context) {
setting, err := monitorService.LoadSetting()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, setting)
}
// @Tags Monitor
// @Summary Update monitor setting
// @Param request body dto.MonitorSettingUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/monitor/setting/update [post]
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改默认监控网卡 [name]-[value]","formatEN":"update default monitor [name]-[value]"}
func (b *BaseApi) UpdateMonitorSetting(c *gin.Context) {
var req dto.MonitorSettingUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := monitorService.UpdateSetting(req.Key, req.Value); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) GetNetworkOptions(c *gin.Context) {
netStat, _ := net.IOCounters(true)
var options []string
options = append(options, "all")
for _, net := range netStat {
options = append(options, net.Name)
}
sort.Strings(options)
helper.SuccessWithData(c, options)
}
func (b *BaseApi) GetIOOptions(c *gin.Context) {
diskStat, _ := disk.IOCounters()
var options []string
options = append(options, "all")
for _, net := range diskStat {
options = append(options, net.Name)
}
sort.Strings(options)
helper.SuccessWithData(c, options)
}
-579
View File
@@ -1,579 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/gin-gonic/gin"
)
// @Tags Runtime
// @Summary List runtimes
// @Accept json
// @Param request body request.RuntimeSearch true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/search [post]
func (b *BaseApi) SearchRuntimes(c *gin.Context) {
var req request.RuntimeSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, items, err := runtimeService.Page(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: items,
})
}
// @Tags Runtime
// @Summary Create runtime
// @Accept json
// @Param request body request.RuntimeCreate true "request"
// @Success 200 {object} model.Runtime
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建运行环境 [name]","formatEN":"Create runtime [name]"}
func (b *BaseApi) CreateRuntime(c *gin.Context) {
var req request.RuntimeCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
ssl, err := runtimeService.Create(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, ssl)
}
// @Tags Website
// @Summary Delete runtime
// @Accept json
// @Param request body request.RuntimeDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除运行环境 [name]","formatEN":"Delete runtime [name]"}
func (b *BaseApi) DeleteRuntime(c *gin.Context) {
var req request.RuntimeDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := runtimeService.Delete(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Delete runtime
// @Accept json
// @Success 200 {array} dto.AppResource
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/installed/delete/check/:id [get]
func (b *BaseApi) DeleteRuntimeCheck(c *gin.Context) {
runTimeId, err := helper.GetIntParamByKey(c, "id")
if err != nil {
helper.BadRequest(c, err)
return
}
checkData, err := runtimeService.DeleteCheck(runTimeId)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, checkData)
}
// @Tags Runtime
// @Summary Update runtime
// @Accept json
// @Param request body request.RuntimeUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/update [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新运行环境 [name]","formatEN":"Update runtime [name]"}
func (b *BaseApi) UpdateRuntime(c *gin.Context) {
var req request.RuntimeUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.Update(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get runtime
// @Accept json
// @Param id path string true "request"
// @Success 200 {object} response.RuntimeDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/:id [get]
func (b *BaseApi) GetRuntime(c *gin.Context) {
id, err := helper.GetIntParamByKey(c, "id")
if err != nil {
helper.BadRequest(c, err)
return
}
res, err := runtimeService.Get(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags Runtime
// @Summary Get Node package scripts
// @Accept json
// @Param request body request.NodePackageReq true "request"
// @Success 200 {array} response.PackageScripts
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/node/package [post]
func (b *BaseApi) GetNodePackageRunScript(c *gin.Context) {
var req request.NodePackageReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := runtimeService.GetNodePackageRunScript(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags Runtime
// @Summary Operate runtime
// @Accept json
// @Param request body request.RuntimeOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/operate [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"操作运行环境 [name]","formatEN":"Operate runtime [name]"}
func (b *BaseApi) OperateRuntime(c *gin.Context) {
var req request.RuntimeOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := runtimeService.OperateRuntime(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get Node modules
// @Accept json
// @Param request body request.NodeModuleReq true "request"
// @Success 200 {array} response.NodeModule
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/node/modules [post]
func (b *BaseApi) GetNodeModules(c *gin.Context) {
var req request.NodeModuleReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := runtimeService.GetNodeModules(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags Runtime
// @Summary Operate Node modules
// @Accept json
// @Param request body request.NodeModuleReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/node/modules/operate [post]
func (b *BaseApi) OperateNodeModules(c *gin.Context) {
var req request.NodeModuleOperateReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := runtimeService.OperateNodeModules(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Sync runtime status
// @Accept json
// @Success 200
// @Security ApiKeyAuth
// @Router /runtimes/sync [post]
func (b *BaseApi) SyncStatus(c *gin.Context) {
err := runtimeService.SyncRuntimeStatus()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get php runtime extension
// @Accept json
// @Param id path string true "request"
// @Success 200 {object} response.PHPExtensionRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/:id/extensions [get]
func (b *BaseApi) GetRuntimeExtension(c *gin.Context) {
id, err := helper.GetIntParamByKey(c, "id")
if err != nil {
helper.BadRequest(c, err)
return
}
res, err := runtimeService.GetPHPExtensions(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags Runtime
// @Summary Install php extension
// @Accept json
// @Param request body request.PHPExtensionInstallReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/extensions/install [post]
func (b *BaseApi) InstallPHPExtension(c *gin.Context) {
var req request.PHPExtensionInstallReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := runtimeService.InstallPHPExtension(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary UnInstall php extension
// @Accept json
// @Param request body request.PHPExtensionInstallReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/extensions/uninstall [post]
func (b *BaseApi) UnInstallPHPExtension(c *gin.Context) {
var req request.PHPExtensionInstallReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := runtimeService.UnInstallPHPExtension(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Load php runtime conf
// @Accept json
// @Param id path integer true "request"
// @Success 200 {object} response.PHPConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/config/:id [get]
func (b *BaseApi) GetPHPConfig(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, err)
return
}
data, err := runtimeService.GetPHPConfig(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Runtime
// @Summary Update runtime php conf
// @Accept json
// @Param request body request.PHPConfigUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/config [post]
// @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) UpdatePHPConfig(c *gin.Context) {
var req request.PHPConfigUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.UpdatePHPConfig(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Update php conf file
// @Accept json
// @Param request body request.PHPFileUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/update [post]
// @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.PHPFileUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.UpdatePHPConfigFile(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get php conf file
// @Accept json
// @Param request body request.PHPFileReq true "request"
// @Success 200 {object} response.FileInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/file [post]
func (b *BaseApi) GetPHPConfigFile(c *gin.Context) {
var req request.PHPFileReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := runtimeService.GetPHPConfigFile(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Runtime
// @Summary Update fpm config
// @Accept json
// @Param request body request.FPMConfig true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/fpm/config [post]
func (b *BaseApi) UpdateFPMConfig(c *gin.Context) {
var req request.FPMConfig
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.UpdateFPMConfig(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get fpm config
// @Accept json
// @Param id path integer true "request"
// @Success 200 {object} request.FPMConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/fpm/config/:id [get]
func (b *BaseApi) GetFPMConfig(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, err)
return
}
data, err := runtimeService.GetFPMConfig(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Runtime
// @Summary Get supervisor process
// @Accept json
// @Param id path integer true "request"
// @Success 200 {array} response.SupervisorProcessConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/supervisor/process/:id [get]
func (b *BaseApi) GetSupervisorProcess(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, err)
return
}
data, err := runtimeService.GetSupervisorProcess(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Runtime
// @Summary Operate supervisor process
// @Accept json
// @Param request body request.PHPSupervisorProcessConfig true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/supervisor/process [post]
func (b *BaseApi) OperateSupervisorProcess(c *gin.Context) {
var req request.PHPSupervisorProcessConfig
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := runtimeService.OperateSupervisorProcess(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Operate supervisor process file
// @Accept json
// @Param request body request.PHPSupervisorProcessFileReq true "request"
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/supervisor/process/file [post]
func (b *BaseApi) OperateSupervisorProcessFile(c *gin.Context) {
var req request.PHPSupervisorProcessFileReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := runtimeService.OperateSupervisorProcessFile(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags Runtime
// @Summary Update PHP container config
// @Accept json
// @Param request body request.PHPContainerConfig true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/container/update [post]
func (b *BaseApi) UpdatePHPContainer(c *gin.Context) {
var req request.PHPContainerConfig
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.UpdatePHPContainer(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get PHP container config
// @Accept json
// @Param id path integer true "request"
// @Success 200 {object} request.PHPContainerConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/container/:id [get]
func (b *BaseApi) GetPHPContainerConfig(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, err)
return
}
data, err := runtimeService.GetPHPContainerConfig(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Runtime
// @Summary Update runtime remark
// @Accept json
// @Param request body request.RuntimeRemark true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/remark [post]
func (b *BaseApi) UpdateRuntimeRemark(c *gin.Context) {
var req request.RuntimeRemark
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.UpdateRemark(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Runtime
// @Summary Get PHP runtime status
// @Accept json
// @Param id path integer true "request"
// @Success 200 {object} map[string]interface{}
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/fpm/status/:id [get]
func (b *BaseApi) GetFPMStatus(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, err)
return
}
data, err := runtimeService.GetFPMStatus(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
-177
View File
@@ -1,177 +0,0 @@
package v2
import (
"encoding/base64"
"encoding/json"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)
// @Tags System Setting
// @Summary Load system setting info
// @Success 200 {object} dto.SettingInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/search [post]
func (b *BaseApi) GetSettingInfo(c *gin.Context) {
setting, err := settingService.GetSettingInfo()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, setting)
}
// @Tags System Setting
// @Summary Load system available status
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/search/available [get]
func (b *BaseApi) GetSystemAvailable(c *gin.Context) {
helper.Success(c)
}
// @Tags System Setting
// @Summary Update system setting
// @Accept json
// @Param request body dto.SettingUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/update [post]
// @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 := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.Update(req.Key, req.Value); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags System Setting
// @Summary Load local backup dir
// @Success 200 {string} path
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/basedir [get]
func (b *BaseApi) LoadBaseDir(c *gin.Context) {
helper.SuccessWithData(c, global.Dir.DataDir)
}
// @Tags System Setting
// @Summary Load local conn
// @Success 200 {object} dto.SSHConnData
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/ssh/conn [get]
func (b *BaseApi) LoadLocalConn(c *gin.Context) {
connInfoInDB := settingService.GetSettingByKey("LocalSSHConn")
if len(connInfoInDB) == 0 {
helper.Success(c)
return
}
var data dto.SSHConnData
if err := json.Unmarshal([]byte(connInfoInDB), &data); err != nil {
helper.Success(c)
return
}
if len(data.Password) != 0 {
data.Password = base64.StdEncoding.EncodeToString([]byte(data.Password))
}
if len(data.PrivateKey) != 0 {
data.PrivateKey = base64.StdEncoding.EncodeToString([]byte(data.PrivateKey))
}
if len(data.PassPhrase) != 0 {
data.PassPhrase = base64.StdEncoding.EncodeToString([]byte(data.PassPhrase))
}
helper.SuccessWithData(c, data)
}
func (b *BaseApi) CheckLocalConn(c *gin.Context) {
_, err := loadLocalConn()
helper.SuccessWithData(c, err == nil)
}
// @Tags System Setting
// @Summary Check local conn info
// @Success 200 {bool} isOk
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/ssh/check/info [post]
func (b *BaseApi) CheckLocalConnByInfo(c *gin.Context) {
var req dto.SSHConnData
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, settingService.TestConnByInfo(req))
}
// @Tags System Setting
// @Summary Save local conn info
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/ssh [post]
func (b *BaseApi) SaveLocalConn(c *gin.Context) {
var req dto.SSHConnData
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := settingService.SaveConnInfo(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func loadLocalConn() (*ssh.SSHClient, error) {
connInfoInDB := settingService.GetSettingByKey("LocalSSHConn")
if len(connInfoInDB) == 0 {
return nil, errors.New("no such ssh conn info in db!")
}
var connInDB model.LocalConnInfo
if err := json.Unmarshal([]byte(connInfoInDB), &connInDB); err != nil {
return nil, err
}
sshInfo := ssh.ConnInfo{
Addr: connInDB.Addr,
Port: int(connInDB.Port),
User: connInDB.User,
AuthMode: connInDB.AuthMode,
Password: connInDB.Password,
PrivateKey: []byte(connInDB.PrivateKey),
PassPhrase: []byte(connInDB.PassPhrase),
}
return ssh.NewClient(sshInfo)
}
// @Tags System Setting
// @Summary Load system setting by key
// @Param key path string true "key"
// @Success 200 {object} dto.SettingInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/get/{key} [get]
func (b *BaseApi) GetSettingByKey(c *gin.Context) {
key := c.Param("key")
if len(key) == 0 {
helper.BadRequest(c, errors.New("key is empty"))
return
}
value := settingService.GetSettingByKey(key)
helper.SuccessWithData(c, value)
}
-260
View File
@@ -1,260 +0,0 @@
package v2
import (
"encoding/base64"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
)
// @Tags SSH
// @Summary Load host SSH setting info
// @Success 200 {object} dto.SSHInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/search [post]
func (b *BaseApi) GetSSHInfo(c *gin.Context) {
info, err := sshService.GetSSHInfo()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, info)
}
// @Tags SSH
// @Summary Operate SSH
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/operate [post]
// @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 := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := sshService.OperateSSH(req.Operation); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags SSH
// @Summary Update host SSH setting
// @Accept json
// @Param request body dto.SSHUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/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.SSHUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := sshService.Update(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags SSH
// @Summary Update host SSH setting by file
// @Accept json
// @Param request body dto.SSHConf true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/conffile/update [post]
// @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 := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := sshService.UpdateByFile(req.File); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags SSH
// @Summary Generate host SSH secret
// @Accept json
// @Param request body dto.CreateRootCert true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/cert [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
func (b *BaseApi) CreateRootCert(c *gin.Context) {
var req dto.CreateRootCert
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if len(req.PassPhrase) != 0 {
passPhrase, err := base64.StdEncoding.DecodeString(req.PassPhrase)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PassPhrase = string(passPhrase)
}
if len(req.PrivateKey) != 0 {
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PrivateKey = string(privateKey)
}
if len(req.PublicKey) != 0 {
publicKey, err := base64.StdEncoding.DecodeString(req.PublicKey)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PublicKey = string(publicKey)
}
if err := sshService.CreateRootCert(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags SSH
// @Summary Sycn host SSH secret
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/cert/sync [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 SSH 密钥 ","formatEN":"sync SSH secret"}
func (b *BaseApi) SyncRootCert(c *gin.Context) {
if err := sshService.SyncRootCert(); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags SSH
// @Summary Load host SSH secret
// @Accept json
// @Param request body dto.SearchWithPage true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/cert/search [post]
func (b *BaseApi) SearchRootCert(c *gin.Context) {
var req dto.SearchWithPage
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, data, err := sshService.SearchRootCerts(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: data,
})
}
// @Tags SSH
// @Summary Delete host SSH secret
// @Accept json
// @Param request body dto.ForceDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/cert/delete [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除 SSH 密钥 ","formatEN":"delete SSH secret"}
func (b *BaseApi) DeleteRootCert(c *gin.Context) {
var req dto.ForceDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := sshService.DeleteRootCerts(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags SSH
// @Summary Load host SSH logs
// @Accept json
// @Param request body dto.SearchSSHLog true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/log [post]
func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
var req dto.SearchSSHLog
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, data, err := sshService.LoadLog(c, req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: data,
})
}
// @Tags SSH
// @Summary Export host SSH logs
// @Accept json
// @Param request body dto.SearchSSHLog true "request"
// @Success 200 {string} path
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/log/export [post]
func (b *BaseApi) ExportSSHLogs(c *gin.Context) {
var req dto.SearchSSHLog
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
tmpFile, err := sshService.ExportLog(c, req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, tmpFile)
}
// @Tags SSH
// @Summary Load host SSH conf
// @Success 200 {string} conf
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/conf [get]
func (b *BaseApi) LoadSSHConf(c *gin.Context) {
data, err := sshService.LoadSSHConf()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
-26
View File
@@ -1,26 +0,0 @@
package v2
import (
"errors"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/gin-gonic/gin"
)
// @Tags Host
// @Summary Check if a system component exists
// @Accept json
// @Param name query string true "Component name to check (e.g., rsync, docker)"
// @Success 200 {object} response.ComponentInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/components/{name} [get]
func (b *BaseApi) CheckComponentExistence(c *gin.Context) {
name := c.Param("name")
if name == "" {
helper.BadRequest(c, errors.New("empty component name"))
return
}
info := systemService.IsComponentExist(name)
helper.SuccessWithData(c, info)
}
-46
View File
@@ -1,46 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/gin-gonic/gin"
)
// @Tags TaskLog
// @Summary Page task logs
// @Accept json
// @Param request body dto.SearchTaskLogReq true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/tasks/search [post]
func (b *BaseApi) PageTasks(c *gin.Context) {
var req dto.SearchTaskLogReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := taskService.Page(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags TaskLog
// @Summary Get the number of executing tasks
// @Success 200 {object} int64
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/tasks/executing/count [get]
func (b *BaseApi) CountExecutingTasks(c *gin.Context) {
count, err := taskService.CountExecutingTask()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, count)
}
-330
View File
@@ -1,330 +0,0 @@
package dto
import (
"encoding/json"
"github.com/1Panel-dev/1Panel/agent/app/model"
"time"
)
type CreateOrUpdateAlert struct {
AlertTitle string `json:"alertTitle"`
AlertType string `json:"alertType"`
AlertMethod string `json:"alertMethod"`
AlertCount uint `json:"alertCount"`
EntryID uint `json:"entryID"`
}
type AlertBase struct {
AlertType string `json:"alertType"`
EntryID uint `json:"entryID"`
}
type PushAlert struct {
TaskName string `json:"taskName"`
AlertType string `json:"alertType"`
EntryID uint `json:"entryID"`
Param string `json:"param"`
}
type AlertSearch struct {
PageInfo
OrderBy string `json:"orderBy" validate:"required,oneof=created_at"`
Order string `json:"order" validate:"required,oneof=null ascending descending"`
Type string `json:"type"`
Status string `json:"status"`
Method string `json:"method"`
}
type AlertDTO struct {
ID uint `json:"id"`
Type string `json:"type"`
Cycle uint `json:"cycle"`
Count uint `json:"count"`
Method string `json:"method"`
Title string `json:"title"`
Project string `json:"project"`
Status string `json:"status"`
SendCount uint `json:"sendCount"`
AdvancedParams string `json:"advancedParams"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type AlertCreate struct {
Type string `json:"type" validate:"required"`
Cycle uint `json:"cycle"`
Count uint `json:"count"`
Method string `json:"method" validate:"required"`
Title string `json:"title"`
Project string `json:"project"`
Status string `json:"status"`
SendCount uint `json:"sendCount"`
AdvancedParams string `json:"advancedParams"`
}
type AlertUpdate struct {
ID uint `json:"id" validate:"required"`
Type string `json:"type"`
Cycle uint `json:"cycle"`
Count uint `json:"count"`
Method string `json:"method"`
Title string `json:"title"`
Project string `json:"project"`
Status string `json:"status"`
SendCount uint `json:"sendCount"`
AdvancedParams string `json:"advancedParams"`
}
type DeleteRequest struct {
ID uint `json:"id" validate:"required"`
}
type AlertUpdateStatus struct {
ID uint `json:"id" validate:"required"`
Status string `json:"status" validate:"required"`
}
type DiskDTO struct {
Path string `json:"path"`
Type string `json:"type"`
Device string `json:"device"`
Total uint64 `json:"total"`
Free uint64 `json:"free"`
Used uint64 `json:"used"`
UsedPercent float64 `json:"usedPercent"`
InodesTotal uint64 `json:"inodesTotal"`
InodesUsed uint64 `json:"inodesUsed"`
InodesFree uint64 `json:"inodesFree"`
InodesUsedPercent float64 `json:"inodesUsedPercent"`
}
type AlertLogSearch struct {
PageInfo
Count uint `json:"count"`
Status string `json:"status"`
}
type AlertLogDTO struct {
ID uint `json:"id"`
Type string `json:"type"`
Count uint `json:"count"`
AlertId uint `json:"alertId"`
AlertDetail AlertDetail `json:"alertDetail"`
AlertRule AlertRule `json:"alertRule"`
Status string `json:"status"`
Method string `json:"method"`
Message string `json:"message"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type AlertLogCreate struct {
Type string `json:"type" validate:"required"`
Count uint `json:"count" validate:"required"`
AlertId uint `json:"alertId" validate:"required"`
AlertDetail string `json:"alertDetail" validate:"required"`
AlertRule string `json:"alertRule" validate:"required"`
Status string `json:"status" validate:"required"`
Method string `json:"method" validate:"required"`
Message string `json:"message"`
RecordId uint `json:"recordId"`
LicenseId string `json:"licenseId" validate:"required"`
}
type AlertLog struct {
ID uint `json:"id" validate:"required"`
}
type AlertDetail struct {
LicenseId string `json:"licenseId"`
Type string `json:"type"`
SubType string `json:"subType"`
Title string `json:"title"`
Method string `json:"method"`
LicenseCode string `json:"licenseCode"`
DeviceId string `json:"deviceId"`
Project string `json:"project"`
Params []Param `json:"params"`
Phone string `json:"phone"`
}
type AlertRule struct {
ID uint `json:"id"`
Type string `json:"type"`
Cycle uint `json:"cycle"`
Count uint `json:"count"`
Method string `json:"method"`
Title string `json:"title"`
Project string `json:"project"`
Status string `json:"status"`
SendCount uint `json:"sendCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type Param struct {
Index string `json:"index"`
Key string `json:"key"`
Value string `json:"value"`
}
type ClamDTO struct {
ID uint `json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Name string `json:"name"`
Status string `json:"status"`
Path string `json:"path"`
}
type CronJobDTO struct {
ID uint `json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Name string `json:"name"`
Status string `json:"status"`
Type string `json:"type"`
}
type CronJobReq struct {
Name string `json:"name"`
Status string `json:"status"`
Type string `json:"type"`
}
type UpgradeInfo struct {
TestVersion string `json:"testVersion"`
NewVersion string `json:"newVersion"`
LatestVersion string `json:"latestVersion"`
ReleaseNote string `json:"releaseNote"`
}
type AlertDiskInfo struct {
Type string
Mount string
Device string
}
type SyncResult struct {
ID uint `json:"id"`
LicenseID string `json:"licenseId"`
SendStatus string `json:"sendStatus"`
CreateTime string `json:"createTime"`
UpdateTime string `json:"updateTime"`
Remarks string `json:"remarks"`
MsgCount int `json:"msgCount"`
MsgCountMax int `json:"msgCountMax"`
}
type QueryRequest struct {
QueryIds []uint `json:"queryIds"`
LicenseId string `json:"licenseId"`
}
type AlertResponse struct {
Result bool `json:"result"`
Data json.RawMessage `json:"data"`
Message string `json:"message"`
}
type PushResult struct {
RecordId uint `json:"recordId"`
LicenseId string `json:"licenseId"`
}
type UpdateOfflineAlertLog struct {
ID uint `json:"id"`
Status string `json:"status"`
Message string `json:"message"`
RecordId uint `json:"recordId"`
LicenseId string `json:"licenseId"`
}
type SyncOfflineAlertLogDTO struct {
QueryRequest string `json:"queryRequest"`
Ids []uint `json:"ids"`
AlertLogs []model.AlertLog `json:"alertLogs"`
LicenseId string `json:"licenseId"`
}
type OfflineAlertResponse struct {
ID uint `json:"id"`
Type string `json:"type"`
RemoteErr error `json:"remoteErr"`
ResponseStruct AlertResponse `json:"responseStruct"`
AlertLogs []model.AlertLog `json:"alertLogs"`
Ids []uint `json:"ids"`
LicenseId string `json:"licenseId"`
}
type OfflineAlertLogDTO struct {
ID uint `json:"id"`
Type string `json:"type"`
Count uint `json:"count"`
AlertId uint `json:"alertId"`
AlertDetail string `json:"alertDetail"`
AlertRule string `json:"alertRule"`
Status string `json:"status"`
Method string `json:"method"`
Message string `json:"message"`
RecordId uint `json:"recordId"`
LicenseId string `json:"licenseId"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type OfflineQueryRequest struct {
Ids []uint `json:"ids"`
QueryIds []uint `json:"queryIds"`
LicenseId string `json:"licenseId"`
}
type AlertConfigUpdate struct {
ID uint `json:"id"`
Type string `json:"type"`
Title string `json:"title"`
Status string `json:"status"`
Config string `json:"config"`
}
type AlertConfigTest struct {
Host string `json:"host"`
Port int `json:"port"`
Sender string `json:"sender"`
Password string `json:"password"`
DisplayName string `json:"displayName"`
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
Recipient string `json:"recipient"`
}
type AlertSendTimeRange struct {
NoticeAlert struct {
SendTimeRange string `json:"sendTimeRange"`
Type []string `json:"type"`
} `json:"noticeAlert"`
ResourceAlert struct {
SendTimeRange string `json:"sendTimeRange"`
Type []string `json:"type"`
} `json:"resourceAlert"`
}
type AlertCommonConfig struct {
IsOffline string `json:"isOffline"`
AlertSendTimeRange AlertSendTimeRange `json:"alertSendTimeRange"`
}
type AlertSmsConfig struct {
Phone string `json:"phone"`
AlertDailyNum uint `json:"alertDailyNum"`
}
type AlertEmailConfig struct {
Host string `json:"host"`
Port int `json:"port"`
Sender string `json:"sender"`
Password string `json:"password"`
DisplayName string `json:"displayName"`
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
Recipient string `json:"recipient"`
}
-125
View File
@@ -1,125 +0,0 @@
package dto
import (
"time"
)
type BackupOperate struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type" validate:"required"`
IsPublic bool `json:"isPublic"`
Bucket string `json:"bucket"`
AccessKey string `json:"accessKey"`
Credential string `json:"credential"`
BackupPath string `json:"backupPath"`
Vars string `json:"vars" validate:"required"`
RememberAuth bool `json:"rememberAuth"`
}
type BackupInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
IsPublic bool `json:"isPublic"`
Bucket string `json:"bucket"`
AccessKey string `json:"accessKey"`
Credential string `json:"credential"`
BackupPath string `json:"backupPath"`
Vars string `json:"vars"`
CreatedAt time.Time `json:"createdAt"`
RememberAuth bool `json:"rememberAuth"`
}
type ForBuckets struct {
Type string `json:"type" validate:"required"`
AccessKey string `json:"accessKey"`
Credential string `json:"credential" validate:"required"`
Vars string `json:"vars" validate:"required"`
}
type SyncFromMaster struct {
Name string `json:"name" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=create delete update"`
Data string `json:"data"`
}
type BackupOption struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
IsPublic bool `json:"isPublic"`
}
type UploadForRecover struct {
FilePath string `json:"filePath"`
TargetDir string `json:"targetDir"`
}
type CommonBackup struct {
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster"`
Name string `json:"name"`
DetailName string `json:"detailName"`
Secret string `json:"secret"`
TaskID string `json:"taskID"`
FileName string `json:"fileName"`
Description string `json:"description"`
}
type CommonRecover struct {
DownloadAccountID uint `json:"downloadAccountID" validate:"required"`
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster"`
Name string `json:"name"`
DetailName string `json:"detailName"`
File string `json:"file"`
Secret string `json:"secret"`
TaskID string `json:"taskID"`
BackupRecordID uint `json:"backupRecordID"`
}
type RecordSearch struct {
PageInfo
Type string `json:"type" validate:"required"`
Name string `json:"name"`
DetailName string `json:"detailName"`
}
type RecordSearchByCronjob struct {
PageInfo
CronjobID uint `json:"cronjobID" validate:"required"`
}
type BackupRecords struct {
ID uint `json:"id"`
CreatedAt time.Time `json:"createdAt"`
AccountType string `json:"accountType"`
AccountName string `json:"accountName"`
DownloadAccountID uint `json:"downloadAccountID"`
FileDir string `json:"fileDir"`
FileName string `json:"fileName"`
Description string `json:"description"`
}
type DownloadRecord struct {
DownloadAccountID uint `json:"downloadAccountID" validate:"required"`
FileDir string `json:"fileDir" validate:"required"`
FileName string `json:"fileName" validate:"required"`
}
type SearchForSize struct {
PageInfo
Type string `json:"type" validate:"required"`
Name string `json:"name"`
DetailName string `json:"detailName"`
Info string `json:"info"`
CronjobID uint `json:"cronjobID"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
}
type RecordFileSize struct {
ID uint `json:"id"`
Name string `json:"name"`
Size int64 `json:"size"`
}
-199
View File
@@ -1,199 +0,0 @@
package dto
import (
"time"
)
type PageCronjob struct {
PageInfo
Info string `json:"info"`
GroupIDs []uint `json:"groupIDs"`
OrderBy string `json:"orderBy" validate:"required,oneof=name status createdAt"`
Order string `json:"order" validate:"required,oneof=null ascending descending"`
}
type CronjobSpec struct {
Spec string `json:"spec" validate:"required"`
}
type CronjobOperate struct {
ID uint `json:"id"`
Name string `json:"name" validate:"required"`
Type string `json:"type" validate:"required"`
GroupID uint `json:"groupID"`
SpecCustom bool `json:"specCustom"`
Spec string `json:"spec" validate:"required"`
Executor string `json:"executor"`
ScriptMode string `json:"scriptMode"`
Script string `json:"script"`
Command string `json:"command"`
ContainerName string `json:"containerName"`
User string `json:"user"`
ScriptID uint `json:"scriptID"`
AppID string `json:"appID"`
Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
SnapshotRule SnapshotRule `json:"snapshotRule"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
RetainCopies int `json:"retainCopies" validate:"number,min=1"`
RetryTimes int `json:"retryTimes" validate:"number,min=0"`
Timeout uint `json:"timeout" validate:"number,min=1"`
IgnoreErr bool `json:"ignoreErr"`
Secret string `json:"secret"`
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
AlertMethod string `json:"alertMethod"`
}
type SnapshotRule struct {
WithImage bool `json:"withImage"`
IgnoreAppIDs []uint `json:"ignoreAppIDs"`
}
type CronjobUpdateStatus struct {
ID uint `json:"id" validate:"required"`
Status string `json:"status" validate:"required"`
}
type CronjobClean struct {
IsDelete bool `json:"isDelete"`
CleanData bool `json:"cleanData"`
CronjobID uint `json:"cronjobID" validate:"required"`
CleanRemoteData bool `json:"cleanRemoteData"`
}
type CronjobBatchDelete struct {
CleanData bool `json:"cleanData"`
CleanRemoteData bool `json:"cleanRemoteData"`
IDs []uint `json:"ids" validate:"required"`
}
type CronjobInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
GroupID uint `json:"groupID"`
SpecCustom bool `json:"specCustom"`
Spec string `json:"spec"`
Executor string `json:"executor"`
ScriptMode string `json:"scriptMode"`
Script string `json:"script"`
Command string `json:"command"`
ContainerName string `json:"containerName"`
User string `json:"user"`
ScriptID uint `json:"scriptID"`
AppID string `json:"appID"`
Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
RetainCopies int `json:"retainCopies"`
RetryTimes int `json:"retryTimes"`
Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
SnapshotRule SnapshotRule `json:"snapshotRule"`
SourceAccounts []string `json:"sourceAccounts"`
DownloadAccount string `json:"downloadAccount"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
LastRecordStatus string `json:"lastRecordStatus"`
LastRecordTime string `json:"lastRecordTime"`
Status string `json:"status"`
Secret string `json:"secret"`
AlertCount uint `json:"alertCount"`
}
type CronjobImport struct {
Cronjobs []CronjobTrans `json:"cronjobs"`
}
type CronjobTrans struct {
Name string `json:"name"`
Type string `json:"type"`
GroupID uint `json:"groupID"`
SpecCustom bool `json:"specCustom"`
Spec string `json:"spec"`
Executor string `json:"executor"`
ScriptMode string `json:"scriptMode"`
Script string `json:"script"`
Command string `json:"command"`
ContainerName string `json:"containerName"`
User string `json:"user"`
URL string `json:"url"`
ScriptName string `json:"scriptName"`
Apps []TransHelper `json:"apps"`
Websites []string `json:"websites"`
DBType string `json:"dbType"`
DBNames []TransHelper `json:"dbName"`
ExclusionRules string `json:"exclusionRules"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
RetainCopies uint64 `json:"retainCopies"`
RetryTimes uint `json:"retryTimes"`
Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
SnapshotRule SnapshotTransHelper `json:"snapshotRule"`
Secret string `json:"secret"`
SourceAccounts []string `json:"sourceAccounts"`
DownloadAccount string `json:"downloadAccount"`
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
AlertMethod string `json:"alertMethod"`
}
type TransHelper struct {
Name string `json:"name"`
DetailName string `json:"detailName"`
}
type SnapshotTransHelper struct {
WithImage bool `json:"withImage"`
IgnoreApps []TransHelper `json:"ignoreApps"`
}
type ScriptOptions struct {
ID uint `json:"id"`
Name string `json:"name"`
}
type SearchRecord struct {
PageInfo
CronjobID int `json:"cronjobID"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
Status string `json:"status"`
}
type Record struct {
ID uint `json:"id"`
TaskID string `json:"taskID"`
StartTime string `json:"startTime"`
Records string `json:"records"`
Status string `json:"status"`
Message string `json:"message"`
TargetPath string `json:"targetPath"`
Interval int `json:"interval"`
File string `json:"file"`
}
-25
View File
@@ -1,25 +0,0 @@
package dto
type LsblkDevice struct {
Name string `json:"name"`
Size string `json:"size"`
Type string `json:"type"`
MountPoint *string `json:"mountpoint"`
FsType *string `json:"fstype"`
Model *string `json:"model"`
Serial string `json:"serial"`
Tran string `json:"tran"`
Rota bool `json:"rota"`
Children []LsblkDevice `json:"children,omitempty"`
}
type LsblkOutput struct {
BlockDevices []LsblkDevice `json:"blockdevices"`
}
type DiskFormatRequest struct {
Device string `json:"device" `
Filesystem string `json:"filesystem" `
Label string `json:"label,omitempty" `
QuickFormat bool `json:"quickFormat,omitempty"`
}
-8
View File
@@ -1,8 +0,0 @@
package dto
type LogFileRes struct {
Lines []string `json:"lines"`
IsEndOfFile bool `json:"isEndOfFile"`
TotalPages int `json:"totalPages"`
TotalLines int `json:"totalLines"`
}
-29
View File
@@ -1,29 +0,0 @@
package dto
type GroupCreate struct {
ID uint `json:"id"`
Name string `json:"name" validate:"required"`
Type string `json:"type" validate:"required"`
}
type GroupSearch struct {
Type string `json:"type" validate:"required"`
}
type GroupUpdate struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type" validate:"required"`
IsDefault bool `json:"isDefault"`
}
type GroupInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
IsDefault bool `json:"isDefault"`
}
type OperateByType struct {
Type string `json:"type"`
}
-15
View File
@@ -1,15 +0,0 @@
package dto
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
)
type SearchTaskLogReq struct {
Status string `json:"status"`
Type string `json:"type"`
PageInfo
}
type TaskDTO struct {
model.Task
}
@@ -1,7 +0,0 @@
package request
type AppIgnoreUpgradeReq struct {
AppID uint `json:"appID" validate:"required"`
AppDetailID uint `json:"appDetailID"`
Scope string `json:"scope" validate:"required,oneof=all version"`
}
-5
View File
@@ -1,5 +0,0 @@
package request
type ReqWithID struct {
ID uint `json:"id" validate:"required"`
}
-20
View File
@@ -1,20 +0,0 @@
package request
type DiskPartitionRequest struct {
Device string `json:"device" validate:"required"`
Filesystem string `json:"filesystem" validate:"required,oneof=ext4 xfs"`
Label string `json:"label"`
AutoMount bool `json:"autoMount"`
MountPoint string `json:"mountPoint" validate:"required"`
}
type DiskMountRequest struct {
Device string `json:"device" validate:"required"`
MountPoint string `json:"mountPoint" validate:"required"`
Filesystem string `json:"filesystem" validate:"required,oneof=ext4 xfs"`
AutoMount bool `json:"autoMount"`
}
type DiskUnmountRequest struct {
MountPoint string `json:"mountPoint" validate:"required"`
}
-50
View File
@@ -1,50 +0,0 @@
package request
import "github.com/1Panel-dev/1Panel/agent/app/dto"
type McpServerSearch struct {
dto.PageInfo
Name string `json:"name"`
Sync bool `json:"sync"`
}
type McpServerCreate struct {
Name string `json:"name" validate:"required"`
Command string `json:"command" validate:"required"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
Port int `json:"port" validate:"required"`
ContainerName string `json:"containerName"`
BaseURL string `json:"baseUrl"`
SsePath string `json:"ssePath"`
HostIP string `json:"hostIP"`
StreamableHttpPath string `json:"streamableHttpPath"`
OutputTransport string `json:"outputTransport" validate:"required"`
Type string `json:"type" validate:"required"`
}
type McpServerUpdate struct {
ID uint `json:"id" validate:"required"`
McpServerCreate
}
type McpServerDelete struct {
ID uint `json:"id" validate:"required"`
}
type McpServerOperate struct {
ID uint `json:"id" validate:"required"`
Operate string `json:"operate" validate:"required"`
}
type McpBindDomain struct {
Domain string `json:"domain" validate:"required"`
SSLID uint `json:"sslID"`
IPList string `json:"ipList"`
}
type McpBindDomainUpdate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
SSLID uint `json:"sslID"`
IPList string `json:"ipList"`
}
-142
View File
@@ -1,142 +0,0 @@
package request
import (
"github.com/1Panel-dev/1Panel/agent/app/dto"
)
type RuntimeSearch struct {
dto.PageInfo
Type string `json:"type"`
Name string `json:"name"`
Status string `json:"status"`
}
type RuntimeCreate struct {
AppDetailID uint `json:"appDetailId"`
Name string `json:"name"`
Resource string `json:"resource"`
Image string `json:"image"`
Type string `json:"type"`
Version string `json:"version"`
Source string `json:"source"`
CodeDir string `json:"codeDir"`
Remark string `json:"remark"`
Params map[string]interface{} `json:"params"`
NodeConfig
}
type NodeConfig struct {
Install bool `json:"install"`
Clean bool `json:"clean"`
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
}
type Environment struct {
Key string `json:"key"`
Value string `json:"value"`
}
type Volume struct {
Source string `json:"source"`
Target string `json:"target"`
}
type ExposedPort struct {
HostPort int `json:"hostPort"`
ContainerPort int `json:"containerPort"`
HostIP string `json:"hostIP"`
}
type RuntimeDelete struct {
ID uint `json:"id"`
ForceDelete bool `json:"forceDelete"`
}
type RuntimeUpdate struct {
Name string `json:"name"`
ID uint `json:"id"`
Image string `json:"image"`
Version string `json:"version"`
Rebuild bool `json:"rebuild"`
Source string `json:"source"`
CodeDir string `json:"codeDir"`
Remark string `json:"remark"`
Params map[string]interface{} `json:"params"`
NodeConfig
}
type NodePackageReq struct {
CodeDir string `json:"codeDir"`
}
type RuntimeOperate struct {
Operate string `json:"operate"`
ID uint `json:"ID"`
}
type NodeModuleOperateReq struct {
Operate string `json:"operate" validate:"oneof=install uninstall update"`
ID uint `json:"ID" validate:"required"`
Module string `json:"module"`
PkgManager string `json:"pkgManager" validate:"oneof=npm yarn"`
}
type NodeModuleReq struct {
ID uint `json:"ID" validate:"required"`
}
type PHPExtensionInstallReq struct {
ID uint `json:"ID" validate:"required"`
Name string `json:"name" validate:"required"`
TaskID string `json:"taskID"`
}
type PHPConfigUpdate struct {
ID uint `json:"id" validate:"required"`
Params map[string]string `json:"params"`
Scope string `json:"scope" validate:"required"`
DisableFunctions []string `json:"disableFunctions"`
UploadMaxSize string `json:"uploadMaxSize"`
}
type PHPFileUpdate struct {
ID uint `json:"id" validate:"required"`
Type string `json:"type" validate:"required"`
Content string `json:"content" validate:"required"`
}
type PHPFileReq struct {
ID uint `json:"id" validate:"required"`
Type string `json:"type" validate:"required"`
}
type FPMConfig struct {
ID uint `json:"id" validate:"required"`
Params map[string]interface{} `json:"params" validate:"required"`
}
type PHPSupervisorProcessConfig struct {
ID uint `json:"id" validate:"required"`
SupervisorProcessConfig
}
type PHPSupervisorProcessFileReq struct {
ID uint `json:"id" validate:"required"`
SupervisorProcessFileReq
}
type PHPContainerConfig struct {
ID uint `json:"id" validate:"required"`
ContainerName string `json:"containerName"`
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
}
type RuntimeRemark struct {
ID uint `json:"id" validate:"required"`
Remark string `json:"remark"`
}
-1
View File
@@ -1 +0,0 @@
package request
-311
View File
@@ -1,311 +0,0 @@
package request
import (
"github.com/1Panel-dev/1Panel/agent/app/dto"
)
type WebsiteSearch struct {
dto.PageInfo
Name string `json:"name"`
OrderBy string `json:"orderBy" validate:"required,oneof=primary_domain type status createdAt expire_date created_at favorite"`
Order string `json:"order" validate:"required,oneof=null ascending descending"`
WebsiteGroupID uint `json:"websiteGroupId"`
Type string `json:"type"`
}
type WebsiteCreate struct {
Type string `json:"type" validate:"required"`
Alias string `json:"alias" validate:"required"`
Remark string `json:"remark"`
Proxy string `json:"proxy"`
WebsiteGroupID uint `json:"webSiteGroupID" validate:"required"`
IPV6 bool `json:"IPV6"`
Domains []WebsiteDomain `json:"domains"`
AppType string `json:"appType" validate:"oneof=new installed"`
AppInstall NewAppInstall `json:"appInstall"`
AppID uint `json:"appID"`
AppInstallID uint `json:"appInstallID"`
RuntimeID uint `json:"runtimeID"`
TaskID string `json:"taskID"`
ParentWebsiteID uint `json:"parentWebsiteID"`
SiteDir string `json:"siteDir"`
RuntimeConfig
FtpConfig
DataBaseConfig
SSLConfig
}
type WebsiteOptionReq struct {
Types []string `json:"types"`
}
type RuntimeConfig struct {
ProxyType string `json:"proxyType"`
Port int `json:"port"`
}
type FtpConfig struct {
FtpUser string `json:"ftpUser"`
FtpPassword string `json:"ftpPassword"`
}
type DataBaseConfig struct {
CreateDb bool `json:"createDb"`
DbName string `json:"dbName"`
DbUser string `json:"dbUser"`
DbPassword string `json:"dbPassword"`
DbHost string `json:"dbHost"`
DBFormat string `json:"dbFormat"`
}
type SSLConfig struct {
EnableSSL bool `json:"enableSSL"`
WebsiteSSLID uint `json:"websiteSSLID"`
}
type NewAppInstall struct {
Name string `json:"name"`
AppDetailId uint `json:"appDetailID"`
Params map[string]interface{} `json:"params"`
AppContainerConfig
}
type WebsiteInstallCheckReq struct {
InstallIds []uint `json:"InstallIds"`
}
type WebsiteUpdate struct {
ID uint `json:"id" validate:"required"`
PrimaryDomain string `json:"primaryDomain" validate:"required"`
Remark string `json:"remark"`
WebsiteGroupID uint `json:"webSiteGroupID"`
ExpireDate string `json:"expireDate"`
IPV6 bool `json:"IPV6"`
Favorite bool `json:"favorite"`
}
type WebsiteDelete struct {
ID uint `json:"id" validate:"required"`
DeleteApp bool `json:"deleteApp"`
DeleteBackup bool `json:"deleteBackup"`
ForceDelete bool `json:"forceDelete"`
}
type WebsiteOp struct {
ID uint `json:"id" validate:"required"`
Operate string `json:"operate"`
}
type WebsiteRedirectUpdate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
Enable bool `json:"enable"`
}
type WebsiteRecover struct {
WebsiteName string `json:"websiteName" validate:"required"`
Type string `json:"type" validate:"required"`
BackupName string `json:"backupName" validate:"required"`
}
type WebsiteRecoverByFile struct {
WebsiteName string `json:"websiteName" validate:"required"`
Type string `json:"type" validate:"required"`
FileDir string `json:"fileDir" validate:"required"`
FileName string `json:"fileName" validate:"required"`
}
type WebsiteGroupCreate struct {
Name string `json:"name" validate:"required"`
}
type WebsiteGroupUpdate struct {
ID uint `json:"id" validate:"required"`
Name string `json:"name"`
Default bool `json:"default"`
}
type WebsiteDomainCreate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Domains []WebsiteDomain `json:"domains" validate:"required"`
}
type WebsiteDomainUpdate struct {
ID uint `json:"id" validate:"required"`
SSL bool `json:"ssl"`
}
type WebsiteDomain struct {
Domain string `json:"domain" validate:"required"`
Port int `json:"port"`
SSL bool `json:"ssl"`
}
type WebsiteDomainDelete struct {
ID uint `json:"id" validate:"required"`
}
type WebsiteHTTPSOp struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Enable bool `json:"enable"`
WebsiteSSLID uint `json:"websiteSSLId"`
Type string `json:"type" validate:"oneof=existed auto manual"`
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
ImportType string `json:"importType"`
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
HttpsPorts []int `json:"httpsPorts"`
Http3 bool `json:"http3"`
}
type WebsiteNginxUpdate struct {
ID uint `json:"id" validate:"required"`
Content string `json:"content" validate:"required"`
}
type WebsiteLogReq struct {
ID uint `json:"id" validate:"required"`
Operate string `json:"operate" validate:"required"`
LogType string `json:"logType" validate:"required"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
type WebsiteDefaultUpdate struct {
ID uint `json:"id"`
}
type WebsitePHPVersionReq struct {
WebsiteID uint `json:"websiteID" validate:"required"`
RuntimeID uint `json:"runtimeID"`
}
type WebsiteUpdateDir struct {
ID uint `json:"id" validate:"required"`
SiteDir string `json:"siteDir" validate:"required"`
}
type WebsiteUpdateDirPermission struct {
ID uint `json:"id" validate:"required"`
User string `json:"user" validate:"required"`
Group string `json:"group" validate:"required"`
}
type WebsiteProxyConfig struct {
ID uint `json:"id" validate:"required"`
Operate string `json:"operate" validate:"required"`
Enable bool `json:"enable" `
Cache bool `json:"cache" `
CacheTime int `json:"cacheTime"`
CacheUnit string `json:"cacheUnit"`
ServerCacheTime int `json:"serverCacheTime"`
ServerCacheUnit string `json:"serverCacheUnit"`
Name string `json:"name" validate:"required"`
Modifier string `json:"modifier"`
Match string `json:"match" validate:"required"`
ProxyPass string `json:"proxyPass" validate:"required"`
ProxyHost string `json:"proxyHost" validate:"required"`
Content string `json:"content"`
FilePath string `json:"filePath"`
Replaces map[string]string `json:"replaces"`
SNI bool `json:"sni"`
ProxySSLName string `json:"proxySSLName"`
}
type WebsiteProxyReq struct {
ID uint `json:"id" validate:"required"`
}
type WebsiteRedirectReq struct {
WebsiteID uint `json:"websiteId" validate:"required"`
}
type WebsiteCommonReq struct {
ID uint `json:"id" validate:"required"`
}
type WafWebsite struct {
Key string `json:"key"`
Domains []string `json:"domains"`
Host []string `json:"host"`
}
type WebsiteHtmlReq struct {
Type string `json:"type" validate:"required"`
}
type WebsiteHtmlUpdate struct {
Type string `json:"type" validate:"required"`
Content string `json:"content" validate:"required"`
}
type WebsiteLBCreate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Name string `json:"name" validate:"required"`
Algorithm string `json:"algorithm"`
Servers []dto.NginxUpstreamServer `json:"servers"`
}
type WebsiteLBUpdate struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Name string `json:"name" validate:"required"`
Algorithm string `json:"algorithm"`
Servers []dto.NginxUpstreamServer `json:"servers"`
}
type WebsiteLBDelete struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Name string `json:"name" validate:"required"`
}
type WebsiteLBUpdateFile struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Name string `json:"name" validate:"required"`
Content string `json:"content" validate:"required"`
}
type WebsiteRealIP struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Open bool `json:"open"`
IPFrom string `json:"ipFrom"`
IPHeader string `json:"ipHeader"`
IPOther string `json:"ipOther"`
}
type ChangeDatabase struct {
WebsiteID uint `json:"websiteID" validate:"required"`
DatabaseID uint `json:"databaseID" `
DatabaseType string `json:"databaseType" `
}
type WebsiteProxyDel struct {
ID uint `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
}
type CrossSiteAccessOp struct {
WebsiteID uint `json:"websiteID" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=Enable Disable"`
}
type ExecComposerReq struct {
Command string `json:"command" validate:"required"`
ExtCommand string `json:"extCommand"`
Mirror string `json:"mirror" validate:"required"`
Dir string `json:"dir" validate:"required"`
User string `json:"user" validate:"required"`
WebsiteID uint `json:"websiteID" validate:"required"`
TaskID string `json:"taskID" validate:"required"`
}
@@ -1,10 +0,0 @@
package response
type AppIgnoreUpgradeDTO struct {
ID uint `json:"ID"`
AppID uint `json:"appID"`
AppDetailID uint `json:"appDetailID"`
Scope string `json:"scope"`
Version string `json:"version"`
Name string `json:"name"`
}
-37
View File
@@ -1,37 +0,0 @@
package response
type DiskInfo struct {
DiskBasicInfo
Partitions []DiskBasicInfo `json:"partitions"`
}
type DiskBasicInfo struct {
Device string `json:"device"`
Size string `json:"size"`
Model string `json:"model"`
DiskType string `json:"diskType"`
IsRemovable bool `json:"isRemovable"`
IsSystem bool `json:"isSystem"`
Filesystem string `json:"filesystem"`
Used string `json:"used"`
Avail string `json:"avail"`
UsePercent int `json:"usePercent"`
MountPoint string `json:"mountPoint"`
IsMounted bool `json:"isMounted"`
Serial string `json:"serial"`
}
type CompleteDiskInfo struct {
Disks []DiskInfo `json:"disks"`
UnpartitionedDisks []DiskBasicInfo `json:"unpartitionedDisks"`
SystemDisk *DiskInfo `json:"systemDisk"`
TotalDisks int `json:"totalDisks"`
TotalCapacity int64 `json:"totalCapacity"`
}
type MountInfo struct {
Device string `json:"device"`
MountPoint string `json:"mountPoint"`
Filesystem string `json:"filesystem"`
Options string `json:"options"`
}
-26
View File
@@ -1,26 +0,0 @@
package response
import (
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/model"
)
type McpServersRes struct {
Items []McpServerDTO `json:"items"`
Total int64 `json:"total"`
}
type McpServerDTO struct {
model.McpServer
Environments []request.Environment `json:"environments"`
Volumes []request.Volume `json:"volumes"`
}
type McpBindDomainRes struct {
Domain string `json:"domain"`
SSLID uint `json:"sslID"`
AcmeAccountID uint `json:"acmeAccountID"`
AllowIPs []string `json:"allowIPs"`
WebsiteID uint `json:"websiteID"`
ConnUrl string `json:"connUrl"`
}
-85
View File
@@ -1,85 +0,0 @@
package response
import (
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/model"
)
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 string `json:"port"`
Path string `json:"path"`
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
Environments []request.Environment `json:"environments"`
Volumes []request.Volume `json:"volumes"`
ContainerStatus string `json:"containerStatus"`
Container string `json:"container"`
Remark string `json:"remark"`
}
type PackageScripts struct {
Name string `json:"name"`
Script string `json:"script"`
}
func NewRuntimeDTO(runtime model.Runtime) RuntimeDTO {
return RuntimeDTO{
ID: runtime.ID,
Name: runtime.Name,
Resource: runtime.Resource,
AppDetailID: runtime.AppDetailID,
Status: runtime.Status,
Type: runtime.Type,
Image: runtime.Image,
Message: runtime.Message,
CreatedAt: runtime.CreatedAt,
CodeDir: runtime.CodeDir,
Version: runtime.Version,
Port: runtime.Port,
Path: runtime.GetPath(),
Container: runtime.ContainerName,
Remark: runtime.Remark,
}
}
type NodeModule struct {
Name string `json:"name"`
Version string `json:"version"`
License string `json:"license"`
Description string `json:"description"`
}
type SupportExtension struct {
Name string `json:"name"`
Description string `json:"description"`
Installed bool `json:"installed"`
Check string `json:"check"`
Versions []string `json:"versions"`
File string `json:"file"`
}
type PHPExtensionRes struct {
Extensions []string `json:"extensions"`
SupportExtensions []SupportExtension `json:"supportExtensions"`
}
type FpmStatusItem struct {
Key string `json:"key"`
Value interface{} `json:"value"`
}
-8
View File
@@ -1,8 +0,0 @@
package response
type ComponentInfo struct {
Exists bool `json:"exists"`
Version string `json:"version"`
Path string `json:"path"`
Error string `json:"error"`
}
-1
View File
@@ -1 +0,0 @@
package response
-80
View File
@@ -1,80 +0,0 @@
package dto
type SettingInfo struct {
DockerSockPath string `json:"dockerSockPath"`
SystemVersion string `json:"systemVersion"`
SystemIP string `json:"systemIP"`
LocalTime string `json:"localTime"`
TimeZone string `json:"timeZone"`
NtpSite string `json:"ntpSite"`
DefaultNetwork string `json:"defaultNetwork"`
LastCleanTime string `json:"lastCleanTime"`
LastCleanSize string `json:"lastCleanSize"`
LastCleanData string `json:"lastCleanData"`
MonitorStatus string `json:"monitorStatus"`
MonitorInterval string `json:"monitorInterval"`
MonitorStoreDays string `json:"monitorStoreDays"`
AppStoreVersion string `json:"appStoreVersion"`
AppStoreLastModified string `json:"appStoreLastModified"`
AppStoreSyncStatus string `json:"appStoreSyncStatus"`
FileRecycleBin string `json:"fileRecycleBin"`
}
type SettingUpdate struct {
Key string `json:"key" validate:"required"`
Value string `json:"value"`
}
type SyncTime struct {
NtpSite string `json:"ntpSite" validate:"required"`
}
type CleanData struct {
SystemClean []CleanTree `json:"systemClean"`
UploadClean []CleanTree `json:"uploadClean"`
DownloadClean []CleanTree `json:"downloadClean"`
SystemLogClean []CleanTree `json:"systemLogClean"`
ContainerClean []CleanTree `json:"containerClean"`
}
type CleanTree struct {
ID string `json:"id"`
Label string `json:"label"`
Children []CleanTree `json:"children"`
Type string `json:"type"`
Name string `json:"name"`
Size uint64 `json:"size"`
IsCheck bool `json:"isCheck"`
IsRecommend bool `json:"isRecommend"`
}
type Clean struct {
TreeType string `json:"treeType"`
Name string `json:"name"`
Size uint64 `json:"size"`
}
type SSHConnData struct {
Addr string `json:"addr" validate:"required"`
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
User string `json:"user" validate:"required"`
AuthMode string `json:"authMode" validate:"oneof=password key"`
Password string `json:"password"`
PrivateKey string `json:"privateKey"`
PassPhrase string `json:"passPhrase"`
}
type SystemProxy struct {
Type string `json:"type"`
URL string `json:"url"`
Port string `json:"port"`
User string `json:"user"`
Password string `json:"password"`
}
-105
View File
@@ -1,105 +0,0 @@
package dto
import "time"
type PageSnapshot struct {
PageInfo
Info string `json:"info"`
OrderBy string `json:"orderBy" validate:"required,oneof=name createdAt"`
Order string `json:"order" validate:"required,oneof=null ascending descending"`
}
type SnapshotCreate struct {
ID uint `json:"id"`
Name string `json:"name"`
TaskID string `json:"taskID"`
SourceAccountIDs string `json:"sourceAccountIDs" validate:"required"`
DownloadAccountID uint `json:"downloadAccountID" validate:"required"`
Description string `json:"description" validate:"max=256"`
Secret string `json:"secret"`
InterruptStep string `json:"interruptStep"`
Timeout uint `json:"timeout"`
AppData []DataTree `json:"appData"`
BackupData []DataTree `json:"backupData"`
PanelData []DataTree `json:"panelData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles []string `json:"ignoreFiles"`
}
type SnapshotData struct {
AppData []DataTree `json:"appData"`
BackupData []DataTree `json:"backupData"`
PanelData []DataTree `json:"panelData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles []string `json:"ignoreFiles"`
}
type DataTree struct {
ID string `json:"id"`
Label string `json:"label"`
Key string `json:"key"`
Name string `json:"name"`
Size uint64 `json:"size"`
IsCheck bool `json:"isCheck"`
IsDisable bool `json:"isDisable"`
Path string `json:"path"`
RelationItemID string `json:"relationItemID"`
Children []DataTree `json:"children"`
}
type SnapshotRecover struct {
IsNew bool `json:"isNew"`
ReDownload bool `json:"reDownload"`
ID uint `json:"id" validate:"required"`
TaskID string `json:"taskID"`
Secret string `json:"secret"`
}
type SnapshotBatchDelete struct {
DeleteWithFile bool `json:"deleteWithFile"`
Ids []uint `json:"ids" validate:"required"`
}
type SnapshotImport struct {
BackupAccountID uint `json:"backupAccountID"`
Names []string `json:"names"`
Description string `json:"description" validate:"max=256"`
}
type SnapshotInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Description string `json:"description" validate:"max=256"`
SourceAccounts []string `json:"sourceAccounts"`
DownloadAccount string `json:"downloadAccount"`
Status string `json:"status"`
Message string `json:"message"`
CreatedAt time.Time `json:"createdAt"`
Version string `json:"version"`
Size int64 `json:"size"`
TaskID string `json:"taskID"`
TaskRecoverID string `json:"taskRecoverID"`
TaskRollbackID string `json:"taskRollbackID"`
InterruptStep string `json:"interruptStep"`
RecoverStatus string `json:"recoverStatus"`
RecoverMessage string `json:"recoverMessage"`
LastRecoveredAt string `json:"lastRecoveredAt"`
RollbackStatus string `json:"rollbackStatus"`
RollbackMessage string `json:"rollbackMessage"`
LastRollbackedAt string `json:"lastRollbackedAt"`
}
-55
View File
@@ -1,55 +0,0 @@
package model
type Alert struct {
BaseModel
Title string `gorm:"type:varchar(256);not null" json:"title"`
Type string `gorm:"type:varchar(64);not null" json:"type"`
Cycle uint `gorm:"type:integer;not null" json:"cycle"`
Count uint `gorm:"type:integer;not null" json:"count"`
Project string `gorm:"type:varchar(64)" json:"project"`
Status string `gorm:"type:varchar(64);not null" json:"status"`
Method string `gorm:"type:varchar(64);not null" json:"method"`
SendCount uint `gorm:"type:integer" json:"sendCount"`
AdvancedParams string `gorm:"type:longText" json:"advancedParam"`
}
type AlertTask struct {
BaseModel
Type string `gorm:"type:varchar(64);not null" json:"type"`
Quota string `gorm:"type:varchar(64)" json:"quota"`
QuotaType string `gorm:"type:varchar(64)" json:"quotaType"`
Method string `gorm:"type:varchar(64);not null;default:'sms'" json:"method"`
}
type AlertLog struct {
BaseModel
Type string `gorm:"type:varchar(64);not null" json:"type"`
Status string `gorm:"type:varchar(64);not null" json:"status"`
AlertId uint `gorm:"type:integer;not null" json:"alertId"`
AlertDetail string `gorm:"type:varchar(256);not null" json:"alertDetail"`
AlertRule string `gorm:"type:varchar(256);not null" json:"alertRule"`
Count uint `gorm:"type:integer;not null" json:"count"`
Message string `gorm:"type:varchar(256);" json:"message"`
RecordId uint `gorm:"type:integer;" json:"recordId"`
LicenseId string `gorm:"type:varchar(256);not null;" json:"licenseId" `
Method string `gorm:"type:varchar(64);not null;default:'sms'" json:"method"`
}
type AlertConfig struct {
BaseModel
Type string `gorm:"type:varchar(64);not null" json:"type"`
Title string `gorm:"type:varchar(64);not null" json:"title"`
Status string `gorm:"type:varchar(64);not null" json:"status"`
Config string `gorm:"type:varchar(256);not null" json:"config"`
}
type LoginLog struct {
BaseModel
IP string `json:"ip"`
Address string `json:"address"`
Agent string `json:"agent"`
Status string `json:"status"`
Message string `json:"message"`
}
-76
View File
@@ -1,76 +0,0 @@
package model
import (
"encoding/json"
"github.com/gin-gonic/gin"
"path/filepath"
"strings"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
)
type App struct {
BaseModel
Name string `json:"name" gorm:"not null"`
Key string `json:"key" gorm:"not null;"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
Description string `json:"description"`
Icon string `json:"icon"`
Type string `json:"type" gorm:"not null"`
Status string `json:"status" gorm:"not null"`
Required string `json:"required"`
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
Limit int `json:"limit" gorm:"not null"`
Website string `json:"website" gorm:"not null"`
Github string `json:"github" gorm:"not null"`
Document string `json:"document" gorm:"not null"`
Recommend int `json:"recommend" gorm:"not null"`
Resource string `json:"resource" gorm:"not null;default:remote"`
ReadMe string `json:"readMe"`
LastModified int `json:"lastModified"`
Architectures string `json:"architectures"`
MemoryRequired int `json:"memoryRequired"`
GpuSupport bool `json:"gpuSupport"`
RequiredPanelVersion float64 `json:"requiredPanelVersion"`
Details []AppDetail `json:"-" gorm:"-:migration"`
TagsKey []string `json:"tags" yaml:"tags" gorm:"-"`
AppTags []AppTag `json:"-" gorm:"-:migration"`
}
func (i *App) IsLocalApp() bool {
return i.Resource == constant.ResourceLocal
}
func (i *App) GetAppResourcePath() string {
if i.IsLocalApp() {
//这里要去掉本地应用的local前缀
return filepath.Join(global.Dir.LocalAppResourceDir, strings.TrimPrefix(i.Key, "local"))
}
return filepath.Join(global.Dir.RemoteAppResourceDir, i.Key)
}
func getLang(c *gin.Context) string {
lang := c.GetHeader("Accept-Language")
if lang == "" {
lang = "en"
}
return lang
}
func (i *App) GetDescription(ctx *gin.Context) string {
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(i.Description), &translations)
lang := strings.ToLower(getLang(ctx))
if desc, ok := translations[lang]; ok && desc != "" {
return desc
}
if lang == "zh" && i.ShortDescZh != "" {
return i.ShortDescZh
}
if desc, ok := translations["en"]; ok && desc != "" {
return desc
}
return i.ShortDescEn
}
-15
View File
@@ -1,15 +0,0 @@
package model
type AppDetail struct {
BaseModel
AppId uint `json:"appId" gorm:"not null"`
Version string `json:"version" gorm:"not null"`
Params string `json:"-"`
DockerCompose string `json:"dockerCompose"`
Status string `json:"status" gorm:"not null"`
LastVersion string `json:"lastVersion"`
LastModified int `json:"lastModified"`
DownloadUrl string `json:"downloadUrl"`
DownloadCallBackUrl string `json:"downloadCallBackUrl"`
Update bool `json:"update"`
}
-8
View File
@@ -1,8 +0,0 @@
package model
type AppIgnoreUpgrade struct {
BaseModel
AppID uint `json:"appID"`
AppDetailID uint `json:"appDetailID"`
Scope string `json:"scope"`
}
-51
View File
@@ -1,51 +0,0 @@
package model
import (
"path"
"strings"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
)
type AppInstall struct {
BaseModel
Name string `json:"name" gorm:"not null;UNIQUE"`
AppId uint `json:"appId" gorm:"not null"`
AppDetailId uint `json:"appDetailId" gorm:"not null"`
Version string `json:"version" gorm:"not null"`
Param string `json:"param"`
Env string `json:"env"`
DockerCompose string `json:"dockerCompose" `
Status string `json:"status" gorm:"not null"`
Description string `json:"description"`
Message string `json:"message"`
ContainerName string `json:"containerName" gorm:"not null"`
ServiceName string `json:"serviceName" gorm:"not null"`
HttpPort int `json:"httpPort"`
HttpsPort int `json:"httpsPort"`
WebUI string `json:"webUI"`
Favorite bool `json:"favorite"`
App App `json:"app" gorm:"-:migration"`
}
func (i *AppInstall) GetPath() string {
return path.Join(i.GetAppPath(), i.Name)
}
func (i *AppInstall) GetComposePath() string {
return path.Join(i.GetAppPath(), i.Name, "docker-compose.yml")
}
func (i *AppInstall) GetEnvPath() string {
return path.Join(i.GetAppPath(), i.Name, ".env")
}
func (i *AppInstall) GetAppPath() string {
if i.App.Resource == constant.AppResourceLocal {
return path.Join(global.Dir.LocalAppInstallDir, strings.TrimPrefix(i.App.Key, constant.AppResourceLocal))
} else {
return path.Join(global.Dir.AppInstallDir, i.App.Key)
}
}
-10
View File
@@ -1,10 +0,0 @@
package model
type AppInstallResource struct {
BaseModel
AppInstallId uint `json:"appInstallId" gorm:"not null;"`
LinkId uint `json:"linkId" gorm:"not null;"`
ResourceId uint `json:"resourceId"`
Key string `json:"key" gorm:"not null"`
From string `json:"from" gorm:"not null;default:local"`
}
-16
View File
@@ -1,16 +0,0 @@
package model
type AppLauncher struct {
BaseModel
Key string `json:"key"`
}
type QuickJump struct {
BaseModel
Name string `json:"name"`
Title string `json:"title"`
Detail string `json:"detail"`
Recommend int `json:"recommend"`
IsShow bool `json:"isShow"`
Router string `json:"router"`
}
-7
View File
@@ -1,7 +0,0 @@
package model
type AppTag struct {
BaseModel
AppId uint `json:"appId" gorm:"not null"`
TagId uint `json:"tagId" gorm:"not null"`
}
-31
View File
@@ -1,31 +0,0 @@
package model
type BackupAccount struct {
BaseModel
Name string `gorm:"not null;default:''" json:"name"`
Type string `gorm:"not null;default:''" json:"type"`
IsPublic bool `json:"isPublic"`
Bucket string `json:"bucket"`
AccessKey string `json:"accessKey"`
Credential string `json:"credential"`
BackupPath string `json:"backupPath"`
Vars string `json:"vars"`
RememberAuth bool `json:"rememberAuth"`
}
type BackupRecord struct {
BaseModel
From string `json:"from"`
CronjobID uint `json:"cronjobID"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
Type string `gorm:"not null;default:''" json:"type"`
Name string `gorm:"not null;default:''" json:"name"`
DetailName string `json:"detailName"`
FileDir string `json:"fileDir"`
FileName string `json:"fileName"`
Description string `json:"description"`
}
-31
View File
@@ -1,31 +0,0 @@
package model
import "time"
type Clam struct {
BaseModel
Name string `gorm:"not null" json:"name"`
Path string `gorm:"not null" json:"path"`
InfectedStrategy string `json:"infectedStrategy"`
InfectedDir string `json:"infectedDir"`
Spec string `json:"spec"`
EntryID int `json:"entryID"`
Description string `json:"description"`
Status string `json:"status"`
IsExecuting bool `json:"isExecuting"`
}
type ClamRecord struct {
BaseModel
ClamID uint `json:"clamID"`
TaskID string `json:"taskID"`
StartTime time.Time `json:"startTime"`
ScanTime string `json:"scanTime"`
InfectedFiles string `json:"infectedFiles"`
TotalError string `json:"totalError"`
Status string `json:"status"`
Message string `json:"message"`
}
-16
View File
@@ -1,16 +0,0 @@
package model
type ComposeTemplate struct {
BaseModel
Name string `gorm:"not null;unique" json:"name"`
Description string `json:"description"`
Content string `json:"content"`
}
type Compose struct {
BaseModel
Name string `json:"name"`
Path string `json:"path"`
}
-66
View File
@@ -1,66 +0,0 @@
package model
import (
"time"
)
type Cronjob struct {
BaseModel
Name string `gorm:"not null" json:"name"`
Type string `gorm:"not null" json:"type"`
GroupID uint `json:"groupID"`
SpecCustom bool `json:"specCustom"`
Spec string `gorm:"not null" json:"spec"`
Executor string `json:"executor"`
Command string `json:"command"`
ContainerName string `json:"containerName"`
ScriptMode string `json:"scriptMode"`
Script string `json:"script"`
User string `json:"user"`
ScriptID uint `json:"scriptID"`
Website string `json:"website"`
AppID string `json:"appID"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
SnapshotRule string `json:"snapshotRule"`
ExclusionRules string `json:"exclusionRules"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
RetryTimes uint `json:"retryTimes"`
Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
RetainCopies uint64 `json:"retainCopies"`
IsExecuting bool `json:"isExecuting"`
Status string `json:"status"`
EntryIDs string `json:"entryIDs"`
Records []JobRecords `json:"records"`
Secret string `json:"secret"`
}
type JobRecords struct {
BaseModel
CronjobID uint `json:"cronjobID"`
TaskID string `json:"taskID"`
StartTime time.Time `json:"startTime"`
Interval float64 `json:"interval"`
Records string `json:"records"`
FromLocal bool `json:"source"`
File string `json:"file"`
Status string `json:"status"`
Message string `json:"message"`
}
type ScriptLibrary struct {
BaseModel
Name string `json:"name" gorm:"not null;"`
Script string `json:"script" gorm:"not null;"`
}
-23
View File
@@ -1,23 +0,0 @@
package model
type Database struct {
BaseModel
AppInstallID uint `json:"appInstallID"`
Name string `json:"name" gorm:"not null;unique"`
Type string `json:"type" gorm:"not null"`
Version string `json:"version" gorm:"not null"`
From string `json:"from" gorm:"not null"`
Address string `json:"address" gorm:"not null"`
Port uint `json:"port" gorm:"not null"`
Username string `json:"username"`
Password string `json:"password"`
SSL bool `json:"ssl"`
RootCert string `json:"rootCert"`
ClientKey string `json:"clientKey"`
ClientCert string `json:"clientCert"`
SkipVerify bool `json:"skipVerify"`
Timeout uint `json:"timeout"`
Description string `json:"description"`
}
-14
View File
@@ -1,14 +0,0 @@
package model
type DatabaseMysql struct {
BaseModel
Name string `json:"name" gorm:"not null"`
From string `json:"from" gorm:"not null;default:local"`
MysqlName string `json:"mysqlName" gorm:"not null"`
Format string `json:"format" gorm:"not null"`
Username string `json:"username" gorm:"not null"`
Password string `json:"password" gorm:"not null"`
Permission string `json:"permission" gorm:"not null"`
IsDelete bool `json:"isDelete"`
Description string `json:"description"`
}
-14
View File
@@ -1,14 +0,0 @@
package model
type DatabasePostgresql struct {
BaseModel
Name string `json:"name" gorm:"not null"`
From string `json:"from" gorm:"not null;default:local"`
PostgresqlName string `json:"postgresqlName" gorm:"not null"`
Format string `json:"format" gorm:"not null"`
Username string `json:"username" gorm:"not null"`
Password string `json:"password" gorm:"not null"`
SuperUser bool `json:"superUser"`
IsDelete bool `json:"isDelete"`
Description string `json:"description"`
}
-10
View File
@@ -1,10 +0,0 @@
package model
type Favorite struct {
BaseModel
Name string `gorm:"not null;" json:"name" `
Path string `gorm:"not null;unique" json:"path"`
Type string `json:"type"`
IsDir bool `json:"isDir"`
IsTxt bool `json:"isTxt"`
}
-21
View File
@@ -1,21 +0,0 @@
package model
type Firewall struct {
BaseModel
Type string `gorm:"not null" json:"type"`
Port string `gorm:"not null" json:"port"`
Protocol string `gorm:"not null" json:"protocol"`
Address string `gorm:"not null" json:"address"`
Strategy string `gorm:"not null" json:"strategy"`
Description string `gorm:"not null" json:"description"`
}
type Forward struct {
BaseModel
Protocol string `gorm:"not null" json:"protocol"`
Port string `gorm:"not null" json:"port"`
TargetIP string `gorm:"not null" json:"targetIP"`
TargetPort string `gorm:"not null" json:"targetPort"`
}
-11
View File
@@ -1,11 +0,0 @@
package model
type Ftp struct {
BaseModel
User string `gorm:"not null" json:"user"`
Password string `gorm:"not null" json:"password"`
Status string `gorm:"not null" json:"status"`
Path string `gorm:"not null" json:"path"`
Description string `gorm:"not null" json:"description"`
}
-8
View File
@@ -1,8 +0,0 @@
package model
type Group struct {
BaseModel
IsDefault bool `json:"isDefault"`
Name string `json:"name"`
Type string `json:"type"`
}
-15
View File
@@ -1,15 +0,0 @@
package model
type ImageRepo struct {
BaseModel
Name string `gorm:"not null" json:"name"`
DownloadUrl string `json:"downloadUrl"`
Protocol string `json:"protocol"`
Username string `json:"username"`
Password string `json:"password"`
Auth bool `json:"auth"`
Status string `json:"status"`
Message string `json:"message"`
}
-21
View File
@@ -1,21 +0,0 @@
package model
type McpServer struct {
BaseModel
Name string `json:"name"`
DockerCompose string `json:"dockerCompose"`
Command string `json:"command"`
ContainerName string `json:"containerName"`
Message string `json:"message"`
Port int `json:"port"`
Status string `json:"status"`
Env string `json:"env"`
BaseURL string `json:"baseUrl"`
SsePath string `json:"ssePath"`
WebsiteID int `json:"websiteID"`
Dir string `json:"dir"`
HostIP string `json:"hostIP"`
StreamableHttpPath string `json:"streamableHttpPath"`
OutputTransport string `json:"outputTransport"`
Type string `json:"type"`
}
-29
View File
@@ -1,29 +0,0 @@
package model
type MonitorBase struct {
BaseModel
Cpu float64 `json:"cpu"`
LoadUsage float64 `json:"loadUsage"`
CpuLoad1 float64 `json:"cpuLoad1"`
CpuLoad5 float64 `json:"cpuLoad5"`
CpuLoad15 float64 `json:"cpuLoad15"`
Memory float64 `json:"memory"`
}
type MonitorIO struct {
BaseModel
Name string `json:"name"`
Read uint64 `json:"read"`
Write uint64 `json:"write"`
Count uint64 `json:"count"`
Time uint64 `json:"time"`
}
type MonitorNetwork struct {
BaseModel
Name string `json:"name"`
Up float64 `json:"up"`
Down float64 `json:"down"`
}
-51
View File
@@ -1,51 +0,0 @@
package model
import (
"path"
"github.com/1Panel-dev/1Panel/agent/global"
)
type Runtime struct {
BaseModel
Name string `gorm:"not null" json:"name"`
AppDetailID uint `json:"appDetailID"`
Image string `json:"image"`
WorkDir string `json:"workDir"`
DockerCompose string `json:"dockerCompose"`
Env string `json:"env"`
Params string `json:"params"`
Version string `gorm:"not null" json:"version"`
Type string `gorm:"not null" json:"type"`
Status string `gorm:"not null" json:"status"`
Resource string `gorm:"not null" json:"resource"`
Port string `json:"port"`
Message string `json:"message"`
CodeDir string `json:"codeDir"`
ContainerName string `json:"containerName"`
Remark string `json:"remark"`
}
func (r *Runtime) GetComposePath() string {
return path.Join(r.GetPath(), "docker-compose.yml")
}
func (r *Runtime) GetEnvPath() string {
return path.Join(r.GetPath(), ".env")
}
func (r *Runtime) GetPath() string {
return path.Join(global.Dir.RuntimeDir, r.Type, r.Name)
}
func (r *Runtime) GetFPMPath() string {
return path.Join(global.Dir.RuntimeDir, r.Type, r.Name, "conf", "php-fpm.conf")
}
func (r *Runtime) GetPHPPath() string {
return path.Join(global.Dir.RuntimeDir, r.Type, r.Name, "conf", "php.ini")
}
func (r *Runtime) GetLogPath() string {
return path.Join(r.GetPath(), "build.log")
}
-27
View File
@@ -1,27 +0,0 @@
package model
type Setting struct {
BaseModel
Key string `json:"key" gorm:"not null;"`
Value string `json:"value"`
About string `json:"about"`
}
type NodeInfo struct {
Scope string `json:"scope"`
BaseDir string `json:"baseDir"`
NodePort uint `json:"nodePort"`
Version string `json:"version"`
ServerCrt string `json:"serverCrt"`
ServerKey string `json:"serverKey"`
}
type LocalConnInfo struct {
Addr string `json:"addr"`
Port uint `json:"port"`
User string `json:"user"`
AuthMode string `json:"authMode"`
Password string `json:"password"`
PrivateKey string `json:"privateKey"`
PassPhrase string `json:"passPhrase"`
}
-36
View File
@@ -1,36 +0,0 @@
package model
type Snapshot struct {
BaseModel
Name string `json:"name" gorm:"not null;unique"`
Secret string `json:"secret"`
Description string `json:"description"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
Status string `json:"status"`
Message string `json:"message"`
Version string `json:"version"`
Timeout uint `json:"timeout"`
TaskID string `json:"taskID"`
TaskRecoverID string `json:"taskRecoverID"`
TaskRollbackID string `json:"taskRollbackID"`
AppData string `json:"appData"`
PanelData string `json:"panelData"`
BackupData string `json:"backupData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles string `json:"ignoreFiles"`
InterruptStep string `json:"interruptStep"`
RecoverStatus string `json:"recoverStatus"`
RecoverMessage string `json:"recoverMessage"`
RollbackStatus string `json:"rollbackStatus"`
RollbackMessage string `json:"rollbackMessage"`
}
-11
View File
@@ -1,11 +0,0 @@
package model
type RootCert struct {
BaseModel
Name string `json:"name" gorm:"not null;"`
EncryptionMode string `json:"encryptionMode"`
PassPhrase string `json:"passPhrase"`
PublicKeyPath string `json:"publicKeyPath"`
PrivateKeyPath string `json:"privateKeyPath"`
Description string `json:"description"`
}
-9
View File
@@ -1,9 +0,0 @@
package model
type Tag struct {
BaseModel
Key string `json:"key" gorm:"not null"`
Name string `json:"name" gorm:"not null"`
Sort int `json:"sort" gorm:"not null;default:1"`
Translations string `json:"translations"`
}
-18
View File
@@ -1,18 +0,0 @@
package model
import "time"
type Task struct {
ID string `gorm:"primarykey;" json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Operate string `json:"operate"`
LogFile string `json:"logFile"`
Status string `json:"status"`
ErrorMsg string `json:"errorMsg"`
OperationLogID uint `json:"operationLogID"`
ResourceID uint `json:"resourceID"`
CurrentStep string `json:"currentStep"`
EndAt time.Time `json:"endAt"`
CreatedAt time.Time `json:"createdAt"`
}
-46
View File
@@ -1,46 +0,0 @@
package model
import "time"
type Website struct {
BaseModel
Protocol string `gorm:"not null" json:"protocol"`
PrimaryDomain string `gorm:"not null" json:"primaryDomain"`
Type string `gorm:"not null" json:"type"`
Alias string `gorm:"not null" json:"alias"`
Remark string `json:"remark"`
Status string `gorm:"not null" json:"status"`
HttpConfig string `gorm:"not null" json:"httpConfig"`
ExpireDate time.Time `json:"expireDate"`
Proxy string `json:"proxy"`
ProxyType string `json:"proxyType"`
SiteDir string `json:"siteDir"`
ErrorLog bool `json:"errorLog"`
AccessLog bool `json:"accessLog"`
DefaultServer bool `json:"defaultServer"`
IPV6 bool `json:"IPV6"`
Rewrite string `json:"rewrite"`
WebsiteGroupID uint `json:"webSiteGroupId"`
WebsiteSSLID uint `json:"webSiteSSLId"`
RuntimeID uint `json:"runtimeID"`
AppInstallID uint `json:"appInstallId"`
FtpID uint `json:"ftpId"`
ParentWebsiteID uint `json:"parentWebsiteID"`
User string `json:"user"`
Group string `json:"group"`
DbType string `json:"dbType"`
DbID uint `json:"dbID"`
Favorite bool `json:"favorite"`
Domains []WebsiteDomain `json:"domains" gorm:"-:migration"`
WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"`
}
func (w Website) TableName() string {
return "websites"
}
-12
View File
@@ -1,12 +0,0 @@
package model
type WebsiteDnsAccount struct {
BaseModel
Name string `gorm:"not null" json:"name"`
Type string `gorm:"not null" json:"type"`
Authorization string `gorm:"not null" json:"-"`
}
func (w WebsiteDnsAccount) TableName() string {
return "website_dns_accounts"
}
-13
View File
@@ -1,13 +0,0 @@
package model
type WebsiteDomain struct {
BaseModel
WebsiteID uint `gorm:"column:website_id;not null;" json:"websiteId"`
Domain string `gorm:"not null" json:"domain"`
SSL bool `json:"ssl"`
Port int `json:"port"`
}
func (w WebsiteDomain) TableName() string {
return "website_domains"
}
-337
View File
@@ -1,337 +0,0 @@
package repo
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"google.golang.org/genproto/googleapis/type/date"
"gorm.io/gorm"
"time"
)
type AlertRepo struct{}
type IAlertRepo interface {
WithByType(alertType string) DBOption
WithByStatusIn(status []string) DBOption
WithByProject(project string) DBOption
WithByCount(count uint) DBOption
WithByAlertId(alertId uint) DBOption
WithByCreateAt(date *date.Date) DBOption
WithByLicenseId(licenseId string) DBOption
WithByRecordId(recordId uint) DBOption
WithByMethod(method string) DBOption
Create(alert *model.Alert) error
Get(opts ...DBOption) (model.Alert, error)
Page(page, size int, opts ...DBOption) (int64, []model.Alert, error)
List(opts ...DBOption) ([]model.Alert, error)
Delete(opts ...DBOption) error
Save(alert *model.Alert) error
Update(maps map[string]interface{}, opts ...DBOption) error
GetLog(opts ...DBOption) (model.AlertLog, error)
CreateLog(alertLog *model.AlertLog) error
PageLog(limit, offset int, opts ...DBOption) (int64, []model.AlertLog, error)
ListLog(opts ...DBOption) ([]model.AlertLog, error)
UpdateLog(id uint, maps map[string]interface{}) error
BatchUpdateLogBy(maps map[string]interface{}, opts ...DBOption) error
DeleteLog(opts ...DBOption) error
CleanAlertLogs() error
CreateAlertTask(alertTaskBase *model.AlertTask) error
DeleteAlertTask(opts ...DBOption) error
GetAlertTask(opts ...DBOption) (model.AlertTask, error)
LoadTaskCount(alertType string, project string, method string) (uint, uint, error)
GetTaskLog(alertType string, alertId uint) (time.Time, error)
GetLicensePushCount(method string) (uint, error)
GetConfig(opts ...DBOption) (model.AlertConfig, error)
AlertConfigList(opts ...DBOption) ([]model.AlertConfig, error)
UpdateAlertConfig(maps map[string]interface{}, opts ...DBOption) error
CreateAlertConfig(config *model.AlertConfig) error
DeleteAlertConfig(opts ...DBOption) error
SyncAll(data []model.AlertConfig) error
}
func NewIAlertRepo() IAlertRepo {
return &AlertRepo{}
}
func (a *AlertRepo) WithByType(alertType string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("`type` = ?", alertType)
}
}
func (a *AlertRepo) WithByStatusIn(status []string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("status in (?)", status)
}
}
func (a *AlertRepo) WithByCount(count uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("count = ?", count)
}
}
func (a *AlertRepo) WithByProject(project string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("project = ?", project)
}
}
func (a *AlertRepo) WithByAlertId(alertId uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("alert_id = ?", alertId)
}
}
func (a *AlertRepo) WithByLicenseId(licenseId string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("license_id = ?", licenseId)
}
}
func (a *AlertRepo) WithByRecordId(recordId uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("record_id = ?", recordId)
}
}
func (a *AlertRepo) WithByMethod(method string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("method = ?", method)
}
}
func (a *AlertRepo) WithByCreateAt(createAt *date.Date) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("DATE(created_at) = DATE(?)", createAt)
}
}
func (a *AlertRepo) Create(alert *model.Alert) error {
return global.AlertDB.Model(&model.Alert{}).Create(alert).Error
}
func (a *AlertRepo) Save(alert *model.Alert) error {
return global.AlertDB.Save(alert).Error
}
func (a *AlertRepo) Get(opts ...DBOption) (model.Alert, error) {
var alert model.Alert
db, _ := getAlertDB(opts...)
err := db.First(&alert).Error
return alert, err
}
func (a *AlertRepo) Page(page, size int, opts ...DBOption) (int64, []model.Alert, error) {
var alerts []model.Alert
alertDb, _ := getAlertDB(opts...)
db := alertDb.Model(&model.Alert{})
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&alerts).Error
return count, alerts, err
}
func (a *AlertRepo) List(opts ...DBOption) ([]model.Alert, error) {
var alert []model.Alert
db, _ := getAlertDB(opts...)
err := db.Find(&alert).Error
return alert, err
}
func (a *AlertRepo) Update(maps map[string]interface{}, opts ...DBOption) error {
db, _ := getAlertDB(opts...)
return db.Model(&model.Alert{}).Updates(maps).Error
}
func (a *AlertRepo) Delete(opts ...DBOption) error {
db, _ := getAlertDB(opts...)
return db.Delete(&model.Alert{}).Error
}
func (a *AlertRepo) GetLog(opts ...DBOption) (model.AlertLog, error) {
var alertLog model.AlertLog
db, _ := getAlertDB(opts...)
err := db.First(&alertLog).Error
return alertLog, err
}
func (a *AlertRepo) CreateLog(log *model.AlertLog) error {
return global.AlertDB.Model(&model.AlertLog{}).Create(&log).Error
}
func (a *AlertRepo) UpdateLog(id uint, maps map[string]interface{}) error {
return global.AlertDB.Model(&model.AlertLog{}).Where("id = ?", id).Updates(maps).Error
}
func (a *AlertRepo) BatchUpdateLogBy(maps map[string]interface{}, opts ...DBOption) error {
db, _ := getAlertDB(opts...)
if len(opts) == 0 {
db = db.Where("1=1")
}
return db.Model(&model.AlertLog{}).Updates(&maps).Error
}
func (a *AlertRepo) PageLog(page, size int, opts ...DBOption) (int64, []model.AlertLog, error) {
var alerts []model.AlertLog
db := global.AlertDB.Model(&model.AlertLog{})
for _, opt := range opts {
db = opt(db)
}
count := int64(0)
db = db.Order("created_at desc").Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&alerts).Error
return count, alerts, err
}
func (a *AlertRepo) ListLog(opts ...DBOption) ([]model.AlertLog, error) {
var alertLog []model.AlertLog
db, _ := getAlertDB(opts...)
err := db.Find(&alertLog).Error
return alertLog, err
}
func (a *AlertRepo) DeleteLog(opts ...DBOption) error {
db, _ := getAlertDB(opts...)
return db.Delete(&model.AlertLog{}).Error
}
func (a *AlertRepo) CleanAlertLogs() error {
return global.AlertDB.Where("1 = 1").Delete(&model.AlertLog{}).Error
}
func (a *AlertRepo) CreateAlertTask(alertTaskBase *model.AlertTask) error {
return global.AlertDB.Model(&model.AlertTask{}).Create(&alertTaskBase).Error
}
func (a *AlertRepo) DeleteAlertTask(opts ...DBOption) error {
db, _ := getAlertDB(opts...)
return db.Delete(&model.AlertTask{}).Error
}
func (a *AlertRepo) GetAlertTask(opts ...DBOption) (model.AlertTask, error) {
var data model.AlertTask
db, _ := getAlertDB(opts...)
err := db.First(&data).Error
return data, err
}
func (a *AlertRepo) LoadTaskCount(alertType string, project string, method string) (uint, uint, error) {
var (
todayCount int64
totalCount int64
)
_ = global.AlertDB.Model(&model.AlertTask{}).Where("type = ? AND quota_type = ? AND method = ?", alertType, project, method).Count(&totalCount).Error
now := time.Now()
todayMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
tomorrowMidnight := todayMidnight.Add(24 * time.Hour)
err := global.AlertDB.Model(&model.AlertTask{}).Where("type = ? AND quota_type = ? AND method = ? AND created_at > ? AND created_at < ?", alertType, project, method, todayMidnight, tomorrowMidnight).Count(&todayCount).Error
return uint(todayCount), uint(totalCount), err
}
func (a *AlertRepo) GetTaskLog(alertType string, alertId uint) (time.Time, error) {
var newDate time.Time
status := []string{constant.AlertSuccess, constant.AlertPushSuccess, constant.AlertSyncError, constant.AlertPushing}
now := time.Now()
todayMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
tomorrowMidnight := todayMidnight.Add(24 * time.Hour)
err := global.AlertDB.Model(&model.AlertLog{}).
Where("type = ? AND alert_id = ? AND status in ? AND created_at > ? AND created_at < ?", alertType, alertId, status, todayMidnight, tomorrowMidnight).
Order("created_at DESC").
Limit(1).
Pluck("created_at", &newDate).Error
if err != nil {
return time.Time{}, err
}
if newDate.IsZero() {
return time.Time{}, nil
}
return newDate, nil
}
func getAlertDB(opts ...DBOption) (*gorm.DB, error) {
var db *gorm.DB
db = global.AlertDB
for _, opt := range opts {
db = opt(db)
}
return db, nil
}
func (a *AlertRepo) GetLicensePushCount(method string) (uint, error) {
var (
todayCount int64
)
now := time.Now()
todayMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
tomorrowMidnight := todayMidnight.Add(24 * time.Hour)
err := global.AlertDB.Model(&model.AlertTask{}).Where("created_at > ? AND created_at < ? AND method = ?", todayMidnight, tomorrowMidnight, method).Count(&todayCount).Error
return uint(todayCount), err
}
func (a *AlertRepo) AlertConfigList(opts ...DBOption) ([]model.AlertConfig, error) {
var config []model.AlertConfig
db, _ := getAlertDB(opts...)
err := db.Find(&config).Error
return config, err
}
func (a *AlertRepo) UpdateAlertConfig(maps map[string]interface{}, opts ...DBOption) error {
db, _ := getAlertDB(opts...)
return db.Model(&model.AlertConfig{}).Updates(maps).Error
}
func (a *AlertRepo) CreateAlertConfig(config *model.AlertConfig) error {
return global.AlertDB.Model(&model.AlertConfig{}).Create(config).Error
}
func (a *AlertRepo) DeleteAlertConfig(opts ...DBOption) error {
db, _ := getAlertDB(opts...)
return db.Delete(&model.AlertConfig{}).Error
}
func (a *AlertRepo) GetConfig(opts ...DBOption) (model.AlertConfig, error) {
var alertConfig model.AlertConfig
db, _ := getAlertDB(opts...)
err := db.First(&alertConfig).Error
return alertConfig, err
}
func (a *AlertRepo) SyncAll(data []model.AlertConfig) error {
tx := global.AlertDB.Begin()
var oldConfigs []model.AlertConfig
_ = tx.Find(&oldConfigs).Error
oldConfigMap := make(map[string]uint)
for _, item := range oldConfigs {
oldConfigMap[item.Type] = item.ID
}
for _, item := range data {
if val, ok := oldConfigMap[item.Type]; ok {
item.ID = val
delete(oldConfigMap, item.Type)
} else {
item.ID = 0
}
if err := tx.Model(model.AlertConfig{}).Where("id = ?", item.ID).Save(&item).Error; err != nil {
tx.Rollback()
return err
}
}
for _, val := range oldConfigMap {
if err := tx.Where("id = ?", val).Delete(&model.AlertConfig{}).Error; err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
return nil
}
-48
View File
@@ -1,48 +0,0 @@
package repo
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"gorm.io/gorm"
)
type AppIgnoreUpgradeRepo struct {
}
type IAppIgnoreUpgradeRepo interface {
WithScope(scope string) DBOption
WithAppID(appID uint) DBOption
List(opts ...DBOption) ([]model.AppIgnoreUpgrade, error)
Create(appIgnoreUpgrade *model.AppIgnoreUpgrade) error
Delete(opts ...DBOption) error
}
func NewIAppIgnoreUpgradeRepo() IAppIgnoreUpgradeRepo {
return &AppIgnoreUpgradeRepo{}
}
func (a AppIgnoreUpgradeRepo) WithScope(scope string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("scope = ?", scope)
}
}
func (a AppIgnoreUpgradeRepo) WithAppID(appID uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("app_id = ?", appID)
}
}
func (a AppIgnoreUpgradeRepo) List(opts ...DBOption) ([]model.AppIgnoreUpgrade, error) {
var appIgnoreUpgradeList []model.AppIgnoreUpgrade
err := getDb(opts...).Find(&appIgnoreUpgradeList).Error
return appIgnoreUpgradeList, err
}
func (a AppIgnoreUpgradeRepo) Create(appIgnoreUpgrade *model.AppIgnoreUpgrade) error {
return global.DB.Create(appIgnoreUpgrade).Error
}
func (a AppIgnoreUpgradeRepo) Delete(opts ...DBOption) error {
return getDb(opts...).Delete(&model.AppIgnoreUpgrade{}).Error
}
-105
View File
@@ -1,105 +0,0 @@
package repo
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
)
type LauncherRepo struct{}
type ILauncherRepo interface {
Get(opts ...DBOption) (model.AppLauncher, error)
ListName(opts ...DBOption) ([]string, error)
Create(launcher *model.AppLauncher) error
Save(launcher *model.AppLauncher) error
Delete(opts ...DBOption) error
GetQuickJump(opts ...DBOption) (model.QuickJump, error)
ListQuickJump(withAll bool) []model.QuickJump
UpdateQuicks(quicks []model.QuickJump) error
}
func NewILauncherRepo() ILauncherRepo {
return &LauncherRepo{}
}
func (u *LauncherRepo) Get(opts ...DBOption) (model.AppLauncher, error) {
var launcher model.AppLauncher
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&launcher).Error
return launcher, err
}
func (u *LauncherRepo) ListName(opts ...DBOption) ([]string, error) {
var ops []model.AppLauncher
db := global.DB.Model(&model.AppLauncher{})
for _, opt := range opts {
db = opt(db)
}
_ = db.Find(&ops).Error
var names []string
for i := 0; i < len(ops); i++ {
names = append(names, ops[i].Key)
}
return names, nil
}
func (u *LauncherRepo) Create(launcher *model.AppLauncher) error {
return global.DB.Create(launcher).Error
}
func (u *LauncherRepo) Save(launcher *model.AppLauncher) error {
return global.DB.Save(launcher).Error
}
func (u *LauncherRepo) Delete(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.AppLauncher{}).Error
}
func (u *LauncherRepo) GetQuickJump(opts ...DBOption) (model.QuickJump, error) {
var launcher model.QuickJump
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&launcher).Error
return launcher, err
}
func (u *LauncherRepo) ListQuickJump(withAll bool) []model.QuickJump {
var quicks []model.QuickJump
if withAll {
_ = global.DB.Find(&quicks).Error
} else {
_ = global.DB.Where("is_show = ?", true).Find(&quicks).Error
}
if !withAll && len(quicks) == 0 {
return []model.QuickJump{
{Name: "Website", Title: "menu.website", Recommend: 10, IsShow: true, Router: "/websites"},
{Name: "Database", Title: "menu.database", Recommend: 30, IsShow: true, Router: "/databases"},
{Name: "Cronjob", Title: "menu.cronjob", Recommend: 50, IsShow: true, Router: "/cronjobs"},
{Name: "AppInstalled", Title: "home.appInstalled", Recommend: 70, IsShow: true, Router: "/apps/installed"},
}
}
return quicks
}
func (u *LauncherRepo) UpdateQuicks(quicks []model.QuickJump) error {
tx := global.DB.Begin()
for _, item := range quicks {
if err := tx.Model(&model.QuickJump{}).Where("id = ?", item.ID).Updates(map[string]interface{}{
"is_show": item.IsShow,
"detail": item.Detail,
}).Error; err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
return nil
}
-148
View File
@@ -1,148 +0,0 @@
package repo
import (
"time"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/google/uuid"
"gorm.io/gorm"
)
type ClamRepo struct{}
type IClamRepo interface {
Page(limit, offset int, opts ...DBOption) (int64, []model.Clam, error)
Create(clam *model.Clam) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
Get(opts ...DBOption) (model.Clam, error)
List(opts ...DBOption) ([]model.Clam, error)
WithByClamID(id uint) DBOption
ListRecord(opts ...DBOption) ([]model.ClamRecord, error)
RecordFirst(id uint) (model.ClamRecord, error)
DeleteRecord(opts ...DBOption) error
StartRecords(clamID uint) model.ClamRecord
EndRecords(record model.ClamRecord, status, message string)
PageRecords(page, size int, opts ...DBOption) (int64, []model.ClamRecord, error)
}
func NewIClamRepo() IClamRepo {
return &ClamRepo{}
}
func (u *ClamRepo) Get(opts ...DBOption) (model.Clam, error) {
var clam model.Clam
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&clam).Error
return clam, err
}
func (u *ClamRepo) List(opts ...DBOption) ([]model.Clam, error) {
var clam []model.Clam
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&clam).Error
return clam, err
}
func (u *ClamRepo) Page(page, size int, opts ...DBOption) (int64, []model.Clam, error) {
var users []model.Clam
db := global.DB.Model(&model.Clam{})
for _, opt := range opts {
db = opt(db)
}
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error
return count, users, err
}
func (u *ClamRepo) Create(clam *model.Clam) error {
return global.DB.Create(clam).Error
}
func (u *ClamRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.Clam{}).Where("id = ?", id).Updates(vars).Error
}
func (u *ClamRepo) Delete(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.Clam{}).Error
}
func (c *ClamRepo) WithByClamID(id uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("clam_id = ?", id)
}
}
func (u *ClamRepo) ListRecord(opts ...DBOption) ([]model.ClamRecord, error) {
var record []model.ClamRecord
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&record).Error
return record, err
}
func (u *ClamRepo) RecordFirst(id uint) (model.ClamRecord, error) {
var record model.ClamRecord
err := global.DB.Where("clam_id = ?", id).Order("created_at desc").First(&record).Error
return record, err
}
func (u *ClamRepo) PageRecords(page, size int, opts ...DBOption) (int64, []model.ClamRecord, error) {
var records []model.ClamRecord
db := global.DB.Model(&model.ClamRecord{})
for _, opt := range opts {
db = opt(db)
}
count := int64(0)
db = db.Count(&count)
err := db.Order("created_at desc").Limit(size).Offset(size * (page - 1)).Find(&records).Error
return count, records, err
}
func (u *ClamRepo) StartRecords(clamID uint) model.ClamRecord {
var record model.ClamRecord
record.StartTime = time.Now()
record.ClamID = clamID
record.TaskID = uuid.New().String()
record.Status = constant.StatusWaiting
if err := global.DB.Create(&record).Error; err != nil {
global.LOG.Errorf("create record status failed, err: %v", err)
}
_ = u.Update(clamID, map[string]interface{}{"is_executing": true})
return record
}
func (u *ClamRepo) EndRecords(record model.ClamRecord, status, message string) {
upMap := make(map[string]interface{})
upMap["status"] = status
upMap["message"] = message
upMap["task_id"] = record.TaskID
upMap["scan_time"] = record.ScanTime
upMap["infected_files"] = record.InfectedFiles
upMap["total_error"] = record.TotalError
if err := global.DB.Model(&model.ClamRecord{}).Where("id = ?", record.ID).Updates(upMap).Error; err != nil {
global.LOG.Errorf("update record status failed, err: %v", err)
}
_ = u.Update(record.ClamID, map[string]interface{}{"is_executing": false})
}
func (u *ClamRepo) DeleteRecord(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.ClamRecord{}).Error
}
-78
View File
@@ -1,78 +0,0 @@
package repo
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"gorm.io/gorm"
)
type GroupRepo struct{}
type IGroupRepo interface {
Get(opts ...DBOption) (model.Group, error)
GetList(opts ...DBOption) ([]model.Group, error)
Create(group *model.Group) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
CancelDefault(groupType string) error
WithByDefault(isDefault bool) DBOption
WithByWebsiteDefault() DBOption
}
func NewIGroupRepo() IGroupRepo {
return &GroupRepo{}
}
func (g *GroupRepo) WithByDefault(isDefault bool) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("is_default = ?", isDefault)
}
}
func (g *GroupRepo) Get(opts ...DBOption) (model.Group, error) {
var group model.Group
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&group).Error
return group, err
}
func (g *GroupRepo) GetList(opts ...DBOption) ([]model.Group, error) {
var groups []model.Group
db := global.DB.Model(&model.Group{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&groups).Error
return groups, err
}
func (g *GroupRepo) Create(group *model.Group) error {
return global.DB.Create(group).Error
}
func (g *GroupRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.Group{}).Where("id = ?", id).Updates(vars).Error
}
func (g *GroupRepo) Delete(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.Group{}).Error
}
func (g *GroupRepo) WithByWebsiteDefault() DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("is_default = ? AND type = ?", 1, "website")
}
}
func (g *GroupRepo) CancelDefault(groupType string) error {
return global.DB.Model(&model.Group{}).
Where("is_default = ? AND type = ?", 1, groupType).
Updates(map[string]interface{}{"is_default": 0}).Error
}
-56
View File
@@ -1,56 +0,0 @@
package repo
import "github.com/1Panel-dev/1Panel/agent/app/model"
type McpServerRepo struct {
}
type IMcpServerRepo interface {
Page(page, size int, opts ...DBOption) (int64, []model.McpServer, error)
GetFirst(opts ...DBOption) (*model.McpServer, error)
Create(mcpServer *model.McpServer) error
Save(mcpServer *model.McpServer) error
DeleteBy(opts ...DBOption) error
List(opts ...DBOption) ([]model.McpServer, error)
}
func NewIMcpServerRepo() IMcpServerRepo {
return &McpServerRepo{}
}
func (m McpServerRepo) Page(page, size int, opts ...DBOption) (int64, []model.McpServer, error) {
var servers []model.McpServer
db := getDb(opts...).Model(&model.McpServer{})
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&servers).Error
return count, servers, err
}
func (m McpServerRepo) GetFirst(opts ...DBOption) (*model.McpServer, error) {
var mcpServer model.McpServer
if err := getDb(opts...).First(&mcpServer).Error; err != nil {
return nil, err
}
return &mcpServer, nil
}
func (m McpServerRepo) List(opts ...DBOption) ([]model.McpServer, error) {
var mcpServers []model.McpServer
if err := getDb(opts...).Find(&mcpServers).Error; err != nil {
return nil, err
}
return mcpServers, nil
}
func (m McpServerRepo) Create(mcpServer *model.McpServer) error {
return getDb().Create(mcpServer).Error
}
func (m McpServerRepo) Save(mcpServer *model.McpServer) error {
return getDb().Save(mcpServer).Error
}
func (m McpServerRepo) DeleteBy(opts ...DBOption) error {
return getDb(opts...).Delete(&model.McpServer{}).Error
}
-74
View File
@@ -1,74 +0,0 @@
package repo
import (
"time"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
)
type MonitorRepo struct{}
type IMonitorRepo interface {
GetBase(opts ...DBOption) ([]model.MonitorBase, error)
GetIO(opts ...DBOption) ([]model.MonitorIO, error)
GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, error)
CreateMonitorBase(model model.MonitorBase) error
BatchCreateMonitorIO(ioList []model.MonitorIO) error
BatchCreateMonitorNet(ioList []model.MonitorNetwork) error
DelMonitorBase(timeForDelete time.Time) error
DelMonitorIO(timeForDelete time.Time) error
DelMonitorNet(timeForDelete time.Time) error
}
func NewIMonitorRepo() IMonitorRepo {
return &MonitorRepo{}
}
func (u *MonitorRepo) GetBase(opts ...DBOption) ([]model.MonitorBase, error) {
var data []model.MonitorBase
db := global.MonitorDB
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&data).Error
return data, err
}
func (u *MonitorRepo) GetIO(opts ...DBOption) ([]model.MonitorIO, error) {
var data []model.MonitorIO
db := global.MonitorDB
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&data).Error
return data, err
}
func (u *MonitorRepo) GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, error) {
var data []model.MonitorNetwork
db := global.MonitorDB
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&data).Error
return data, err
}
func (u *MonitorRepo) CreateMonitorBase(model model.MonitorBase) error {
return global.MonitorDB.Create(&model).Error
}
func (u *MonitorRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
}
func (u *MonitorRepo) BatchCreateMonitorNet(ioList []model.MonitorNetwork) error {
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
}
func (u *MonitorRepo) DelMonitorBase(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error
}
func (u *MonitorRepo) DelMonitorIO(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error
}
func (u *MonitorRepo) DelMonitorNet(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
}
-80
View File
@@ -1,80 +0,0 @@
package repo
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
)
type ScriptRepo struct{}
type IScriptRepo interface {
Get(opts ...DBOption) (model.ScriptLibrary, error)
List(opts ...DBOption) ([]model.ScriptLibrary, error)
SyncAll(data []model.ScriptLibrary) error
}
func NewIScriptRepo() IScriptRepo {
return &ScriptRepo{}
}
func (u *ScriptRepo) Get(opts ...DBOption) (model.ScriptLibrary, error) {
var script model.ScriptLibrary
db := global.DB
if global.IsMaster {
db = global.CoreDB
}
for _, opt := range opts {
db = opt(db)
}
err := db.First(&script).Error
return script, err
}
func (u *ScriptRepo) List(opts ...DBOption) ([]model.ScriptLibrary, error) {
var ops []model.ScriptLibrary
if global.IsMaster {
db := global.CoreDB.Model(&model.ScriptLibrary{})
for _, opt := range opts {
db = opt(db)
}
err := db.Where("is_interactive = ?", false).Find(&ops).Error
return ops, err
}
db := global.DB.Model(&model.ScriptLibrary{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&ops).Error
return ops, err
}
func (u *ScriptRepo) SyncAll(data []model.ScriptLibrary) error {
tx := global.DB.Begin()
var oldScripts []model.ScriptLibrary
_ = tx.Where("1 = 1").Find(&oldScripts).Error
oldScriptMap := make(map[string]uint)
for _, item := range oldScripts {
oldScriptMap[item.Name] = item.ID
}
for _, item := range data {
if val, ok := oldScriptMap[item.Name]; ok {
item.ID = val
delete(oldScriptMap, item.Name)
} else {
item.ID = 0
}
if err := tx.Model(model.ScriptLibrary{}).Where("id = ?", item.ID).Save(&item).Error; err != nil {
tx.Rollback()
return err
}
}
for _, val := range oldScriptMap {
if err := tx.Where("id = ?", val).Delete(&model.ScriptLibrary{}).Error; err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
return nil
}
-125
View File
@@ -1,125 +0,0 @@
package repo
import (
"context"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/app/model"
"gorm.io/gorm"
)
type TaskRepo struct {
}
type ITaskRepo interface {
Save(ctx context.Context, task *model.Task) error
GetFirst(opts ...DBOption) (model.Task, error)
Page(page, size int, opts ...DBOption) (int64, []model.Task, error)
Update(ctx context.Context, task *model.Task) error
UpdateRunningTaskToFailed() error
CountExecutingTask() (int64, error)
Delete(opts ...DBOption) error
DeleteAll() error
WithByID(id string) DBOption
WithResourceID(id uint) DBOption
WithOperate(taskOperate string) DBOption
WithByStatus(status string) DBOption
}
func NewITaskRepo() ITaskRepo {
return &TaskRepo{}
}
func getTaskDb(opts ...DBOption) *gorm.DB {
db := global.TaskDB
for _, opt := range opts {
db = opt(db)
}
return db
}
func getTaskTx(ctx context.Context, opts ...DBOption) *gorm.DB {
tx, ok := ctx.Value(constant.DB).(*gorm.DB)
if ok {
for _, opt := range opts {
tx = opt(tx)
}
return tx
}
return getTaskDb(opts...)
}
func (t TaskRepo) WithByID(id string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("id = ?", id)
}
}
func (t TaskRepo) WithOperate(taskOperate string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("operate = ?", taskOperate)
}
}
func (t TaskRepo) WithResourceID(id uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("resource_id = ?", id)
}
}
func (t TaskRepo) WithByStatus(status string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("status = ?", status)
}
}
func (t TaskRepo) Save(ctx context.Context, task *model.Task) error {
return getTaskTx(ctx).Save(&task).Error
}
func (t TaskRepo) GetFirst(opts ...DBOption) (model.Task, error) {
var task model.Task
db := getTaskDb(opts...).Model(&model.Task{})
if err := db.First(&task).Error; err != nil {
return task, err
}
return task, nil
}
func (t TaskRepo) Page(page, size int, opts ...DBOption) (int64, []model.Task, error) {
var tasks []model.Task
db := getTaskDb(opts...).Model(&model.Task{})
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&tasks).Error
return count, tasks, err
}
func (t TaskRepo) Update(ctx context.Context, task *model.Task) error {
return getTaskTx(ctx).Save(&task).Error
}
func (t TaskRepo) UpdateRunningTaskToFailed() error {
return getTaskDb(t.WithByStatus(constant.StatusExecuting)).Model(&model.Task{}).Updates(map[string]interface{}{"status": constant.StatusFailed, "error_msg": "1Panel restart causes failure"}).Error
}
func (t TaskRepo) CountExecutingTask() (int64, error) {
var count int64
err := getTaskDb(t.WithByStatus(constant.StatusExecuting)).Model(&model.Task{}).Count(&count).Error
return count, err
}
func (t TaskRepo) Delete(opts ...DBOption) error {
db := global.TaskDB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.Task{}).Error
}
func (t TaskRepo) DeleteAll() error {
return global.TaskDB.Where("1 = 1").Delete(&model.Task{}).Error
}
-555
View File
@@ -1,555 +0,0 @@
package service
import (
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/copier"
"github.com/1Panel-dev/1Panel/agent/utils/email"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/shirou/gopsutil/v4/disk"
"sort"
"strings"
"sync"
"time"
)
type AlertService struct{}
type IAlertService interface {
PageAlert(req dto.AlertSearch) (int64, []dto.AlertDTO, error)
GetAlerts() ([]dto.AlertDTO, error)
CreateAlert(create dto.AlertCreate) error
UpdateAlert(req dto.AlertUpdate) error
DeleteAlert(id uint) error
GetAlert(id uint) (dto.AlertDTO, error)
UpdateStatus(id uint, status string) error
ExternalUpdateAlert(req dto.AlertCreate) error
GetDisks() ([]dto.DiskDTO, error)
PageAlertLogs(req dto.AlertLogSearch) (int64, []dto.AlertLogDTO, error)
CleanAlertLogs() error
GetClams() ([]dto.ClamDTO, error)
GetCronJobs(req dto.CronJobReq) ([]dto.CronJobDTO, error)
GetAlertConfig() ([]model.AlertConfig, error)
UpdateAlertConfig(req dto.AlertConfigUpdate) error
DeleteAlertConfig(id uint) error
TestAlertConfig(req dto.AlertConfigTest) (bool, error)
}
func NewIAlertService() IAlertService {
return &AlertService{}
}
func (a AlertService) PageAlert(search dto.AlertSearch) (int64, []dto.AlertDTO, error) {
var (
opts []repo.DBOption
result []dto.AlertDTO
)
if search.Status != "" {
opts = append(opts, repo.WithByStatus(search.Status))
}
if search.Type != "" {
opts = append(opts, alertRepo.WithByType(search.Type))
}
opts = append(opts, repo.WithOrderBy("created_at desc"))
total, alerts, err := alertRepo.Page(search.Page, search.PageSize, opts...)
if err != nil {
return 0, nil, err
}
for _, item := range alerts {
result = append(result, dto.AlertDTO{
ID: item.ID,
Type: item.Type,
Cycle: item.Cycle,
Count: item.Count,
Method: item.Method,
Title: item.Title,
Project: item.Project,
Status: item.Status,
SendCount: item.SendCount,
AdvancedParams: item.AdvancedParams,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
})
}
return total, result, err
}
func (a AlertService) GetAlerts() ([]dto.AlertDTO, error) {
var (
opts []repo.DBOption
result []dto.AlertDTO
)
opts = append(opts, repo.WithByStatus(constant.AlertEnable))
alerts, err := alertRepo.List(opts...)
if err != nil {
return nil, err
}
for _, item := range alerts {
result = append(result, dto.AlertDTO{
ID: item.ID,
Type: item.Type,
Cycle: item.Cycle,
Count: item.Count,
Method: item.Method,
Title: item.Title,
Project: item.Project,
Status: item.Status,
SendCount: item.SendCount,
AdvancedParams: item.AdvancedParams,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
})
}
return result, err
}
func (a AlertService) CreateAlert(create dto.AlertCreate) error {
var alertID uint
var alertInfo model.Alert
if create.Project != "" {
alertInfo, _ := alertRepo.Get(alertRepo.WithByType(create.Type), alertRepo.WithByProject(create.Project))
alertID = alertInfo.ID
} else {
alertInfo, _ := alertRepo.Get(alertRepo.WithByType(create.Type))
alertID = alertInfo.ID
}
if alertID != 0 {
var upAlert dto.AlertUpdate
if err := copier.Copy(&upAlert, &create); err != nil {
return buserr.WithErr("ErrStructTransform", err)
}
upAlert.ID = alertID
err := a.UpdateAlert(upAlert)
if err != nil {
return err
}
} else {
alertInfo.Status = constant.AlertEnable
if err := copier.Copy(&alertInfo, &create); err != nil {
return buserr.WithErr("ErrStructTransform", err)
}
if err := alertRepo.Create(&alertInfo); err != nil {
return err
}
NewIAlertTaskHelper().InitTask(alertInfo.Type)
}
return nil
}
func (a AlertService) UpdateAlert(req dto.AlertUpdate) error {
upMap := make(map[string]interface{})
upMap["id"] = req.ID
upMap["type"] = req.Type
upMap["cycle"] = req.Cycle
upMap["count"] = req.Count
upMap["method"] = req.Method
upMap["title"] = req.Title
upMap["project"] = req.Project
upMap["status"] = req.Status
upMap["send_count"] = req.SendCount
upMap["advanced_params"] = req.AdvancedParams
if err := alertRepo.Update(upMap, repo.WithByID(req.ID)); err != nil {
return err
}
NewIAlertTaskHelper().InitTask(req.Type)
return nil
}
func (a AlertService) DeleteAlert(id uint) error {
alertInfo, _ := alertRepo.Get(repo.WithByID(id))
if alertInfo.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
err := alertRepo.Delete(repo.WithByID(id))
if err != nil {
return err
}
alerts, err := a.GetAlerts()
if err != nil {
return err
}
if len(alerts) > 0 {
NewIAlertTaskHelper().InitTask(alertInfo.Type)
} else {
NewIAlertTaskHelper().StopTask()
}
return nil
}
func (a AlertService) GetAlert(id uint) (dto.AlertDTO, error) {
var res dto.AlertDTO
alertInfo, err := alertRepo.Get(repo.WithByID(id))
if err != nil {
return res, err
}
_ = copier.Copy(&res, &alertInfo)
return res, nil
}
func (a AlertService) UpdateStatus(id uint, status string) error {
alertInfo, _ := alertRepo.Get(repo.WithByID(id))
if alertInfo.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
err := alertRepo.Update(map[string]interface{}{"status": status}, repo.WithByID(alertInfo.ID))
if err != nil {
return err
}
alerts, err := a.GetAlerts()
if err != nil {
return err
}
if len(alerts) > 0 {
NewIAlertTaskHelper().InitTask(alertInfo.Type)
} else {
NewIAlertTaskHelper().StopTask()
}
return nil
}
func (a AlertService) GetDisks() ([]dto.DiskDTO, error) {
var disks []dto.DiskDTO
excludes := map[string]struct{}{
"/mnt/cdrom": {}, "/boot": {}, "/boot/efi": {}, "/dev": {}, "/dev/shm": {},
"/run/lock": {}, "/run": {}, "/run/shm": {}, "/run/user": {},
}
stdout, err := executeDiskCommand()
if err != nil {
return disks, nil
}
lines := strings.Split(stdout, "\n")
var mounts []dto.AlertDiskInfo
for _, line := range lines {
fields := strings.Fields(line)
if len(fields) < 7 {
continue
}
mountPoint := strings.Join(fields[6:], " ")
if shouldExclude(fields, mountPoint, excludes) {
continue
}
mounts = append(mounts, dto.AlertDiskInfo{Type: fields[1], Device: fields[0], Mount: mountPoint})
}
var (
wg sync.WaitGroup
mu sync.Mutex
)
wg.Add(len(mounts))
for i := 0; i < len(mounts); i++ {
go func(timeoutCh <-chan time.Time, mount dto.AlertDiskInfo) {
defer wg.Done()
var itemData dto.DiskDTO
itemData.Path = mount.Mount
itemData.Type = mount.Type
itemData.Device = mount.Device
select {
case <-timeoutCh:
mu.Lock()
disks = append(disks, 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()
disks = append(disks, 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()
disks = append(disks, itemData)
mu.Unlock()
}
}(time.After(5*time.Second), mounts[i])
}
wg.Wait()
sort.Slice(disks, func(i, j int) bool {
return disks[i].Path < disks[j].Path
})
return disks, nil
}
func executeDiskCommand() (string, error) {
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second))
stdout, err := cmdMgr.RunWithStdoutBashC("df -hT -P | grep '/' | grep -v tmpfs | grep -v 'snap/core' | grep -v udev")
if err != nil {
cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
stdout, err = cmdMgr2.RunWithStdoutBashC("df -lhT -P | grep '/' | grep -v tmpfs | grep -v 'snap/core' | grep -v udev")
}
return stdout, err
}
func shouldExclude(fields []string, mountPoint string, excludes map[string]struct{}) bool {
if strings.HasPrefix(mountPoint, "/snap") || len(strings.Split(mountPoint, "/")) > 10 {
return true
}
if strings.TrimSpace(fields[1]) == "tmpfs" {
return true
}
if strings.Contains(fields[2], "K") {
return true
}
if strings.Contains(mountPoint, "docker") {
return true
}
_, excluded := excludes[mountPoint]
return excluded
}
func (a AlertService) PageAlertLogs(search dto.AlertLogSearch) (int64, []dto.AlertLogDTO, error) {
var (
opts []repo.DBOption
result []dto.AlertLogDTO
)
if search.Status != "" {
opts = append(opts, repo.WithByStatus(search.Status))
}
if search.Count != 0 {
opts = append(opts, alertRepo.WithByCount(search.Count))
}
opts = append(opts, repo.WithOrderBy("created_at desc"))
total, alerts, err := alertRepo.PageLog(search.Page, search.PageSize, opts...)
if err != nil {
return 0, nil, err
}
for _, item := range alerts {
alertLogDTO, err := a.parseAlertLog(item)
if err != nil {
return 0, nil, err
}
result = append(result, alertLogDTO)
}
return total, result, err
}
func (a AlertService) parseAlertLog(item model.AlertLog) (dto.AlertLogDTO, error) {
var alertDetail dto.AlertDetail
var alertRule dto.AlertRule
if err := unmarshalAlertInfo(item.AlertDetail, &alertDetail); err != nil {
return dto.AlertLogDTO{}, err
}
if err := unmarshalAlertInfo(item.AlertRule, &alertRule); err != nil {
return dto.AlertLogDTO{}, err
}
return dto.AlertLogDTO{
ID: item.ID,
Count: item.Count,
Type: item.Type,
Status: item.Status,
Method: item.Method,
Message: item.Message,
AlertId: item.AlertId,
AlertDetail: alertDetail,
AlertRule: alertRule,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}, nil
}
func unmarshalAlertInfo(data string, v interface{}) error {
if err := json.Unmarshal([]byte(data), v); err != nil {
return fmt.Errorf("unmarshal alert info vars failed, err: %v", err)
}
return nil
}
func (a AlertService) CleanAlertLogs() error {
return alertRepo.CleanAlertLogs()
}
func (a AlertService) GetClams() ([]dto.ClamDTO, error) {
var clams []dto.ClamDTO
clamList, err := clamRepo.List()
for _, clam := range clamList {
var clamDTO dto.ClamDTO
clamDTO.ID = clam.ID
clamDTO.Name = clam.Name
clamDTO.Path = clam.Path
clamDTO.Status = clam.Status
clamDTO.UpdatedAt = clam.UpdatedAt
clamDTO.CreatedAt = clam.CreatedAt
clams = append(clams, clamDTO)
}
return clams, err
}
func (a AlertService) GetCronJobs(req dto.CronJobReq) ([]dto.CronJobDTO, error) {
var cronJobs []dto.CronJobDTO
var (
opts []repo.DBOption
)
if req.Status != "" {
opts = append(opts, repo.WithByStatus(req.Status))
}
if req.Type != "" {
opts = append(opts, repo.WithByType(req.Type))
}
cronjobList, err := cronjobRepo.List(opts...)
for _, cronJob := range cronjobList {
var cronJobDTO dto.CronJobDTO
cronJobDTO.ID = cronJob.ID
cronJobDTO.Name = cronJob.Name
cronJobDTO.Status = cronJob.Status
cronJobDTO.Type = cronJob.Type
cronJobDTO.UpdatedAt = cronJob.UpdatedAt
cronJobDTO.CreatedAt = cronJob.CreatedAt
cronJobs = append(cronJobs, cronJobDTO)
}
return cronJobs, err
}
func (a AlertService) GetAlertConfig() ([]model.AlertConfig, error) {
var (
opts []repo.DBOption
configs []model.AlertConfig
)
opts = append(opts, repo.WithByStatus(constant.AlertEnable))
configs, err := alertRepo.AlertConfigList(opts...)
return configs, err
}
func (a AlertService) UpdateAlertConfig(req dto.AlertConfigUpdate) error {
if req.ID != 0 {
upMap := make(map[string]interface{})
upMap["id"] = req.ID
upMap["type"] = req.Type
upMap["title"] = req.Title
upMap["status"] = req.Status
upMap["config"] = req.Config
if err := alertRepo.UpdateAlertConfig(upMap, repo.WithByID(req.ID)); err != nil {
return err
}
} else {
var alertConfig model.AlertConfig
if err := copier.Copy(&alertConfig, &req); err != nil {
return buserr.WithErr("ErrStructTransform", err)
}
if err := alertRepo.CreateAlertConfig(&alertConfig); err != nil {
return err
}
}
return nil
}
func (a AlertService) DeleteAlertConfig(id uint) error {
return alertRepo.DeleteAlertConfig(repo.WithByID(id))
}
func (a AlertService) TestAlertConfig(req dto.AlertConfigTest) (bool, error) {
cfg := email.SMTPConfig{
Host: req.Host,
Port: req.Port,
Username: req.Sender,
Password: req.Password,
From: fmt.Sprintf("%s <%s>", req.DisplayName, req.Sender),
Encryption: req.Encryption,
Recipient: req.Recipient,
}
msg := email.EmailMessage{
Subject: i18n.GetMsgByKey("TestAlertTitle"),
Body: i18n.GetMsgByKey("TestAlert"),
IsHTML: false,
}
transport := xpack.LoadRequestTransport()
if err := email.SendMail(cfg, msg, transport); err != nil {
return false, err
}
return true, nil
}
func (a AlertService) ExternalUpdateAlert(updateAlert dto.AlertCreate) error {
upMap := make(map[string]interface{})
var newStatus string
if updateAlert.SendCount == 0 {
newStatus = constant.AlertDisable
} else {
newStatus = constant.AlertEnable
upMap["send_count"] = updateAlert.SendCount
if updateAlert.Method != "" {
upMap["method"] = updateAlert.Method
}
}
upMap["status"] = newStatus
alertInfo, _ := alertRepo.Get(
alertRepo.WithByType(updateAlert.Type),
alertRepo.WithByProject(updateAlert.Project),
)
if alertInfo.ID > 0 {
shouldUpdate := false
if alertInfo.Status != newStatus {
shouldUpdate = true
}
if val, ok := upMap["send_count"]; ok && val != alertInfo.SendCount {
shouldUpdate = true
}
if val, ok := upMap["method"]; ok && val != "" && val != alertInfo.Method {
shouldUpdate = true
}
if shouldUpdate {
if err := alertRepo.Update(
upMap,
alertRepo.WithByProject(updateAlert.Project),
alertRepo.WithByType(updateAlert.Type),
); err != nil {
return err
}
}
} else {
if updateAlert.Method != "" && updateAlert.Title != "" {
updateAlert.Status = newStatus
if err := a.CreateAlert(updateAlert); err != nil {
return err
}
}
}
return nil
}
-889
View File
@@ -1,889 +0,0 @@
package service
import (
"encoding/json"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
alertUtil "github.com/1Panel-dev/1Panel/agent/utils/alert"
"github.com/1Panel-dev/1Panel/agent/utils/common"
versionUtil "github.com/1Panel-dev/1Panel/agent/utils/version"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/disk"
"github.com/shirou/gopsutil/v4/load"
"github.com/shirou/gopsutil/v4/mem"
"github.com/shirou/gopsutil/v4/net"
"math"
"sort"
"strconv"
"strings"
"time"
)
const (
ResourceAlertInterval = 30
CheckIntervalSec = 3
LoadCheckIntervalMin = 5
)
type AlertTaskHelper struct {
DiskIO chan []disk.IOCountersStat
NetIO chan []net.IOCountersStat
}
type IAlertTaskHelper interface {
StopTask()
StartTask()
ResetTask()
InitTask(alertType string)
}
var cpuLoad1, cpuLoad5, cpuLoad15 []float64
var memoryLoad1, memoryLoad5, memoryLoad15 []float64
var baseTypes = map[string]bool{"ssl": true, "siteEndTime": true, "panelPwdEndTime": true, "panelUpdate": true}
var resourceTypes = map[string]bool{"cpu": true, "memory": true, "disk": true, "load": true, "panelLogin": true, "sshLogin": true, "nodeException": true, "licenseException": true}
func NewIAlertTaskHelper() IAlertTaskHelper {
return &AlertTaskHelper{
DiskIO: make(chan []disk.IOCountersStat, 1),
NetIO: make(chan []net.IOCountersStat, 1),
}
}
func (m *AlertTaskHelper) StartTask() {
baseAlert, resourceAlert := m.getClassifiedAlerts()
if len(baseAlert) == 0 && len(resourceAlert) == 0 {
return
}
handleBaseAlerts(baseAlert)
handleResourceAlerts(resourceAlert)
}
func (m *AlertTaskHelper) StopTask() {
stopBaseJob()
stopResourceJob()
}
func (m *AlertTaskHelper) ResetTask() {
m.StopTask()
m.StartTask()
}
func (m *AlertTaskHelper) InitTask(alertType string) {
resetAlertState(alertType)
if baseTypes[alertType] {
stopBaseJob()
} else if resourceTypes[alertType] {
stopResourceJob()
}
m.StartTask()
}
func resetAlertState(alertType string) {
switch alertType {
case "cpu":
cpuLoad1 = []float64{}
cpuLoad5 = []float64{}
cpuLoad15 = []float64{}
case "memory":
memoryLoad1 = []float64{}
memoryLoad5 = []float64{}
memoryLoad15 = []float64{}
}
}
func (m *AlertTaskHelper) getClassifiedAlerts() (baseAlerts, resourceAlerts []dto.AlertDTO) {
alertList, _ := NewIAlertService().GetAlerts()
for _, alert := range alertList {
if baseTypes[alert.Type] {
baseAlerts = append(baseAlerts, alert)
} else if resourceTypes[alert.Type] {
resourceAlerts = append(resourceAlerts, alert)
}
}
return
}
func handleBaseAlerts(baseAlerts []dto.AlertDTO) {
if len(baseAlerts) == 0 {
stopResourceJob()
return
}
if global.AlertBaseJobID == 0 {
baseTask(baseAlerts)
jobID, err := global.Cron.AddFunc("*/30 * * * *", func() {
baseTask(baseAlerts)
})
if err != nil {
global.LOG.Errorf("alert base job start failed: %v", err)
return
}
global.AlertBaseJobID = jobID
global.LOG.Info("start alert base job")
}
}
func handleResourceAlerts(resourceAlerts []dto.AlertDTO) {
if len(resourceAlerts) == 0 {
stopResourceJob()
return
}
if global.AlertResourceJobID == 0 {
jobID, err := global.Cron.AddFunc("*/1 * * * *", func() {
resourceTask(resourceAlerts)
})
if err != nil {
global.LOG.Errorf("alert resource job start failed: %v", err)
return
}
global.AlertResourceJobID = jobID
global.LOG.Info("start alert resource job")
}
}
func stopBaseJob() {
if global.AlertBaseJobID != 0 {
global.Cron.Remove(global.AlertBaseJobID)
global.AlertBaseJobID = 0
global.LOG.Info("stop alert base job")
}
}
func stopResourceJob() {
if global.AlertResourceJobID != 0 {
global.Cron.Remove(global.AlertResourceJobID)
global.AlertResourceJobID = 0
global.LOG.Info("stop alert resource job")
}
}
func baseTask(baseAlert []dto.AlertDTO) {
for _, alert := range baseAlert {
if !alertUtil.CheckSendTimeRange(alert.Type) {
continue
}
switch alert.Type {
case "ssl":
loadSSLInfo(alert)
case "siteEndTime":
loadWebsiteInfo(alert)
case "panelPwdEndTime":
if global.IsMaster {
loadPanelPwd(alert)
}
case "panelUpdate":
if global.IsMaster {
loadPanelUpdate(alert)
}
}
}
}
func resourceTask(resourceAlert []dto.AlertDTO) {
minute := time.Now().Minute()
for _, alert := range resourceAlert {
if !alertUtil.CheckSendTimeRange(alert.Type) {
continue
}
execute := minute%LoadCheckIntervalMin == 0
switch alert.Type {
case "cpu":
loadCPUUsage(alert)
case "memory":
loadMemUsage(alert)
case "load":
loadLoadInfo(alert)
case "disk":
loadDiskUsage(alert)
case "panelLogin":
loadPanelLogin(alert)
case "sshLogin":
loadSSHLogin(alert)
case "nodeException":
if execute && global.IsMaster {
loadNodeException(alert)
}
case "licenseException":
if execute && global.IsMaster {
loadLicenseException(alert)
}
}
}
}
func loadSSLInfo(alert dto.AlertDTO) {
opts := getRepoOptionsByProject(alert.Project)
sslList, _ := repo.NewISSLRepo().List(opts...)
if len(sslList) == 0 {
return
}
daysDiffMap, projectMap := calculateSSLExpiryDays(sslList, alert.Cycle)
projectJSON := serializeAndSortProjects(projectMap)
if projectJSON == "" || len(daysDiffMap) == 0 {
return
}
sender := NewAlertSender(alert, projectJSON)
for daysDiff, domains := range daysDiffMap {
domainStr := strings.Join(domains, ",")
params := createAlertBaseParams(strconv.Itoa(len(domains)), strconv.Itoa(daysDiff))
sender.Send(domainStr, params)
}
}
func loadWebsiteInfo(alert dto.AlertDTO) {
opts := getRepoOptionsByProject(alert.Project)
websiteList, _ := websiteRepo.List(opts...)
if len(websiteList) == 0 {
return
}
daysDiffMap, projectMap := calculateWebsiteExpiryDays(websiteList, alert.Cycle)
projectJSON := serializeAndSortProjects(projectMap)
if projectJSON == "" || len(daysDiffMap) == 0 {
return
}
sender := NewAlertSender(alert, projectJSON)
for daysDiff, domains := range daysDiffMap {
domainStr := strings.Join(domains, ",")
params := createAlertBaseParams(strconv.Itoa(len(domains)), strconv.Itoa(daysDiff))
sender.Send(domainStr, params)
}
}
func loadPanelPwd(alert dto.AlertDTO) {
// only master alert
expDays, err := getSettingValue("ExpirationDays")
if err != nil || expDays == "0" {
global.LOG.Info("panel password expiration setting not enabled, skip")
return
}
expTimeStr, err := getSettingValue("ExpirationTime")
if err != nil {
return
}
expTime, _ := time.Parse(constant.DateTimeLayout, expTimeStr)
daysDiff := calculateDaysDifference(expTime)
if daysDiff >= 0 && int(alert.Cycle) >= daysDiff {
params := createAlertPwdParams(strconv.Itoa(daysDiff))
sender := NewAlertSender(alert, expTimeStr)
sender.Send(strconv.Itoa(daysDiff), params)
}
}
func loadPanelUpdate(alert dto.AlertDTO) {
// only master alert
info, err := versionUtil.GetUpgradeVersionInfo()
if err != nil {
global.LOG.Errorf("error getting version info: %s", err)
return
}
version := getValidVersion(info)
if version == "" {
return
}
sender := NewAlertSender(alert, version)
sender.Send(version, []dto.Param{})
}
// 获取 CPU 使用率数据并发送到通道
func loadCPUUsage(alert dto.AlertDTO) {
percent, err := cpu.Percent(time.Duration(CheckIntervalSec)*time.Second, false)
if err != nil {
global.LOG.Errorf("error getting cpu usage, err: %v", err)
return
}
if len(percent) > 0 {
var usageLoad *[]float64
var threshold int
switch alert.Cycle {
case 1:
usageLoad = &cpuLoad1
threshold = 1
case 5:
usageLoad = &cpuLoad5
threshold = 5
case 15:
usageLoad = &cpuLoad15
threshold = 15
}
shouldSendResourceAlert(alert, percent[0], usageLoad, threshold)
}
}
// 获取内存使用情况数据并发送到通道
func loadMemUsage(alert dto.AlertDTO) {
memStat, err := mem.VirtualMemory()
if err != nil {
global.LOG.Errorf("error getting memory usage, err: %v", err)
return
}
percent := memStat.UsedPercent
var memoryLoad *[]float64
var threshold int
switch alert.Cycle {
case 1:
memoryLoad = &memoryLoad1
threshold = 1
case 5:
memoryLoad = &memoryLoad5
threshold = 5
case 15:
memoryLoad = &memoryLoad15
threshold = 15
}
shouldSendResourceAlert(alert, percent, memoryLoad, threshold)
}
// 获取系统负载数据并发送到通道
func loadLoadInfo(alert dto.AlertDTO) {
avgStat, err := load.Avg()
if err != nil {
global.LOG.Errorf("error getting load usage, err: %v", err)
return
}
var loadValue float64
CPUTotal, _ := cpu.Counts(true)
switch alert.Cycle {
case 1:
loadValue = avgStat.Load1 / (float64(CPUTotal*2) * 0.75) * 100
case 5:
loadValue = avgStat.Load5 / (float64(CPUTotal*2) * 0.75) * 100
case 15:
loadValue = avgStat.Load15 / (float64(CPUTotal*2) * 0.75) * 100
default:
return
}
if loadValue < float64(alert.Count) {
return
}
newDate, err := alertRepo.GetTaskLog(alert.Type, alert.ID)
if err != nil {
global.LOG.Errorf("task log record not found, err: %v", err)
}
if isAlertDue(newDate) {
sendResourceAlert(alert, loadValue)
}
}
func loadDiskUsage(alert dto.AlertDTO) {
newDate, err := alertRepo.GetTaskLog(alert.Type, alert.ID)
if err != nil {
global.LOG.Errorf("record not found, err: %v", err)
return
}
if isAlertDue(newDate) {
if strings.Contains(alert.Project, "all") {
err = processAllDisks(alert)
} else {
err = processSingleDisk(alert)
}
}
}
func loadPanelLogin(alert dto.AlertDTO) {
count, isAlert, err := alertUtil.CountRecentFailedLoginLogs(alert.Cycle, alert.Count)
alertType := alert.Type
quota := strconv.Itoa(count)
quotaType := strconv.Itoa(int(alert.Cycle))
if err != nil {
global.LOG.Errorf("Failed to count recent failed login logs: %v", err)
}
if isAlert {
alertType = "panelLogin"
quota = strconv.Itoa(count)
quotaType = "panelLogin"
params := []dto.Param{
{
Index: "1",
Key: "cycle",
Value: "",
},
{
Index: "2",
Key: "project",
Value: "",
},
}
sendAlerts(alert, alertType, quota, quotaType, params)
}
whitelist := strings.Split(strings.TrimSpace(alert.AdvancedParams), "\n")
records, err := alertUtil.FindRecentSuccessLoginsNotInWhitelist(30, whitelist)
if err != nil {
global.LOG.Errorf("Failed to check recent failed ip login logs: %v", err)
}
if len(records) > 0 {
quota = strings.Join(func() []string {
var ips []string
for _, r := range records {
ips = append(ips, r.IP)
}
return ips
}(), "\n")
alertType = "panelIpLogin"
quotaType = "panelIpLogin"
params := []dto.Param{
{
Index: "1",
Key: "cycle",
Value: "",
},
{
Index: "2",
Key: "project",
Value: " IP ",
},
}
sendAlerts(alert, alertType, quota, quotaType, params)
}
}
func loadSSHLogin(alert dto.AlertDTO) {
count, isAlert, err := alertUtil.CountRecentFailedSSHLog(alert.Cycle, alert.Count)
alertType := alert.Type
quota := strconv.Itoa(count)
quotaType := strconv.Itoa(int(alert.Cycle))
if err != nil {
global.LOG.Errorf("Failed to count recent failed ssh login logs: %v", err)
}
if isAlert {
alertType = "sshLogin"
quota = strconv.Itoa(count)
quotaType = "sshLogin"
params := []dto.Param{
{
Index: "1",
Key: "cycle",
Value: " SSH ",
},
{
Index: "2",
Key: "project",
Value: "",
},
}
sendAlerts(alert, alertType, quota, quotaType, params)
}
whitelist := strings.Split(strings.TrimSpace(alert.AdvancedParams), "\n")
records, err := alertUtil.FindRecentSuccessLoginNotInWhitelist(30, whitelist)
if err != nil {
global.LOG.Errorf("Failed to check recent failed ip ssh login logs: %v", err)
}
if len(records) > 0 {
quota = strings.Join(records, "\n")
alertType = "sshIpLogin"
quotaType = "sshIpLogin"
params := []dto.Param{
{
Index: "1",
Key: "cycle",
Value: " SSH ",
},
{
Index: "2",
Key: "project",
Value: " IP ",
},
}
sendAlerts(alert, alertType, quota, quotaType, params)
}
}
func loadNodeException(alert dto.AlertDTO) {
// only master alert
failCount, err := xpack.GetNodeErrorAlert()
if err != nil {
global.LOG.Errorf("error getting node, err: %s", err)
return
}
if failCount > 0 {
quotaType := "node-error"
params := []dto.Param{
{
Index: "1",
Key: "cycle",
Value: strconv.Itoa(int(failCount)),
},
}
newDate, err := alertRepo.GetTaskLog(alert.Type, alert.ID)
if err != nil {
global.LOG.Errorf("record not found, err: %v", err)
return
}
if isAlertDue(newDate) {
sender := NewAlertSender(alert, quotaType)
sender.ResourceSend(strconv.Itoa(int(failCount)), params)
}
}
}
func loadLicenseException(alert dto.AlertDTO) {
// only master alert
failCount, err := xpack.GetLicenseErrorAlert()
if err != nil {
global.LOG.Errorf("error getting license, err: %s", err)
return
}
if failCount > 0 {
quotaType := "license-error"
params := []dto.Param{
{
Index: "1",
Key: "cycle",
Value: strconv.Itoa(int(failCount)),
},
}
newDate, err := alertRepo.GetTaskLog(alert.Type, alert.ID)
if err != nil {
global.LOG.Errorf("record not found, err: %v", err)
return
}
if isAlertDue(newDate) {
sender := NewAlertSender(alert, quotaType)
sender.ResourceSend(strconv.Itoa(int(failCount)), params)
}
}
}
func sendAlerts(alert dto.AlertDTO, alertType, quota, quotaType string, params []dto.Param) {
methods := strings.Split(alert.Method, ",")
newDate, err := alertRepo.GetTaskLog(alertType, alert.ID)
if err != nil {
global.LOG.Errorf("task log record not found, err: %v", err)
}
if newDate.IsZero() || calculateMinutesDifference(newDate) > ResourceAlertInterval {
for _, m := range methods {
m = strings.TrimSpace(m)
switch m {
case constant.SMS:
if !alertUtil.CheckSMSSendLimit(constant.SMS) {
continue
}
todayCount, isValid := canSendAlertToday(alertType, quotaType, alert.SendCount, constant.SMS)
if !isValid {
continue
}
create := dto.AlertLogCreate{
Type: alertType,
AlertId: alert.ID,
Count: todayCount + 1,
}
_ = xpack.CreateSMSAlertLog(alertType, alert, create, quotaType, params, constant.SMS)
alertUtil.CreateNewAlertTask(quota, alertType, quotaType, constant.SMS)
global.LOG.Infof("%s alert sms push successful", alertType)
case constant.Email:
todayCount, isValid := canSendAlertToday(alertType, quotaType, alert.SendCount, constant.Email)
if !isValid {
continue
}
create := dto.AlertLogCreate{
Type: alertType,
AlertId: alert.ID,
Count: todayCount + 1,
}
alertInfo := alert
alertInfo.Type = alertType
create.AlertRule = alertUtil.ProcessAlertRule(alert)
create.AlertDetail = alertUtil.ProcessAlertDetail(alertInfo, quotaType, params, constant.Email)
transport := xpack.LoadRequestTransport()
_ = alertUtil.CreateEmailAlertLog(create, alertInfo, params, transport)
alertUtil.CreateNewAlertTask(quota, alertType, quotaType, constant.Email)
global.LOG.Infof("%s alert email push successful", alertType)
}
}
}
}
// ------------------------------
func getRepoOptionsByProject(project string) []repo.DBOption {
var opts []repo.DBOption
if project != "all" {
itemID, _ := strconv.Atoi(project)
opts = append(opts, repo.WithByID(uint(itemID)))
}
return opts
}
func serializeAndSortProjects(projectMap map[uint][]time.Time) string {
if len(projectMap) == 0 {
return ""
}
keys := make([]int, 0, len(projectMap))
for k := range projectMap {
keys = append(keys, int(k))
}
sort.Ints(keys)
projectJSON, err := json.Marshal(projectMap)
if err != nil {
global.LOG.Errorf("Failed to serialize projectMap: %v", err)
return ""
}
return string(projectJSON)
}
func calculateSSLExpiryDays(sslList []model.WebsiteSSL, cycle uint) (map[int][]string, map[uint][]time.Time) {
currentDate := time.Now()
daysDiffMap := make(map[int][]string)
projectMap := make(map[uint][]time.Time)
for _, ssl := range sslList {
daysDiff := int(ssl.ExpireDate.Sub(currentDate).Hours() / 24)
if daysDiff > 0 && int(cycle) >= daysDiff {
daysDiffMap[daysDiff] = append(daysDiffMap[daysDiff], ssl.PrimaryDomain)
projectMap[ssl.ID] = append(projectMap[ssl.ID], ssl.ExpireDate)
}
}
return daysDiffMap, projectMap
}
func calculateWebsiteExpiryDays(websites []model.Website, cycle uint) (map[int][]string, map[uint][]time.Time) {
currentDate := time.Now()
daysDiffMap := make(map[int][]string)
projectMap := make(map[uint][]time.Time)
for _, website := range websites {
daysDiff := int(website.ExpireDate.Sub(currentDate).Hours() / 24)
if daysDiff > 0 && int(cycle) >= daysDiff {
daysDiffMap[daysDiff] = append(daysDiffMap[daysDiff], website.PrimaryDomain)
projectMap[website.ID] = append(projectMap[website.ID], website.ExpireDate)
}
}
return daysDiffMap, projectMap
}
func getSettingValue(key string) (string, error) {
var setting model.Setting
if err := global.CoreDB.Model(&model.Setting{}).Where("key = ?", key).First(&setting).Error; err != nil {
global.LOG.Errorf("load %s from db setting failed: %v", key, err)
return "", err
}
return setting.Value, nil
}
func getValidVersion(info *dto.UpgradeInfo) string {
if info.NewVersion != "" {
return info.NewVersion
} else if info.TestVersion != "" {
return info.TestVersion
} else if info.LatestVersion != "" {
return info.LatestVersion
}
return ""
}
func shouldSendResourceAlert(alert dto.AlertDTO, currentUsage float64, usageLoad *[]float64, threshold int) {
newDate, err := alertRepo.GetTaskLog(alert.Type, alert.ID)
if err != nil {
global.LOG.Errorf("record not found, err: %v", err)
}
if isAlertDue(newDate) {
*usageLoad = append(*usageLoad, currentUsage)
if len(*usageLoad) > threshold {
*usageLoad = (*usageLoad)[1:]
}
if len(*usageLoad) == threshold {
avgUsage := average(*usageLoad)
if avgUsage >= float64(alert.Count) {
sendResourceAlert(alert, avgUsage)
}
}
}
}
func isAlertDue(lastAlertTime time.Time) bool {
if lastAlertTime.IsZero() {
return true
}
return calculateMinutesDifference(lastAlertTime) > ResourceAlertInterval
}
func sendResourceAlert(alert dto.AlertDTO, value float64) {
valueStr := common.FormatPercent(value)
module := getModuleName(alert.Type)
params := createAlertAvgParams(strconv.Itoa(int(alert.Cycle)), module, valueStr)
sender := NewAlertSender(alert, strconv.Itoa(int(alert.Cycle)))
sender.ResourceSend(valueStr, params)
}
func getModuleName(alertType string) string {
var module string
switch alertType {
case "cpu":
module = " CPU "
case "memory":
module = "内存"
case "load":
module = "负载"
default:
}
return module
}
func canSendAlertToday(alertType, quotaType string, sendCount uint, method string) (uint, bool) {
todayCount, _, err := alertRepo.LoadTaskCount(alertType, quotaType, method)
if err != nil {
global.LOG.Errorf("error getting task info, err: %v", err)
return todayCount, false
}
if todayCount >= sendCount {
return todayCount, false
}
return todayCount, true
}
func average(arr []float64) float64 {
total := 0.0
for _, v := range arr {
total += v
}
return total / float64(len(arr))
}
func createAlertBaseParams(project, cycle string) []dto.Param {
return []dto.Param{
{
Index: "1",
Key: "project",
Value: project,
},
{
Index: "2",
Key: "cycle",
Value: cycle,
},
}
}
func createAlertPwdParams(cycle string) []dto.Param {
return []dto.Param{
{
Index: "1",
Key: "cycle",
Value: cycle,
},
}
}
func createAlertAvgParams(cycle, module, count string) []dto.Param {
return []dto.Param{
{
Index: "1",
Key: "cycle",
Value: cycle,
},
{
Index: "2",
Key: "module",
Value: module,
},
{
Index: "3",
Key: "count",
Value: count,
},
}
}
func createAlertDiskParams(project, count string) []dto.Param {
return []dto.Param{
{
Index: "1",
Key: "project",
Value: project,
},
{
Index: "2",
Key: "count",
Value: count,
},
}
}
func processAllDisks(alert dto.AlertDTO) error {
diskList, err := NewIAlertService().GetDisks()
if err != nil {
global.LOG.Errorf("error getting disk list, err: %v", err)
return err
}
for _, item := range diskList {
if success, err := checkAndCreateDiskAlert(alert, item.Path); err == nil && success {
global.LOG.Infof("disk alert pushed successfully for %s", item.Path)
}
}
return nil
}
func processSingleDisk(alert dto.AlertDTO) error {
success, err := checkAndCreateDiskAlert(alert, alert.Project)
if err != nil {
return err
}
if success {
global.LOG.Infof("disk alert pushed successfully for %s", alert.Project)
}
return nil
}
func checkAndCreateDiskAlert(alert dto.AlertDTO, path string) (bool, error) {
usageStat, err := disk.Usage(path)
if err != nil {
global.LOG.Errorf("error getting disk usage for %s, err: %v", path, err)
return false, err
}
usedTotal, usedStr := calculateUsedTotal(alert.Cycle, usageStat)
commonTotal := float64(alert.Count)
if alert.Cycle == 1 {
commonTotal *= 1024 * 1024 * 1024
}
if usedTotal < commonTotal {
return false, nil
}
global.LOG.Infof("disk「 %s 」usage: %s", path, usedStr)
params := createAlertDiskParams(path, usedStr)
sender := NewAlertSender(alert, alert.Project)
sender.ResourceSend(path, params)
return true, nil
}
func calculateUsedTotal(cycle uint, usageStat *disk.UsageStat) (float64, string) {
if cycle == 1 {
return float64(usageStat.Used), common.FormatBytes(usageStat.Used)
}
return usageStat.UsedPercent, common.FormatPercent(usageStat.UsedPercent)
}
func calculateDaysDifference(expirationTime time.Time) int {
currentDate := time.Now()
formattedTime := currentDate.Format(constant.DateTimeLayout)
parsedTime, _ := time.Parse(constant.DateTimeLayout, formattedTime)
timeGap := expirationTime.Sub(parsedTime).Milliseconds()
if timeGap < 0 {
return -1
}
daysDifference := int(math.Floor(float64(timeGap) / (3600 * 1000 * 24)))
return daysDifference
}
func calculateMinutesDifference(newDate time.Time) int {
now := time.Now()
if newDate.After(now) {
return -1
}
minutesDifference := int(now.Sub(newDate).Minutes())
return minutesDifference
}
-165
View File
@@ -1,165 +0,0 @@
package service
import (
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
alertUtil "github.com/1Panel-dev/1Panel/agent/utils/alert"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"strings"
)
type AlertSender struct {
alert dto.AlertDTO
quotaType string
}
func NewAlertSender(alert dto.AlertDTO, quotaType string) *AlertSender {
return &AlertSender{
alert: alert,
quotaType: quotaType,
}
}
func (s *AlertSender) Send(quota string, params []dto.Param) {
methods := strings.Split(s.alert.Method, ",")
for _, method := range methods {
method = strings.TrimSpace(method)
switch method {
case constant.SMS:
s.sendSMS(quota, params)
case constant.Email:
s.sendEmail(quota, params)
}
}
}
func (s *AlertSender) ResourceSend(quota string, params []dto.Param) {
methods := strings.Split(s.alert.Method, ",")
for _, method := range methods {
method = strings.TrimSpace(method)
switch method {
case constant.SMS:
s.sendResourceSMS(quota, params)
case constant.Email:
s.sendResourceEmail(quota, params)
}
}
}
func (s *AlertSender) sendSMS(quota string, params []dto.Param) {
if !alertUtil.CheckSMSSendLimit(constant.SMS) {
return
}
totalCount, isValid := s.canSendAlert(constant.SMS)
if !isValid {
return
}
create := dto.AlertLogCreate{
Status: constant.AlertSuccess,
Count: totalCount + 1,
AlertId: s.alert.ID,
Type: s.alert.Type,
}
_ = xpack.CreateSMSAlertLog(s.alert.Type, s.alert, create, quota, params, constant.SMS)
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.SMS)
global.LOG.Infof("%s alert sms push successful", s.alert.Type)
}
func (s *AlertSender) sendEmail(quota string, params []dto.Param) {
totalCount, isValid := s.canSendAlert(constant.Email)
if !isValid {
return
}
create := dto.AlertLogCreate{
Status: constant.AlertSuccess,
Count: totalCount + 1,
AlertId: s.alert.ID,
Type: s.alert.Type,
AlertRule: alertUtil.ProcessAlertRule(s.alert),
AlertDetail: alertUtil.ProcessAlertDetail(s.alert, quota, params, constant.Email),
}
transport := xpack.LoadRequestTransport()
_ = alertUtil.CreateEmailAlertLog(create, s.alert, params, transport)
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Email)
global.LOG.Infof("%s alert email push successful", s.alert.Type)
}
func (s *AlertSender) sendResourceSMS(quota string, params []dto.Param) {
if !alertUtil.CheckSMSSendLimit(constant.SMS) {
return
}
todayCount, isValid := s.canResourceSendAlert(constant.SMS)
if !isValid {
return
}
create := dto.AlertLogCreate{
Status: constant.AlertSuccess,
Count: todayCount + 1,
AlertId: s.alert.ID,
Type: s.alert.Type,
}
if err := xpack.CreateSMSAlertLog(s.alert.Type, s.alert, create, quota, params, constant.SMS); err != nil {
global.LOG.Errorf("failed to send SMS alert: %v", err)
return
}
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.SMS)
global.LOG.Infof("%s alert sms push successful", s.alert.Type)
}
func (s *AlertSender) sendResourceEmail(quota string, params []dto.Param) {
todayCount, isValid := s.canResourceSendAlert(constant.Email)
if !isValid {
return
}
create := dto.AlertLogCreate{
Status: constant.AlertSuccess,
Count: todayCount + 1,
AlertId: s.alert.ID,
Type: s.alert.Type,
AlertRule: alertUtil.ProcessAlertRule(s.alert),
AlertDetail: alertUtil.ProcessAlertDetail(s.alert, quota, params, constant.Email),
}
transport := xpack.LoadRequestTransport()
if err := alertUtil.CreateEmailAlertLog(create, s.alert, params, transport); err != nil {
global.LOG.Errorf("failed to send Email alert: %v", err)
return
}
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Email)
global.LOG.Infof("%s alert email push successful", s.alert.Type)
}
func (s *AlertSender) canSendAlert(method string) (uint, bool) {
todayCount, totalCount, err := alertRepo.LoadTaskCount(s.alert.Type, s.quotaType, method)
if err != nil {
global.LOG.Errorf("error getting task count: %v", err)
return totalCount, false
}
if todayCount >= 1 || s.alert.SendCount <= totalCount {
return totalCount, false
}
return totalCount, true
}
func (s *AlertSender) canResourceSendAlert(method string) (uint, bool) {
todayCount, _, err := alertRepo.LoadTaskCount(s.alert.Type, s.quotaType, method)
if err != nil {
global.LOG.Errorf("error getting task count: %v", err)
return todayCount, false
}
if s.alert.SendCount <= todayCount {
return todayCount, false
}
return todayCount, true
}
File diff suppressed because it is too large Load Diff
-76
View File
@@ -1,76 +0,0 @@
package service
import (
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/pkg/errors"
"gorm.io/gorm"
)
type AppIgnoreUpgradeService struct {
}
type IAppIgnoreUpgradeService interface {
List() ([]response.AppIgnoreUpgradeDTO, error)
CreateAppIgnore(req request.AppIgnoreUpgradeReq) error
Delete(req request.ReqWithID) error
}
func NewIAppIgnoreUpgradeService() IAppIgnoreUpgradeService {
return AppIgnoreUpgradeService{}
}
func (a AppIgnoreUpgradeService) List() ([]response.AppIgnoreUpgradeDTO, error) {
var res []response.AppIgnoreUpgradeDTO
ignores, err := appIgnoreUpgradeRepo.List()
if err != nil {
return nil, err
}
for _, ignore := range ignores {
dto := response.AppIgnoreUpgradeDTO{
ID: ignore.ID,
AppID: ignore.AppID,
AppDetailID: ignore.AppDetailID,
Scope: ignore.Scope,
}
app, err := appRepo.GetFirst(repo.WithByID(ignore.AppID))
if errors.Is(err, gorm.ErrRecordNotFound) {
_ = appIgnoreUpgradeRepo.Delete(repo.WithByID(ignore.ID))
continue
}
dto.Name = app.Name
if ignore.Scope == "version" {
appDetail, err := appDetailRepo.GetFirst(repo.WithByID(ignore.AppDetailID))
if errors.Is(err, gorm.ErrRecordNotFound) {
_ = appIgnoreUpgradeRepo.Delete(repo.WithByID(ignore.ID))
continue
}
dto.Version = appDetail.Version
}
res = append(res, dto)
}
return res, nil
}
func (a AppIgnoreUpgradeService) CreateAppIgnore(req request.AppIgnoreUpgradeReq) error {
appIgnoreUpgrade := model.AppIgnoreUpgrade{
AppID: req.AppID,
Scope: req.Scope,
}
if req.Scope == "version" {
appIgnoreUpgrade.AppDetailID = req.AppDetailID
}
if req.Scope == "all" {
_ = appIgnoreUpgradeRepo.Delete(appInstallRepo.WithAppId(req.AppID))
}
if err := appIgnoreUpgradeRepo.Create(&appIgnoreUpgrade); err != nil {
return err
}
return nil
}
func (a AppIgnoreUpgradeService) Delete(req request.ReqWithID) error {
return appIgnoreUpgradeRepo.Delete(repo.WithByID(req.ID))
}
File diff suppressed because it is too large Load Diff
-619
View File
@@ -1,619 +0,0 @@
package service
import (
"bufio"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"path"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cloud_storage"
"github.com/1Panel-dev/1Panel/agent/utils/cloud_storage/client"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/jinzhu/copier"
)
type BackupService struct{}
type IBackupService interface {
CheckUsed(name string, isPublic bool) error
LoadBackupOptions() ([]dto.BackupOption, error)
SearchWithPage(search dto.SearchPageWithType) (int64, interface{}, error)
Create(backupDto dto.BackupOperate) error
GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error)
Update(req dto.BackupOperate) error
Delete(id uint) error
RefreshToken(req dto.OperateByID) error
GetLocalDir() (string, error)
UploadForRecover(req dto.UploadForRecover) error
MysqlBackup(db dto.CommonBackup) error
PostgresqlBackup(db dto.CommonBackup) error
MysqlRecover(db dto.CommonRecover) error
PostgresqlRecover(db dto.CommonRecover) error
MysqlRecoverByUpload(req dto.CommonRecover) error
PostgresqlRecoverByUpload(req dto.CommonRecover) error
RedisBackup(db dto.CommonBackup) error
RedisRecover(db dto.CommonRecover) error
WebsiteBackup(db dto.CommonBackup) error
WebsiteRecover(req dto.CommonRecover) error
AppBackup(db dto.CommonBackup) (*model.BackupRecord, error)
AppRecover(req dto.CommonRecover) error
}
func NewIBackupService() IBackupService {
return &BackupService{}
}
func (u *BackupService) GetLocalDir() (string, error) {
account, err := backupRepo.Get(repo.WithByType(constant.Local))
if err != nil {
return "", err
}
return account.BackupPath, nil
}
func (u *BackupService) SearchWithPage(req dto.SearchPageWithType) (int64, interface{}, error) {
options := []repo.DBOption{repo.WithOrderBy("created_at desc")}
if len(req.Type) != 0 {
options = append(options, repo.WithByType(req.Type))
}
if len(req.Info) != 0 {
options = append(options, repo.WithByType(req.Info))
}
count, accounts, err := backupRepo.Page(req.Page, req.PageSize, options...)
if err != nil {
return 0, nil, err
}
var data []dto.BackupInfo
for _, account := range accounts {
var item dto.BackupInfo
if err := copier.Copy(&item, &account); err != nil {
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err)
}
if item.Type != constant.Sftp && item.Type != constant.Local {
item.BackupPath = path.Join("/", strings.TrimPrefix(item.BackupPath, "/"))
}
if !item.RememberAuth {
item.AccessKey = ""
item.Credential = ""
if account.Type == constant.Sftp {
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(item.Vars), &varMap); err != nil {
continue
}
delete(varMap, "passPhrase")
itemVars, _ := json.Marshal(varMap)
item.Vars = string(itemVars)
}
} else {
item.AccessKey, _ = encrypt.StringDecryptWithBase64(item.AccessKey)
item.Credential, _ = encrypt.StringDecryptWithBase64(item.Credential)
}
if account.Type == constant.OneDrive || account.Type == constant.ALIYUN || account.Type == constant.GoogleDrive {
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(item.Vars), &varMap); err != nil {
continue
}
delete(varMap, "refresh_token")
delete(varMap, "drive_id")
itemVars, _ := json.Marshal(varMap)
item.Vars = string(itemVars)
}
data = append(data, item)
}
return count, data, nil
}
func (u *BackupService) Create(req dto.BackupOperate) error {
if req.Type == constant.Local {
return buserr.New("ErrBackupLocalCreate")
}
if req.Type != constant.Sftp {
req.BackupPath = strings.TrimPrefix(req.BackupPath, "/")
}
backup, _ := backupRepo.Get(repo.WithByName(req.Name))
if backup.ID != 0 {
return buserr.New("ErrRecordExist")
}
if err := copier.Copy(&backup, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
itemAccessKey, err := base64.StdEncoding.DecodeString(backup.AccessKey)
if err != nil {
return err
}
backup.AccessKey = string(itemAccessKey)
itemCredential, err := base64.StdEncoding.DecodeString(backup.Credential)
if err != nil {
return err
}
backup.Credential = string(itemCredential)
if req.Type == constant.OneDrive || req.Type == constant.GoogleDrive || req.Type == constant.ALIYUN {
if err := loadRefreshTokenByCode(&backup); err != nil {
return err
}
}
if req.Type != constant.Local {
isOk, err := u.checkBackupConn(&backup)
if err != nil || !isOk {
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
}
}
backup.AccessKey, err = encrypt.StringEncrypt(backup.AccessKey)
if err != nil {
return err
}
backup.Credential, err = encrypt.StringEncrypt(backup.Credential)
if err != nil {
return err
}
if err := backupRepo.Create(&backup); err != nil {
return err
}
return nil
}
func (u *BackupService) GetBuckets(req dto.ForBuckets) ([]interface{}, error) {
itemAccessKey, err := base64.StdEncoding.DecodeString(req.AccessKey)
if err != nil {
return nil, err
}
req.AccessKey = string(itemAccessKey)
itemCredential, err := base64.StdEncoding.DecodeString(req.Credential)
if err != nil {
return nil, err
}
req.Credential = string(itemCredential)
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(req.Vars), &varMap); err != nil {
return nil, err
}
switch req.Type {
case constant.Sftp, constant.WebDAV:
varMap["username"] = req.AccessKey
varMap["password"] = req.Credential
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
varMap["accessKey"] = req.AccessKey
varMap["secretKey"] = req.Credential
}
client, err := cloud_storage.NewCloudStorageClient(req.Type, varMap)
if err != nil {
return nil, err
}
return client.ListBuckets()
}
func (u *BackupService) Delete(id uint) error {
backup, _ := backupRepo.Get(repo.WithByID(id))
if backup.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
if backup.Type == constant.Local {
return buserr.New("ErrBackupLocalDelete")
}
if err := u.CheckUsed(backup.Name, false); err != nil {
return err
}
return backupRepo.Delete(repo.WithByID(id))
}
func (u *BackupService) Update(req dto.BackupOperate) error {
backup, _ := backupRepo.Get(repo.WithByID(req.ID))
if backup.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
if req.Type != constant.Sftp && req.Type != constant.Local && req.BackupPath != "/" {
req.BackupPath = strings.TrimPrefix(req.BackupPath, "/")
}
var newBackup model.BackupAccount
if err := copier.Copy(&newBackup, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
itemAccessKey, err := base64.StdEncoding.DecodeString(newBackup.AccessKey)
if err != nil {
return err
}
newBackup.AccessKey = string(itemAccessKey)
itemCredential, err := base64.StdEncoding.DecodeString(newBackup.Credential)
if err != nil {
return err
}
newBackup.Credential = string(itemCredential)
if backup.Type == constant.Local {
if err := changeLocalBackup(backup.BackupPath, newBackup.BackupPath); err != nil {
return err
}
global.Dir.LocalBackupDir = newBackup.BackupPath
}
if newBackup.Type == constant.OneDrive || newBackup.Type == constant.GoogleDrive || newBackup.Type == constant.ALIYUN {
if err := loadRefreshTokenByCode(&newBackup); err != nil {
return err
}
}
if backup.Type != constant.Local {
isOk, err := u.checkBackupConn(&newBackup)
if err != nil || !isOk {
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
}
newBackup.AccessKey, err = encrypt.StringEncrypt(newBackup.AccessKey)
if err != nil {
return err
}
newBackup.Credential, err = encrypt.StringEncrypt(newBackup.Credential)
if err != nil {
return err
}
}
newBackup.ID = backup.ID
newBackup.CreatedAt = backup.CreatedAt
newBackup.UpdatedAt = backup.UpdatedAt
if err := backupRepo.Save(&newBackup); err != nil {
return err
}
return nil
}
func (u *BackupService) RefreshToken(req dto.OperateByID) error {
backup, _ := backupRepo.Get(repo.WithByID(req.ID))
if backup.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
return fmt.Errorf("failed to refresh %s - %s token, please retry, err: %v", backup.Type, backup.Name, err)
}
var (
refreshToken string
err error
)
switch backup.Type {
case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap)
}
if err != nil {
varMap["refresh_status"] = constant.StatusFailed
varMap["refresh_msg"] = err.Error()
return fmt.Errorf("failed to refresh %s-%s token, please retry, err: %v", backup.Type, backup.Name, err)
}
varMap["refresh_status"] = constant.StatusSuccess
varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout)
varMap["refresh_token"] = refreshToken
varsItem, _ := json.Marshal(varMap)
backup.Vars = string(varsItem)
return backupRepo.Save(&backup)
}
func (u *BackupService) UploadForRecover(req dto.UploadForRecover) error {
fileOp := files.NewFileOp()
if !fileOp.Stat(req.TargetDir) {
if err := fileOp.CreateDir(req.TargetDir, constant.DirPerm); err != nil {
return err
}
}
return fileOp.Copy(req.FilePath, req.TargetDir)
}
func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, error) {
client, err := newClient(backup, false)
if err != nil {
return false, err
}
fileItem := path.Join(global.Dir.BaseDir, "1panel/tmp/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, constant.FilePerm)
if err != nil {
return false, err
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString("1Panel 备份账号测试文件。\n")
_, _ = write.WriteString("1Panel 備份賬號測試文件。\n")
_, _ = write.WriteString("1Panel Backs up account test files.\n")
_, _ = write.WriteString("1Panelアカウントのテストファイルをバックアップします。\n")
write.Flush()
targetPath := path.Join(backup.BackupPath, "test/1panel")
if backup.Type != constant.Sftp && backup.Type != constant.Local && targetPath != "/" {
targetPath = strings.TrimPrefix(targetPath, "/")
}
if _, err := client.Upload(fileItem, targetPath); err != nil {
return false, err
}
_, _ = client.Delete(path.Join(backup.BackupPath, "test/1panel"))
return true, nil
}
func (u *BackupService) LoadBackupOptions() ([]dto.BackupOption, error) {
accounts, err := backupRepo.List(repo.WithOrderBy("created_at desc"))
if err != nil {
return nil, err
}
var data []dto.BackupOption
for _, account := range accounts {
var item dto.BackupOption
if err := copier.Copy(&item, &account); err != nil {
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err)
}
data = append(data, item)
}
return data, nil
}
func (u *BackupService) CheckUsed(name string, isPublic bool) error {
account, _ := backupRepo.Get(repo.WithByName(name), backupRepo.WithByPublic(isPublic))
if account.ID == 0 {
return nil
}
cronjobs, _ := cronjobRepo.List()
for _, job := range cronjobs {
if job.DownloadAccountID == account.ID {
return buserr.New("ErrBackupInUsed")
}
ids := strings.Split(job.SourceAccountIDs, ",")
for _, idItem := range ids {
if idItem == fmt.Sprintf("%v", account.ID) {
return buserr.New("ErrBackupInUsed")
}
}
}
return nil
}
func NewBackupClientWithID(id uint) (*model.BackupAccount, cloud_storage.CloudStorageClient, error) {
account, _ := backupRepo.Get(repo.WithByID(id))
backClient, err := newClient(&account, true)
if err != nil {
return nil, nil, err
}
return &account, backClient, nil
}
type backupClientHelper struct {
id uint
accountType string
name string
backupPath string
client cloud_storage.CloudStorageClient
isOk bool
hasBackup bool
message string
}
func NewBackupClientMap(ids []string) map[string]backupClientHelper {
var accounts []model.BackupAccount
var idItems []uint
for i := 0; i < len(ids); i++ {
item, _ := strconv.Atoi(ids[i])
idItems = append(idItems, uint(item))
}
accounts, _ = backupRepo.List(repo.WithByIDs(idItems))
clientMap := make(map[string]backupClientHelper)
for _, item := range accounts {
backClient, err := newClient(&item, true)
itemHelper := backupClientHelper{
client: backClient,
name: item.Name,
backupPath: item.BackupPath,
accountType: item.Type,
id: item.ID,
isOk: err == nil,
}
if err != nil {
itemHelper.message = err.Error()
}
clientMap[fmt.Sprintf("%v", item.ID)] = itemHelper
}
return clientMap
}
func uploadWithMap(taskItem task.Task, accountMap map[string]backupClientHelper, src, dst, accountIDs string, downloadAccountID, retry uint) error {
accounts := strings.Split(accountIDs, ",")
for _, account := range accounts {
if len(account) == 0 {
continue
}
itemBackup, ok := accountMap[account]
if !ok {
continue
}
if itemBackup.hasBackup {
continue
}
if !itemBackup.isOk {
taskItem.LogFailed(i18n.GetMsgWithDetail("LoadBackupFailed", itemBackup.message))
continue
}
name := itemBackup.name
if itemBackup.name == "localhost" {
name = i18n.GetMsgByKey("Localhost")
}
taskItem.LogStart(i18n.GetMsgWithMap("UploadFile", map[string]interface{}{
"file": path.Join(itemBackup.backupPath, dst),
"backup": name,
}))
for i := 0; i < int(retry)+1; i++ {
_, err := itemBackup.client.Upload(src, path.Join(itemBackup.backupPath, dst))
taskItem.LogWithStatus(i18n.GetMsgByKey("Upload"), err)
if err != nil {
if account == fmt.Sprintf("%d", downloadAccountID) {
return err
}
} else {
break
}
}
itemBackup.hasBackup = true
accountMap[account] = itemBackup
}
os.RemoveAll(src)
return nil
}
func newClient(account *model.BackupAccount, isEncrypt bool) (cloud_storage.CloudStorageClient, error) {
varMap := make(map[string]interface{})
if len(account.Vars) != 0 {
if err := json.Unmarshal([]byte(account.Vars), &varMap); err != nil {
return nil, err
}
}
varMap["bucket"] = account.Bucket
varMap["backupPath"] = account.BackupPath
if isEncrypt {
account.AccessKey, _ = encrypt.StringDecrypt(account.AccessKey)
account.Credential, _ = encrypt.StringDecrypt(account.Credential)
}
switch account.Type {
case constant.Sftp, constant.WebDAV:
varMap["username"] = account.AccessKey
varMap["password"] = account.Credential
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
varMap["accessKey"] = account.AccessKey
varMap["secretKey"] = account.Credential
case constant.UPYUN:
varMap["operator"] = account.AccessKey
varMap["password"] = account.Credential
}
client, err := cloud_storage.NewCloudStorageClient(account.Type, varMap)
if err != nil {
return nil, err
}
return client, nil
}
func loadRefreshTokenByCode(backup *model.BackupAccount) error {
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
return fmt.Errorf("unmarshal backup vars failed, err: %v", err)
}
refreshToken := ""
var err error
if backup.Type == constant.GoogleDrive {
refreshToken, err = client.RefreshGoogleToken("authorization_code", "refreshToken", varMap)
if err != nil {
return err
}
}
if backup.Type == constant.OneDrive {
refreshToken, err = client.RefreshToken("authorization_code", "refreshToken", varMap)
if err != nil {
return err
}
}
if backup.Type != constant.ALIYUN {
delete(varMap, "code")
varMap["refresh_token"] = refreshToken
}
varMap["refresh_status"] = constant.StatusSuccess
varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout)
itemVars, err := json.Marshal(varMap)
if err != nil {
return fmt.Errorf("json marshal var map failed, err: %v", err)
}
backup.Vars = string(itemVars)
return nil
}
func loadBackupNamesByID(accountIDs string, downloadID uint) ([]string, string, error) {
accountIDList := strings.Split(accountIDs, ",")
var ids []uint
for _, item := range accountIDList {
if len(item) != 0 {
itemID, _ := strconv.Atoi(item)
ids = append(ids, uint(itemID))
}
}
list, err := backupRepo.List(repo.WithByIDs(ids))
if err != nil {
return nil, "", err
}
var accounts []string
var downloadAccount string
for _, item := range list {
accounts = append(accounts, item.Name)
if item.ID == downloadID {
downloadAccount = item.Name
}
}
return accounts, downloadAccount, nil
}
func changeLocalBackup(oldPath, newPath string) error {
fileOp := files.NewFileOp()
if fileOp.Stat(path.Join(oldPath, "app")) {
if err := fileOp.CopyDir(path.Join(oldPath, "app"), newPath); err != nil {
return err
}
}
if fileOp.Stat(path.Join(oldPath, "database")) {
if err := fileOp.CopyDir(path.Join(oldPath, "database"), newPath); err != nil {
return err
}
}
if fileOp.Stat(path.Join(oldPath, "directory")) {
if err := fileOp.CopyDir(path.Join(oldPath, "directory"), newPath); err != nil {
return err
}
}
if fileOp.Stat(path.Join(oldPath, "system_snapshot")) {
if err := fileOp.CopyDir(path.Join(oldPath, "system_snapshot"), newPath); err != nil {
return err
}
}
if fileOp.Stat(path.Join(oldPath, "website")) {
if err := fileOp.CopyDir(path.Join(oldPath, "website"), newPath); err != nil {
return err
}
}
if fileOp.Stat(path.Join(oldPath, "log")) {
if err := fileOp.CopyDir(path.Join(oldPath, "log"), newPath); err != nil {
return err
}
}
if fileOp.Stat(path.Join(oldPath, "master")) {
if err := fileOp.CopyDir(path.Join(oldPath, "master"), newPath); err != nil {
return err
}
}
_ = fileOp.RmRf(path.Join(oldPath, "app"))
_ = fileOp.RmRf(path.Join(oldPath, "database"))
_ = fileOp.RmRf(path.Join(oldPath, "directory"))
_ = fileOp.RmRf(path.Join(oldPath, "system_snapshot"))
_ = fileOp.RmRf(path.Join(oldPath, "website"))
_ = fileOp.RmRf(path.Join(oldPath, "log"))
_ = fileOp.RmRf(path.Join(oldPath, "master"))
return nil
}
-401
View File
@@ -1,401 +0,0 @@
package service
import (
"context"
"encoding/json"
"fmt"
"io/fs"
"os"
"path"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/pkg/errors"
)
func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, error) {
app, err := appRepo.GetFirst(appRepo.WithKey(req.Name))
if err != nil {
return nil, err
}
install, err := appInstallRepo.GetFirst(repo.WithByName(req.DetailName), appInstallRepo.WithAppId(app.ID))
if err != nil {
return nil, err
}
timeNow := time.Now().Format(constant.DateTimeSlimLayout)
itemDir := fmt.Sprintf("app/%s/%s", req.Name, req.DetailName)
backupDir := path.Join(global.Dir.LocalBackupDir, itemDir)
fileName := req.FileName
if req.FileName == "" {
fileName = fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
}
backupApp := func() (*model.BackupRecord, error) {
if err = handleAppBackup(&install, nil, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err)
return nil, err
}
record := &model.BackupRecord{
Type: "app",
Name: req.Name,
DetailName: req.DetailName,
SourceAccountIDs: "1",
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
Description: req.Description,
}
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return nil, err
}
return record, nil
}
if req.TaskID != "" {
go func() {
_, _ = backupApp()
}()
} else {
return backupApp()
}
return nil, nil
}
func (u *BackupService) AppRecover(req dto.CommonRecover) error {
app, err := appRepo.GetFirst(appRepo.WithKey(req.Name))
if err != nil {
return err
}
install, err := appInstallRepo.GetFirst(repo.WithByName(req.DetailName), appInstallRepo.WithAppId(app.ID))
if err != nil {
return err
}
fileOp := files.NewFileOp()
if !fileOp.Stat(req.File) {
return buserr.WithName("ErrFileNotFound", req.File)
}
if _, err := compose.Down(install.GetComposePath()); err != nil {
return err
}
go func() {
if err := handleAppRecover(&install, nil, req.File, false, req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("recover app %s failed, err: %v", req.DetailName, err)
}
}()
return nil
}
func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name string, databaseID uint) error {
switch resourceKey {
case constant.AppMysql, constant.AppMariaDB:
db, err := mysqlRepo.Get(repo.WithByID(databaseID))
if err != nil {
return err
}
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
databaseHelper := DatabaseHelper{Database: db.MysqlName, DBType: resourceKey, Name: db.Name}
if err := handleMysqlBackup(databaseHelper, parentTask, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
return err
}
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
case constant.AppPostgresql:
db, err := postgresqlRepo.Get(repo.WithByID(databaseID))
if err != nil {
return err
}
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
databaseHelper := DatabaseHelper{Database: db.PostgresqlName, DBType: resourceKey, Name: db.Name}
if err := handlePostgresqlBackup(databaseHelper, parentTask, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
return err
}
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
}
return nil
}
func handleAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret, taskID string) error {
var (
err error
backupTask *task.Task
)
backupTask = parentTask
if parentTask == nil {
backupTask, err = task.NewTaskWithOps(install.Name, task.TaskBackup, task.TaskScopeApp, taskID, install.ID)
if err != nil {
return err
}
}
itemHandler := func() error { return doAppBackup(install, backupTask, backupDir, fileName, excludes, secret) }
backupTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), func(t *task.Task) error { return itemHandler() }, nil)
if parentTask != nil {
return itemHandler()
}
return backupTask.Execute()
}
func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverFile string, isRollback bool, secret, taskID string) error {
var (
err error
recoverTask *task.Task
isOk = false
rollbackFile string
)
recoverTask = parentTask
if parentTask == nil {
recoverTask, err = task.NewTaskWithOps(install.Name, task.TaskRecover, task.TaskScopeApp, taskID, install.ID)
if err != nil {
return err
}
}
recoverApp := func(t *task.Task) error {
fileOp := files.NewFileOp()
if !isRollback {
rollbackFile = path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)))
if err := handleAppBackup(install, recoverTask, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
t.Log(fmt.Sprintf("backup app %s for rollback before recover failed, err: %v", install.Name, err))
}
}
if err := fileOp.TarGzExtractPro(recoverFile, path.Dir(recoverFile), secret); err != nil {
return err
}
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
defer func() {
_, _ = compose.Up(install.GetComposePath())
_ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", ""))
}()
if !fileOp.Stat(tmpPath+"/app.json") || !fileOp.Stat(tmpPath+"/app.tar.gz") {
return errors.New(i18n.GetMsgByKey("AppBackupFileIncomplete"))
}
var oldInstall model.AppInstall
appJson, err := os.ReadFile(tmpPath + "/app.json")
if err != nil {
return err
}
if err := json.Unmarshal(appJson, &oldInstall); err != nil {
return fmt.Errorf("unmarshal app.json failed, err: %v", err)
}
if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name {
return errors.New(i18n.GetMsgByKey("AppAttributesNotMatch"))
}
newEnvFile := ""
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
for _, resource := range resources {
var database model.Database
switch resource.From {
case constant.AppResourceRemote:
database, err = databaseRepo.Get(repo.WithByID(resource.LinkId))
if err != nil {
return err
}
case constant.AppResourceLocal:
resourceApp, err := appInstallRepo.GetFirst(repo.WithByID(resource.LinkId))
if err != nil {
return err
}
database, err = databaseRepo.Get(databaseRepo.WithAppInstallID(resourceApp.ID), repo.WithByType(resource.Key), repo.WithByFrom(constant.AppResourceLocal), repo.WithByName(resourceApp.Name))
if err != nil {
return err
}
}
switch database.Type {
case constant.AppPostgresql:
db, err := postgresqlRepo.Get(repo.WithByID(resource.ResourceId))
if err != nil {
return err
}
taskName := task.GetTaskName(db.Name, task.TaskRecover, task.TaskScopeDatabase)
t.LogStart(taskName)
if err := handlePostgresqlRecover(dto.CommonRecover{
Name: database.Name,
DetailName: db.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
}, parentTask, true); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
t.LogSuccess(taskName)
case constant.AppMysql, constant.AppMariaDB:
db, err := mysqlRepo.Get(repo.WithByID(resource.ResourceId))
if err != nil {
return err
}
newDB, envMap, err := reCreateDB(db.ID, database, oldInstall.Env)
if err != nil {
return err
}
oldHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", envMap["PANEL_DB_HOST"].(string))
newHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", database.Address)
oldInstall.Env = strings.ReplaceAll(oldInstall.Env, oldHost, newHost)
envMap["PANEL_DB_HOST"] = database.Address
newEnvFile, err = coverEnvJsonToStr(oldInstall.Env)
if err != nil {
return err
}
_ = appInstallResourceRepo.BatchUpdateBy(map[string]interface{}{"resource_id": newDB.ID}, repo.WithByID(resource.ID))
taskName := task.GetTaskName(db.Name, task.TaskRecover, task.TaskScopeDatabase)
t.LogStart(taskName)
if err := handleMysqlRecover(dto.CommonRecover{
Name: newDB.MysqlName,
DetailName: newDB.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
}, parentTask, true, ""); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
t.LogSuccess(taskName)
}
}
appDir := install.GetPath()
backPath := fmt.Sprintf("%s_bak", appDir)
_ = fileOp.Rename(appDir, backPath)
_ = fileOp.CreateDir(appDir, constant.DirPerm)
deCompressName := i18n.GetWithName("DeCompressFile", "app.tar.gz")
t.LogStart(deCompressName)
if err := fileOp.TarGzExtractPro(tmpPath+"/app.tar.gz", install.GetAppPath(), ""); err != nil {
t.LogFailedWithErr(deCompressName, err)
_ = fileOp.DeleteDir(appDir)
_ = fileOp.Rename(backPath, appDir)
return err
}
t.LogSuccess(deCompressName)
_ = fileOp.DeleteDir(backPath)
if len(newEnvFile) != 0 {
envPath := fmt.Sprintf("%s/%s/.env", install.GetAppPath(), install.Name)
file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
return err
}
defer file.Close()
_, _ = file.WriteString(newEnvFile)
}
oldInstall.ID = install.ID
oldInstall.Status = constant.StatusRunning
oldInstall.AppId = install.AppId
oldInstall.AppDetailId = install.AppDetailId
oldInstall.App.ID = install.AppId
if err := appInstallRepo.Save(context.Background(), &oldInstall); err != nil {
global.LOG.Errorf("save db app install failed, err: %v", err)
return err
}
isOk = true
return nil
}
rollBackApp := func(t *task.Task) {
if isRollback {
return
}
if !isOk {
t.Log(i18n.GetMsgByKey("RecoverFailedStartRollBack"))
if err := handleAppRecover(install, t, rollbackFile, true, "", ""); err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("Rollback"), err)
return
}
t.LogSuccess(i18n.GetMsgByKey("Rollback"))
_ = os.RemoveAll(rollbackFile)
} else {
_ = os.RemoveAll(rollbackFile)
}
}
recoverTask.AddSubTask(task.GetTaskName(install.Name, task.TaskRecover, task.TaskScopeApp), recoverApp, rollBackApp)
if parentTask != nil {
return recoverApp(parentTask)
}
return recoverTask.Execute()
}
func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret string) error {
fileOp := files.NewFileOp()
tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", ""))
if !fileOp.Stat(tmpDir) {
if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil {
return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err)
}
}
defer func() {
_ = os.RemoveAll(tmpDir)
}()
remarkInfo, _ := json.Marshal(install)
remarkInfoPath := fmt.Sprintf("%s/app.json", tmpDir)
if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil {
return err
}
appPath := install.GetPath()
if err := fileOp.TarGzCompressPro(true, appPath, path.Join(tmpDir, "app.tar.gz"), "", excludes); err != nil {
return err
}
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
for _, resource := range resources {
if err := backupDatabaseWithTask(parentTask, resource.Key, tmpDir, install.Name, resource.ResourceId); err != nil {
return err
}
}
parentTask.LogStart(i18n.GetMsgByKey("CompressDir"))
if err := fileOp.TarGzCompressPro(true, tmpDir, path.Join(backupDir, fileName), secret, ""); err != nil {
return err
}
parentTask.Log(i18n.GetWithName("CompressFileSuccess", fileName))
return nil
}
func reCreateDB(dbID uint, database model.Database, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
mysqlService := NewIMysqlService()
ctx := context.Background()
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: database.Name, Type: database.Type, DeleteBackup: false, ForceDelete: true})
envMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil {
return nil, envMap, err
}
oldName, _ := envMap["PANEL_DB_NAME"].(string)
oldUser, _ := envMap["PANEL_DB_USER"].(string)
oldPassword, _ := envMap["PANEL_DB_USER_PASSWORD"].(string)
createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{
Name: oldName,
From: database.From,
Database: database.Name,
Format: "utf8mb4",
Username: oldUser,
Password: oldPassword,
Permission: "%",
})
cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByDbName(fmt.Sprintf("%v", dbID)))
for _, job := range cronjobs {
_ = cronjobRepo.Update(job.ID, map[string]interface{}{"db_name": fmt.Sprintf("%v", createDB.ID)})
}
if err != nil {
return nil, envMap, err
}
return createDB, envMap, nil
}

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