Compare commits

..
386 Commits
Author SHA1 Message Date
Plynksiy Nikita 65f0a9e3cf docs: add note about requiring conf and resources directories (or specifying paths via -c and RUSTDESK_API_GIN_RESOURCES_PATH) when running without docker (#311) 2025-07-09 09:43:56 +08:00
lejianwen 77836a4e56 feat(user): add remark field to User model and form (#307) 2025-07-08 12:14:46 +08:00
lejianwen 09f8316bf1 feat: Update database version constant to 264 2025-07-08 12:13:31 +08:00
k3-cat c52706e621 feat: Improve oauth redirect (#303)
* fix: redirects after oauth can potentially misalign with server's actually hostname

* feat: remove `RedirectURL` from oauth config, as it should checked by provider rather than client

* feat: align oauth endpoint with the hostname in requests
2025-07-04 14:30:07 +08:00
k3-cat 17dcff4f43 feat: better autorenewal (#305) 2025-07-04 14:27:47 +08:00
Plynksiy Nikita 0b39c4e104 feat(password): Password hashing with bcrypt (#290)
* feat(password): add configurable password hashing with md5 and bcrypt

* docs: add password hashing algorithm configuration (bcrypt/md5)

* feat(password): better bcrypt fallback and minor refactoring

* feat(password): handle errors in password encryption and verification

* feat(password): remove password hashing algorithm configuration
2025-06-24 17:23:36 +08:00
Plynksiy Nikita ee176b314e feat: Use crypto/rand for secure random string generation (#293) 2025-06-18 20:47:24 +08:00
Plynksiy Nikita 1ffc9c4a5b fix: correct typo in build arg FRONTEND_GIT_REPO (#292) 2025-06-18 20:42:13 +08:00
Plynksiy Nikita 1257246552 feat(i18n): replace hardcoded messages with translated strings (#289) 2025-06-17 09:05:10 +08:00
lejianwen 2948eaaa5c chore: Update Go version to 1.23 in build configurations 2025-06-16 15:41:16 +08:00
lejianwen 8641ba5c0c docs: Update swagger docs 2025-06-16 12:31:48 +08:00
lejianwen 60b7a18fe7 feat: Add PostgreSQL support and refactor MySQL DSN handling (#284) 2025-06-16 12:26:08 +08:00
lejianwen ca068816ae feat: Add start time in /api/sysinfover 2025-06-16 12:23:48 +08:00
lejianwen 06648d9a6c fix(admin): Use admin-hello first
(#274) (#255)
2025-06-15 15:33:12 +08:00
puyujian 8a8abd5163 feat(oauth): 支持linux.do登录 (#280)
* 支持linux.do登录

* 修正
2025-06-15 15:32:20 +08:00
lejianwen 97f98cd6ce chore: update download links for musl cross-compilers 2025-06-05 12:14:17 +08:00
lejianwen 51f2920661 fix: Init sqlite fail(#266) 2025-06-04 09:31:43 +08:00
lejianwen 7a5d141ce8 fix(server): Port custom (#257) 2025-05-30 12:27:37 +08:00
lejianwen 3cef02a0bb fix(webclient): Peer online status 2025-05-29 18:51:37 +08:00
lejianwen 46a7ecc1ba fix: Captcha some problem when users login with same ip 2025-05-27 17:36:20 +08:00
lejianwen 4d2b037f5e docs: Readme 2025-05-25 17:44:29 +08:00
lejianwen 323364b24e feat(register): Register status can be set (#223) 2025-05-25 17:03:13 +08:00
lejianwen f19109cdf8 feat(login): Captcha upgrade and add the function to ban IP addresses (#250) 2025-05-25 16:52:58 +08:00
Tao Chen 527260d60a fix: dn should be case-insensitive (#250) 2025-05-21 09:07:08 +08:00
lejianwen 46bb44f0ab fix(webclient): DefaultIdServerPort undefined (#238) 2025-05-16 20:14:36 +08:00
lejianwen 2f1380f24a fix(webclient): Remove license warning (#235) 2025-05-13 13:11:19 +08:00
lejianwen ece3328e94 feat(webclient): Web client to 1.4.0 2025-05-12 20:16:08 +08:00
lejianwen fdd26d87be fix: PageSize (#225) 2025-05-06 19:08:18 +08:00
lejianwen 2ade0dda42 chore: Noelware/docker-manifest-action 2025-04-25 16:20:36 +08:00
lejianwen a87ae5cf65 chore: Noelware/docker-manifest-action 2025-04-25 14:34:45 +08:00
lejianwen fe7b8b53a6 style: Oauth page languages 2025-04-24 21:52:43 +08:00
lejianwen b929f3efdb style: Remove useless configurations 2025-04-15 10:52:46 +08:00
lejianwen f847fc076f fix: Low case (#149) 2025-04-15 10:46:21 +08:00
lejianwen 60d0a701ce fix: Share pwd 2025-04-15 10:09:56 +08:00
lejianwen 0dedaf6824 feat: Peer share to group 2025-04-14 19:12:40 +08:00
lejianwen ab231b3fed feat: Add SysInfoVer endpoint and AppService for version retrieval 2025-04-07 16:38:21 +08:00
lejianwen e7f28cca36 fix: Update peer based on the UUID (#180) 2025-04-02 09:50:16 +08:00
lejianwen 505e8aac4b feat: Add Korean translations validator (#168) 2025-04-02 09:42:29 +08:00
lejianwen 746e2a6052 fix: Get Uuids 2025-03-15 21:02:47 +08:00
lejianwen dc03d5d83d style: Update peer last online time logic (#173) 2025-03-15 21:02:08 +08:00
lejianwen b770ab178d feat(admin): Add filter by ip and username (#172) 2025-03-15 19:49:49 +08:00
Tao Chen fd7e022e88 fix: rm varify password accidentally (#176) 2025-03-15 19:40:02 +08:00
lejianwen ac5df6826b fix: Init database err (#166) 2025-03-04 18:14:25 +08:00
lejianwen 91908859bc docs: Readme 2025-03-04 16:30:12 +08:00
lejianwen 9c8822f857 fix: templates 2025-03-04 16:14:34 +08:00
lejianwen 9709da7fb6 style(webclient): ws-host 2025-03-04 15:48:25 +08:00
lejianwen 1852f10131 feat(config): add ws-host configuration (#156) 2025-03-04 15:43:25 +08:00
Tao Chen 77d7b43e21 fix: Fix/ldap tls (#162)
* optimize and fix tls of LDAP

* fix
2025-03-02 22:59:01 +08:00
lejianwen 7410b539a0 style(service): refactor global dependencies to use local variables 2025-02-26 19:15:38 +08:00
lejianwen 0403d71502 feat(oauth): Oauth nonce (#148) 2025-02-26 16:36:53 +08:00
lejianwen 2af1d93a7d feat(oauth): Oauth callback page beautification (#115) 2025-02-25 13:51:49 +08:00
lejianwen 76281ad761 feat(api): Add device group for 1.3.8 2025-02-23 21:35:42 +08:00
lejianwen d1ec9b4916 feat(api): Add /device-group/accessible for 1.3.8 2025-02-23 15:32:44 +08:00
lejianwen 448e7460a9 style(oidc): Oidc style 2025-02-21 09:49:41 +08:00
lejianwen ee0cbabffc fix(admin): Admin hello 2025-02-20 19:37:34 +08:00
lejianwen d6a5af890a style: No need exec sql on version 261 2025-02-20 19:22:22 +08:00
lejianwen dc313441e5 fix: Js content-type 2025-02-19 16:04:03 +08:00
Tao Chen c75320f4f4 feat(oidc): add pkce (#150) 2025-02-19 09:31:25 +08:00
lejianwen c788f78416 docs: Readme 2025-02-17 10:59:38 +08:00
lejianwen 49cf954d4a fix(config)!: Token expire time (#145)
将配置中的过期时间单位统一为time.Duration,可以设置为`h`,`m`,`s`
2025-02-17 10:49:59 +08:00
lejianwen 014e3db54f docs: Readme 2025-02-16 21:06:55 +08:00
lejianwen 6d9c245c81 fix(webclient): port 2025-02-16 14:17:37 +08:00
lejianwen 7fa9b79f31 fix(webclient): port 2025-02-16 14:11:36 +08:00
lejianwen c7f3d13b7f fix(webclient): port 2025-02-16 13:33:06 +08:00
lejianwen 46f08a89d2 feat: Login by pwd can be disable
---

Closes: #141
2025-02-16 13:06:45 +08:00
lejianwen 0dcfedb4dc fix(webclient)!: Webclient path is /ws/(relay|id) (#73 #143 #140)
Webclient 的反代引发了很多问题,现在将在HTTPS下的path固定为`/ws/(relay|id)`

---

Closes: #143 #140
2025-02-16 12:41:32 +08:00
lejianwen 918bf85a2d style: middleware name 2025-02-12 22:09:52 +08:00
lejianwen 99db5f7190 fix(admin): Admin web title 2025-02-12 21:10:07 +08:00
lejianwen 18eff791b2 style: Module name 2025-02-12 19:46:39 +08:00
lejianwen 624dcacac5 style: generate 2025-02-12 16:56:41 +08:00
lejianwen 878d5fd27c style: Remove generate 2025-02-12 16:25:04 +08:00
lejianwen 4b893ce0e8 docs: Docs 2025-02-12 16:14:51 +08:00
lejianwen 472524f836 style: Module name 2025-02-12 16:07:51 +08:00
lejianwen dbf8b23b15 fix: Config watchConfig (#135)
---
Closes: #135
2025-02-10 10:13:34 +08:00
lejianwen 79a5dd53ae fix: User disabled can not work (#133)
---
Closes: #133
2025-02-10 10:13:15 +08:00
Tao Chen 8a5b20685c fix: When OIDC and LDAP work togethar (#132 #134)
* fix OIDC create user if LDAP enable

* `newUser.GroupId = 1` for ldap

* fix
2025-02-10 10:08:49 +08:00
lejianwen 5a9c972de0 docs: Readme 2025-02-09 21:13:01 +08:00
Tao Chen fc0e67122d docs: add LDAP info (#130) 2025-02-09 19:36:31 +08:00
lejianwen eb642f66ca docs: Readme 2025-02-07 18:14:12 +08:00
lejianwen 8cac15f7dd style: Log time 2025-02-07 17:57:28 +08:00
lejianwen 5011e2b7c1 feat: Web sso env (#125) 2025-02-07 17:52:40 +08:00
lejianwen b0008143b1 docs: Up readme 2025-02-07 17:52:40 +08:00
lejianwen a3c3ab5a72 style: Up conf 2025-02-07 17:52:40 +08:00
lejianwen 3a16269215 docs: Up readme 2025-02-07 17:52:40 +08:00
lejianwen 151145b0c3 feat: Random Initial Password for Admin (#117) 2025-02-07 17:52:39 +08:00
lejianwen 9c794e9d4b fix(build): Fix no admin in deb (#119 #120) 2025-02-03 13:29:35 +08:00
lejianwen 01f697d279 fix(api): Add Default Token Expire (#113) 2025-02-03 13:18:08 +08:00
lejianwen 6cdc37333b style: webclient 2025-02-03 00:01:10 +08:00
Tao Chen ae32915565 feat(ldap): Add LDAP
* rename: Admin to AdminGroup

* update

* cleanup

* tmp save group mapping

* add enableControl(not-test)

* verify username exist before create(for LDAP)

* add getAllGroupsDn()

* rename

* adminGroup

* enable TLS Verify

* init for ldap

---------

Co-authored-by: Tao Chen <iamtaochen@outlook.com>
2025-02-02 23:59:52 +08:00
lejianwen f49457dc5b feat(webclient): Up to 1.3.7 2025-01-21 19:12:28 +08:00
lejianwen d9e2e247ea feat(api): Add api token expire
Resolves #109
2025-01-21 18:23:28 +08:00
lejianwen c6f2f2f150 feat(api): Add api/version
Resolves #110
2025-01-20 20:04:22 +08:00
lejianwen 56b9c66cb8 docs: Up Swagger docs 2025-01-20 19:35:47 +08:00
lejianwen 5d8a0d0e1f style: Add Start Tips 2025-01-20 13:12:45 +08:00
lejianwen f4cb9beda5 fix(api): Change tag to alphabetical sorting
Fixes: #108
2025-01-20 13:07:41 +08:00
lejianwen b66fc3c06d fix(docs): Api Route doc 2025-01-19 13:10:43 +08:00
lejianwen ab2e1a9236 feat(i18n): Add ZH_TW 2025-01-19 13:10:19 +08:00
Jia-Bin ab77b400a1 Add Traditional Chinese 2025-01-18 23:04:39 +08:00
lejianwen eb7ab63563 docs: Up readme 2025-01-16 22:01:23 +08:00
lejianwen 4cf7d01622 docs: Up readme 2025-01-16 21:59:46 +08:00
lejianwen a876078a9c feat(server): Rustdesk Id Server Port & Relay Server Port #104 2025-01-16 20:57:00 +08:00
lejianwen 495f2ae3c6 refactor(config): Up Config Load 2025-01-16 20:40:42 +08:00
lejianwen 4e6d11baf0 docs: Up readme 2025-01-15 21:56:04 +08:00
lejianwen a951b982b3 fix: Jwt 2025-01-15 20:26:26 +08:00
lejianwen a33be66504 docs: Up readme 2025-01-15 20:09:08 +08:00
lejianwen f41b9d5887 feat!: Add JWT
- `RUSTDESK_API_JWT_KEY`如果设置,将会启用JWT,token自动续期功能将失效
- 此功能是为了server端校验token的合法性
2025-01-15 19:25:28 +08:00
lejianwen 3c608463e6 docs: Up readme 2025-01-12 23:12:00 +08:00
lejianwen eeffbe124a docs: Up readme 2025-01-12 21:35:34 +08:00
lejianwen d7f2d54faa feat(server): Add Rustdesk Relay Server Commands 2025-01-04 20:49:44 +08:00
lejianwen 7db4b03634 style(server): fmt print to log 2025-01-02 21:49:37 +08:00
lejianwen 77760a681a docs: Up readme 2025-01-02 17:03:07 +08:00
lejianwen f9c1447ceb fix: Fix Dockerfile_full_s6 2024-12-31 23:33:17 +08:00
lejianwen fb749c1902 fix(server): Fix Rustdesk Sys Command 2024-12-31 23:29:05 +08:00
lejianwen 240c44aa07 feat(server): Add Rustdesk Command
And add build full s6 image for rustdesk command
2024-12-31 23:16:15 +08:00
lejianwen 92cd8642c8 docs(readme): Up readme
Connection timeout issues move to #92
2024-12-30 13:36:57 +08:00
lejianwen 89d90cf919 docs(readme): Up readme
Connection timeout issues move to #92
2024-12-30 13:35:06 +08:00
lejianwen 920c6b6d8b docs(readme): Up readme
Connection timeout issues move to #92
2024-12-30 13:33:11 +08:00
lejianwen 1dd4df3a1c chore(buildTest): add start.bat to run on windows 2024-12-27 20:13:55 +08:00
lejianwen c7d44cc253 fix(build): add start.bat to run on windows(#89) 2024-12-27 20:09:08 +08:00
lejianwen 5082ab1893 refactor(admin): Move Admin Web Route to user model 2024-12-27 19:27:33 +08:00
lejianwen e8b2425222 feat(admin): Add My Login log 2024-12-27 19:25:59 +08:00
lejianwen 09d12cefd8 feat(admin): Support Markdown to welcome msg 2024-12-25 19:21:50 +08:00
lejianwen 5f1166965d fix(api): Get ab list when personal is disabled (#86) 2024-12-25 19:04:42 +08:00
lejianwen 0dbab182e9 fix(webclient): share fail when expire is 0
Closes: #88
2024-12-25 15:01:03 +08:00
lejianwen 512f3f99fd fix(build): fix build_test.yml 2024-12-25 14:06:29 +08:00
lejianwen 6fb4fad705 fix(build): up build.yml to build deb 2024-12-25 13:20:12 +08:00
lejianwen fa92529e9b chore(build): up build.yml to build deb 2024-12-25 12:57:11 +08:00
Follow the windandymwl d6c6051a6c feat(build): 添加构建deb包相关基础 (#87)
* 添加构建deb包相关基础

* 补齐工作流,等待验证

* 修复构建时没有创建的data目录保障deb包构建

* 修复其余架构deb包构建中的依赖错误

* 修复:由于小改工作流导致写错架构的问题

* 修复拼写错误导致的目录错误

* 添加上传工件,和发布rel工作流,完成相关事务

---------

Co-authored-by: ymwl <ymwlpoolc@qq.com>
2024-12-25 12:28:51 +08:00
lejianwen ce063bd3ac feat(webclient): v1.3.5 -> v1.3.6 2024-12-24 10:25:47 +08:00
lejianwen 4468894dfb chore(changelog): up build.yml to generate changelog 2024-12-22 14:14:51 +08:00
lejianwen 8b00b919ad chore(changelog): up build.yml to generate changelog 2024-12-22 14:04:23 +08:00
64f4a6dfac feat(i18n): Merge pull request #85 from jimmyGALLAND/trans-fr
add locale french
2024-12-22 13:57:56 +08:00
jimmyGALLAND 6faa5153b6 add locale french 2024-12-21 22:56:48 +01:00
lejianwen a771b1e9b0 fix(webclient): remove console.log when query online by new 2024-12-21 21:49:03 +08:00
lejianwen 7750f9c54d chore(changelog): up build.yml to add changelog 2024-12-21 21:39:11 +08:00
lejianwen b2d24ee67b docs(webclient): up readme 2024-12-21 21:31:54 +08:00
lejianwen 589a2a5123 feat(webclient): add new query_online function
There may be a loss of performance
Therefore, it is not enabled by default
2024-12-21 21:15:06 +08:00
lejianwen 184d3d357d optimize add ab from peer #84 2024-12-20 11:11:32 +08:00
lejianwen 50b3d85270 up docs and readme 2024-12-18 14:28:06 +08:00
lejianwen 09fdd34ba3 fix captcha 2024-12-18 13:51:06 +08:00
lejianwen bba10261c5 fix captcha 2024-12-18 13:36:01 +08:00
lejianwen 46bfe54097 add show-swagger config #83 2024-12-18 12:50:09 +08:00
lejianwen 503e7a307e up docs 2024-12-18 12:44:06 +08:00
lejianwen 821b0a6faf add captcha #82 2024-12-18 12:43:55 +08:00
lejianwen d60fdff179 split my from admin 2024-12-17 21:41:56 +08:00
lejianwen fdd841e82a add batch add ab from peer and up my 2024-12-13 16:27:12 +08:00
lejianwen 2d6f0a116a add share record manage 2024-12-13 12:32:36 +08:00
lejianwen bd13fe4ef4 up web client v2 2024-12-10 18:26:08 +08:00
lejianwen 6e1b208464 up README.md 2024-12-10 15:28:05 +08:00
lejianwen 76433a409e up README.md 2024-12-09 13:43:04 +08:00
lejianwen 9b4fa679c2 add batch add ab from peer
add batch update ab tags
2024-12-06 19:45:41 +08:00
lejianwen c2ae95c4cc up api docs 2024-12-06 10:36:40 +08:00
lejianwen b2b7f60fd5 add batch delete user token 2024-12-06 10:36:27 +08:00
lejianwen a465888b31 up username length to 32 #70 2024-12-06 10:22:28 +08:00
lejianwen d368bdc84c up web client v2 2024-12-04 13:43:04 +08:00
lejianwen cdc1150505 up readme 2024-11-28 12:42:15 +08:00
32d525c53c Create LICENSE 2024-11-26 17:29:46 +08:00
lejianwen a89b40c607 add es lang 2024-11-26 10:43:01 +08:00
lejianwen b6bd9150d9 up web client v2 from rustdesk 2024-11-22 19:54:19 +08:00
lejianwen 96e3e3bc86 up docs 2024-11-22 19:53:49 +08:00
lejianwen 41377f41bb Split the language 2024-11-22 19:39:28 +08:00
lejianwen fb744f81e2 up img 2024-11-20 19:33:27 +08:00
lejianwen 750c3bcbcd fix #62 2024-11-20 19:32:44 +08:00
lejianwen d4015d7284 fix 2024-11-20 09:20:29 +08:00
lejianwen a9bf3fda73 fix https://github.com/lejianwen/rustdesk-api/discussions/59#discussioncomment-11306760 2024-11-20 09:17:29 +08:00
lejianwen 7f467a4814 up web client v2 2024-11-18 21:39:18 +08:00
lejianwen 9f10b5e983 up readme 2024-11-17 18:27:15 +08:00
lejianwen 5291270e6a up ws connect in https #12 2024-11-17 17:34:51 +08:00
lejianwen 56bba381d8 fix 2024-11-16 22:08:06 +08:00
lejianwen 2ff276b162 up package lock 2024-11-16 20:56:26 +08:00
lejianwen d77191ce0f up ws js 2024-11-16 20:03:30 +08:00
lejianwen f99803aef4 up 2024-11-16 19:42:13 +08:00
lejianwen e09fa17013 add webclientv2 2024-11-16 18:33:02 +08:00
lejianwen c7e69aa8a5 fix gitignore 2024-11-15 21:43:23 +08:00
ljw 9548068283 up readme 2024-11-12 11:54:21 +08:00
ljw 09958c78f3 up readme 2024-11-12 11:53:57 +08:00
ljw aced098982 add batch delete log #57 2024-11-12 09:08:10 +08:00
ljw 7862a34760 up admin conf 2024-11-12 08:43:49 +08:00
ljw 1384d28cac add admin conf 2024-11-11 22:26:15 +08:00
ljw 24b7338153 up readme 2024-11-09 20:38:11 +08:00
ljw 30d254eaef fix #55 2024-11-09 20:14:14 +08:00
ljw bb8a936ade add build_test.yml 2024-11-08 16:09:50 +08:00
ljw 61044fd30b add build_test.yml 2024-11-08 16:05:43 +08:00
ljw 22a4546d0f add cmd 2024-11-08 15:54:49 +08:00
ljw 07450416ed fix #52 & add auto refresh token #53 2024-11-07 10:46:00 +08:00
0d6db0d2a1 Merge pull request #52 from IamTaoChen/fix/bug
fix: cannot delete user
2024-11-07 10:21:50 +08:00
Tao Chen ab30b3407b add error information 2024-11-06 15:06:15 +08:00
Tao Chen 7a4c735803 fix: cannot delete user 2024-11-06 14:36:12 +08:00
ljw 654c764019 fix migrate 2024-11-05 21:07:39 +08:00
ljw 7101139250 fix migrate 2024-11-05 21:07:31 +08:00
ljw 793614841a fix migrate 2024-11-05 21:03:32 +08:00
ljw 94f2ac5b2a fix username length #48 2024-11-05 11:57:16 +08:00
ljw d4d39eecaa up oauth re 2024-11-05 11:48:35 +08:00
ljw 8af01c859c Merge branch 'oauth_re' of https://github.com/IamTaoChen/rustdesk-api into IamTaoChen-oauth_re 2024-11-05 08:24:48 +08:00
Tao Chen 3af92d03e8 modify google ro re-use oidc 2024-11-04 21:30:58 +08:00
Tao Chen f17d891302 fix: delete check 2024-11-03 22:23:24 +08:00
Tao Chen 51623436b0 fix: call us.IsAdmin(u) to check admin 2024-11-03 21:59:17 +08:00
Tao Chen 1b7c7eef8f fix google 2024-11-03 18:04:28 +08:00
Tao Chen 15e4c7e522 re-use responseLoginSuccess 2024-11-03 17:25:27 +08:00
Tao Chen 120ab132a9 fix: last admin shouldn't be deleted, disabled or demoted 2024-11-03 17:19:05 +08:00
Tao Chen 0b52e8faa8 fix: Github AvatarUrl to OauthUser 2024-11-03 16:49:28 +08:00
Tao Chen 60eaaf390a add err for RegisterByOauth 2024-11-03 16:49:03 +08:00
Tao Chen 9101badb1c fronted for docker-dev 2024-11-03 16:34:50 +08:00
Tao Chen 7082111b34 optimize /admin/login-options 2024-11-03 05:37:34 +08:00
Tao Chen a156f2681e chroe 2024-11-03 05:34:19 +08:00
Tao Chen 7cb823c957 add Avatar to OauthUser 2024-11-03 05:33:59 +08:00
Tao Chen 817f612224 low case email 2024-11-03 05:25:10 +08:00
Tao Chen 1cbaf9d6bc const var for op name 2024-11-03 05:13:22 +08:00
Tao Chen d353f9837f fix: email from github 2024-11-03 05:11:31 +08:00
Tao Chen 14beef72fc fix: Email of Register 2024-11-03 05:07:17 +08:00
Tao Chen 91a33fe7f6 fix: RegisterByOauth without Email 2024-11-03 04:35:39 +08:00
ljw 7ad7a0ff41 fix #45 2024-11-02 18:49:16 +08:00
Tao Chen d646469f71 set user_id=0 at peers, when the user is deleted 2024-11-02 08:24:07 +08:00
Tao Chen 4f616ffff1 When login, peer doesn't exist, it should create 2024-11-02 08:19:44 +08:00
Tao Chen 64400fba61 delete the token when delete a peer 2024-11-02 08:02:03 +08:00
Tao Chen fc15e8c63d add MyPeers for user 2024-11-02 07:35:26 +08:00
Tao Chen cbba1e5317 add email for register 2024-11-02 05:43:55 +08:00
Tao Chen 75b997dcc4 add DeviceId to userToken 2024-11-02 05:42:47 +08:00
Tao Chen 853063c59b logout should unbind uuid and uid of peer 2024-11-02 05:07:41 +08:00
Tao Chen 5c65edb8fa fix bug ValidateOauthProvider location 2024-11-02 04:20:00 +08:00
Tao Chen 7707cc116f re-construct oauth 2024-11-02 04:01:28 +08:00
ljw 737fe749de load key from file 2024-11-01 14:56:11 +08:00
b9c6f17e3f Merge pull request #42 from IamTaoChen/docker
Docker Optimize
2024-11-01 13:10:59 +08:00
Tao Chen af6a340003 add more 2024-11-01 01:33:08 +08:00
Tao Chen 8ba3bee944 optimize scripts 2024-11-01 01:33:05 +08:00
Tao Chen 153c3566b6 optimize build speed, like cache and mirror 2024-11-01 01:32:45 +08:00
Tao Chen 97a4753f4f add ARG CONTRY=CN to improve the alpinelinux install speed 2024-11-01 00:29:33 +08:00
Tao Chen 74c3899b55 add bash to run dev-docker 2024-11-01 00:28:43 +08:00
ljw 273ac6d1a8 add remove user token #34 2024-10-31 22:29:12 +08:00
5edbb39a63 Merge pull request #40 from IamTaoChen/resetEmptyPassWD
Reset empty password
2024-10-31 18:46:34 +08:00
Tao Chen 0c974c4113 Merge branch 'master' into resetEmptyPassWD 2024-10-31 16:35:32 +08:00
Tao Chen 46657a525d ommit check old passwd if password is empty 2024-10-31 16:23:06 +08:00
Tao Chen b36aa6f917 add IsPasswordEmpty... 2024-10-31 16:22:42 +08:00
ljw cddb0ebef9 up readme #28 2024-10-31 15:48:36 +08:00
ljw 788c4e3531 up readme #28 2024-10-31 15:47:39 +08:00
ljw 47f9ad8274 add register 2024-10-31 15:14:30 +08:00
ljw 855beb7fa9 up oauth 2024-10-31 14:03:48 +08:00
f57816b1b0 Merge pull request #36 from IamTaoChen/oidc-for-web
OIDC for web
2024-10-31 11:10:46 +08:00
Tao Chen ff08fefc30 rename build stage 2024-10-31 09:21:43 +08:00
Tao Chen f792ab9055 add some /admin/ to surport web OIDC 2024-10-31 09:21:30 +08:00
ljw 63af103a4e fix buidconfirm 2024-10-30 20:59:51 +08:00
ljw 0a36d44cec up del user 2024-10-30 19:34:56 +08:00
a1f4e1de84 Merge pull request #32 from IamTaoChen/bug/odic-user
delete user from user_thirds and update README
2024-10-30 19:08:50 +08:00
Tao Chen 05b20d47db modify delete user 2024-10-30 16:33:01 +08:00
Tao Chen 6b746f13d1 update README 2024-10-30 16:31:47 +08:00
Tao Chen e838d5bcd2 update README for OIDC 2024-10-30 16:29:49 +08:00
Tao Chen 0dcc21260e delete user from user_thirds, too 2024-10-30 15:59:33 +08:00
ljw 3c30ad145c up v 2024-10-30 15:46:12 +08:00
ljw 06b0a8e873 add docker-compose-dev.yaml 2024-10-30 15:34:45 +08:00
b7de2ccadd Merge pull request #30 from IamTaoChen/oidc
Add General OIDC Login
2024-10-30 14:40:10 +08:00
Tao Chen b52c5cfca1 bind oidc ThirdEmail 2024-10-29 23:09:54 +08:00
Tao Chen fe910c37cf fix: spelling 2024-10-29 23:00:17 +08:00
Tao Chen 337ef330eb fix bug 2024-10-29 18:48:37 +08:00
Tao Chen ffa47177aa fix bug - oidc scopes 2024-10-29 18:46:45 +08:00
ljw 46a76853c3 fix oauth register #26 #23 2024-10-29 15:31:27 +08:00
Tao Chen 2cd7dfb2b3 fix bug 2024-10-29 14:27:15 +08:00
Tao Chen fee2808bca try add oidc 2024-10-29 11:51:01 +08:00
Tao Chen 49e5eb186a optimize docker 2024-10-29 11:50:55 +08:00
Tao Chen dee2865466 optimize build.sh 2024-10-29 10:58:17 +08:00
ljw eb340b2615 add last online ip #24 2024-10-28 20:24:34 +08:00
ljw e714549a95 up address book add version #20 2024-10-28 19:48:47 +08:00
ljw a1367bcd3d up peer update 2024-10-28 19:15:13 +08:00
ljw 642351dafd fix bug #27 2024-10-28 16:08:33 +08:00
ljw 90b9b5adba up 2024-10-28 14:54:00 +08:00
ljw 5bf4bbe45f add address book name &
add share address book
2024-10-28 14:51:07 +08:00
ljw 036f928fa3 up readme 2024-10-23 11:09:28 +08:00
ljw 94e7b31fb6 fix group 2024-10-23 11:09:13 +08:00
ljw be4742382d up build.yml 2024-10-23 09:19:02 +08:00
ljw 70d2f1a055 add armv7l build #21 2024-10-23 09:03:01 +08:00
ljw 877fe50049 add ru lang 2024-10-22 19:46:38 +08:00
ljw 7d505705ee add ko lang,but validator dont have translations ko 2024-10-22 12:21:32 +08:00
ljw 38f81a03b5 Merge branch 'master' of https://github.com/lejianwen/rustdesk-api 2024-10-22 11:31:01 +08:00
d549d23819 Merge pull request #19 from jkh0kr/master
Add Korean language file
2024-10-22 11:30:49 +08:00
ljw 934675e0f0 up 2024-10-22 11:28:27 +08:00
진기환 2be397aa38 Add Korean language file 2024-10-22 10:35:58 +09:00
ljw a0a422ed45 up readme 2024-10-21 21:35:27 +08:00
ljw fcce10c695 add file conn log 2024-10-21 21:08:25 +08:00
ljw 30eb14702f up build.yml 2024-10-20 20:26:08 +08:00
ljw 3679fcc874 fix group create type 2024-10-20 20:15:12 +08:00
ljw d085b4e3c2 up readme 2024-10-20 19:40:49 +08:00
dc8fcdf214 Merge pull request #17 from Ogannesson/master
Add proxy option for Google Oauthon
2024-10-20 19:05:01 +08:00
Oganneson 8bab23b65b Add oauth callback via proxy
Improved support for environment variables and configuration files, and standardized default behaviors
2024-10-20 17:56:11 +08:00
ljw f64022e411 add conn log 2024-10-18 15:05:58 +08:00
ljw 2d37302cf9 fix write when heartbeat #14 2024-10-17 10:24:02 +08:00
ljw 1a1856257d fix write when heartbeat #14 2024-10-16 21:32:55 +08:00
ljw 24f570b64f fix pc add #13 2024-10-16 10:10:20 +08:00
ljw 6322177b71 fix pc add #13 2024-10-16 09:28:39 +08:00
ljw d2390d1cb3 Revert "add webclient v2 preview"
This reverts commit 399c32da7d.
2024-10-15 16:35:34 +08:00
ljw 6fe6f6b708 Revert "up readme"
This reverts commit a656f4fec3.
2024-10-15 16:35:34 +08:00
ljw a656f4fec3 up readme 2024-10-15 16:13:42 +08:00
ljw 399c32da7d add webclient v2 preview 2024-10-15 16:11:40 +08:00
ljw 62167836dc fix docs 2024-10-15 14:51:19 +08:00
ljw caef3897a0 add login fail warn &
add web client on/off &
up admin peer filter &
upgrade web client
2024-10-14 10:43:29 +08:00
ljw 5ef6810e3f up readme 2024-10-12 10:02:04 +08:00
ljw ae2079f583 Revert "Revert "up readme""
This reverts commit aa65382a0f.
2024-10-11 22:45:35 +08:00
ljw aa65382a0f Revert "up readme"
This reverts commit 18c61a2bfc.
2024-10-11 22:06:20 +08:00
ljw 18c61a2bfc up readme 2024-10-11 21:39:58 +08:00
ljw 7cc1a8a58a up readme 2024-10-11 10:11:42 +08:00
ljw cf9feac702 up readme 2024-10-10 13:00:29 +08:00
ljw a963cd0209 fix readme 2024-10-10 12:40:54 +08:00
ljw 6a5408f9b8 up gorm logger & add share to guest by web client 2024-10-09 15:53:08 +08:00
ljw 9aad62d1e4 build tag 2024-09-29 12:47:04 +08:00
ljw 867eab40f8 build default push to docker 2024-09-29 12:39:33 +08:00
ljw eb5c7efc4c fix build 2024-09-29 12:23:34 +08:00
857abc16e7 Merge pull request #5 from gigaion/new-build-1
build.yml - Add GHCR & Dynamic Inputs
2024-09-29 12:12:17 +08:00
ljw 28b9866c42 upgrade: init by i18n
add: batch delete peer
add: batch peer to addressbook
2024-09-29 11:53:58 +08:00
Gigaion a27deb0a41 build.yml - Add GHCR & Dynamic Inputs
build.yml - Add GHCR & Dynamic Inputs
2024-09-28 13:30:44 -07:00
ljw 8e026de20b test 2024-09-28 11:01:23 +08:00
ljw 718ecc2372 test 2024-09-28 10:12:56 +08:00
ljw 56d46722f4 test 2024-09-28 10:05:04 +08:00
ljw b6463cd715 test 2024-09-28 09:57:32 +08:00
ljw bd3ae0cbfe fix build docker image 2024-09-28 09:39:26 +08:00
ljw 83c3aa894f fix build docker image 2024-09-28 09:33:59 +08:00
ljw 1b88d26fea up build 2024-09-27 22:08:36 +08:00
ljw 588287fdb4 up build 2024-09-27 22:06:04 +08:00
ljw 688e544b07 up build 2024-09-27 22:03:06 +08:00
ljw 3e3f812e83 up build 2024-09-27 21:48:48 +08:00
ljw b551c7abe4 up build 2024-09-27 21:37:12 +08:00
ljw 6d1e7a4c05 up build 2024-09-27 21:29:19 +08:00
ljw 3341a4bc8e up build docker echo manifest 2024-09-27 21:20:54 +08:00
ljw 1c84980d36 up build docker 2024-09-27 20:10:17 +08:00
ljw 833b25881d up build docker 2024-09-27 20:06:49 +08:00
ljw 9dbf58903c up build docker 2024-09-27 19:40:48 +08:00
ljw ad007f0d91 up build docker 2024-09-27 18:49:22 +08:00
ljw 4b06973a52 up build docker 2024-09-27 18:48:09 +08:00
ljw 159a67f15d up build docker 2024-09-27 17:49:17 +08:00
ljw 7c03b9953b up build docker 2024-09-27 17:32:25 +08:00
ljw f90987de8d up build docker 2024-09-27 17:26:40 +08:00
ljw 70e4ff7820 up build docker 2024-09-27 17:25:30 +08:00
ljw a99356f54b up build docker 2024-09-27 17:24:25 +08:00
ljw c5bc9534cc up build docker 2024-09-27 17:15:06 +08:00
ljw a40733424f up build docker 2024-09-27 16:52:02 +08:00
ljw a937efc60e up build docker 2024-09-27 16:07:06 +08:00
ljw 6adb0e8415 up build docker 2024-09-27 15:59:12 +08:00
ljw ff9ffb2f12 up build docker 2024-09-27 15:31:43 +08:00
ljw 9be4f472ae up build docker 2024-09-27 15:23:19 +08:00
ljw 8581d74b08 up build docker 2024-09-27 15:18:45 +08:00
ljw dafe9bd6b6 up build docker 2024-09-27 14:58:17 +08:00
ljw 3ae5772360 up build docker 2024-09-27 14:54:11 +08:00
ljw 4628dbccfb up build docker 2024-09-27 14:46:39 +08:00
ljw 572b1d4c14 up build docker 2024-09-27 14:35:43 +08:00
ljw bdb70e9859 up build docker 2024-09-27 14:29:55 +08:00
ljw 38bda17271 up build docker 2024-09-27 14:24:17 +08:00
ljw 455e1d2e5b up build docker 2024-09-27 14:19:56 +08:00
ljw 89cd724bab up build docker 2024-09-27 14:18:36 +08:00
ljw b9109b4d0e up build docker 2024-09-27 14:16:59 +08:00
ljw 945958f552 up build docker 2024-09-27 14:10:50 +08:00
ljw 78eb0d5c06 up release_arm64.yml 2024-09-27 10:43:48 +08:00
ljw bc6eae711e up release_arm64.yml 2024-09-27 10:38:14 +08:00
ljw f0a4bf6164 up docker_arm64.yml 2024-09-26 14:36:15 +08:00
ljw fc3b5e3ac3 up docker_arm64.yml 2024-09-26 14:33:01 +08:00
ljw f7235ac847 up docker_arm64.yml 2024-09-26 14:26:15 +08:00
ljw 231f4ddb7f up docker_arm64.yml 2024-09-26 14:24:14 +08:00
ljw 3cad3994cb add docker_arm64.yml 2024-09-26 14:18:57 +08:00
ljw 8c97cc8686 up README 2024-09-26 13:38:43 +08:00
ljw 7ae976ee5d up README_EN.md 2024-09-26 13:21:17 +08:00
ljw e91b53eb32 test release_arm64.yml 2024-09-26 11:49:11 +08:00
ljw 90311536a7 test release_arm64.yml 2024-09-26 11:46:17 +08:00
ljw e951b7f2f9 fix Dockerfile 2024-09-26 09:29:02 +08:00
ljw e0f94b62cf add i18n 2024-09-25 22:42:36 +08:00
ljw 8cb701ec85 add i18n 2024-09-25 22:41:57 +08:00
ljw 9afd11e3b8 up readme 2024-09-24 21:16:03 +08:00
ljw a1d495f2db fix group peers 2024-09-24 19:35:20 +08:00
ljw 652fa93910 up readme 2024-09-24 15:22:21 +08:00
ljw ef414855f0 up docs 2024-09-24 15:16:07 +08:00
ljw 76cf35cdf0 up readme 2024-09-24 15:15:26 +08:00
ljw 9d7aa05032 add personal apis 2024-09-24 14:43:27 +08:00
ljw 62a22c697d up web client can get pwd if exist 2024-09-24 10:15:04 +08:00
ljw be497a5aa7 add docker.yml 2024-09-23 14:43:43 +08:00
ljw fc3e16bc63 up README.md 2024-09-23 10:21:43 +08:00
ljw df35912461 up release.yml 2024-09-23 10:13:44 +08:00
ljw 0ddc66a854 up release.yml 2024-09-23 10:10:29 +08:00
ljw 716d557d66 up test.yml 2024-09-23 10:07:10 +08:00
ljw f9edcb9d47 up test.yml 2024-09-22 21:40:17 +08:00
ljw d4623c5bc9 up test.yml 2024-09-22 21:28:43 +08:00
ljw 02ba4a3330 up test.yml 2024-09-22 20:30:12 +08:00
ljw a72d4eaf78 up test.yml 2024-09-22 19:46:37 +08:00
ljw 4d3abb2dc0 up test.yml 2024-09-22 17:58:42 +08:00
ad6a8d1f7a Update test.yml 2024-09-21 22:49:06 +08:00
a5c8c2ac97 Update test.yml 2024-09-21 21:55:36 +08:00
1237004cb1 Update test.yml 2024-09-21 21:44:43 +08:00
c2bcd17df7 Update go.yml 2024-09-21 21:43:31 +08:00
bb49cbdd50 Update test.yml 2024-09-21 21:40:36 +08:00
6ad770a824 Create test.yml 2024-09-21 21:35:55 +08:00
593eeb3ac3 Update go.yml 2024-09-21 21:17:03 +08:00
6a7be3ef84 Create go.yml 2024-09-21 21:13:54 +08:00
208 changed files with 224681 additions and 3453 deletions
-61
View File
@@ -1,61 +0,0 @@
name: Build & Push Docker Image
# Builds the Docker image and publishes it to the Gitea container registry
# at git.hackner.dev/thomas/rustdesk-api.
#
# Requires a running Gitea Actions runner (act_runner) and two repo secrets
# (Settings -> Actions -> Secrets):
# REGISTRY_USER - Gitea username (e.g. thomas)
# REGISTRY_PASSWORD - a Gitea access token with "write:package" scope
#
# (Alternatively the built-in ${{ secrets.GITHUB_TOKEN }} can be used with
# username ${{ gitea.actor }} if your Gitea grants it package write access.)
on:
push:
branches:
- master
tags:
- 'v*.*.*'
workflow_dispatch:
env:
REGISTRY: git.hackner.dev
IMAGE_NAME: ${{ github.repository }} # -> thomas/rustdesk-api
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Gitea container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.dev
push: true
build-args: |
GO_VERSION=1.23
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+444
View File
@@ -0,0 +1,444 @@
name: Build
on:
workflow_dispatch:
inputs:
BASE_IMAGE_NAMESPACE:
description: 'Base image namespace (Default: Your Github username)'
required: false
default: ''
DOCKERHUB_IMAGE_NAMESPACE:
description: 'Docker Hub image namespace (Default: Your Github username)'
required: false
default: ''
GHCR_IMAGE_NAMESPACE:
description: 'GitHub Container Registry image namespace (Default: Your Github username)'
required: false
default: ''
SKIP_DOCKER_HUB:
description: 'Set to true to skip pushing to Docker Hub (default: false)'
required: false
default: 'false'
SKIP_GHCR:
description: 'Set to true to skip pushing to GHCR (default: false)'
required: false
default: 'false'
WEBCLIENT_SOURCE_LOCATION:
description: 'Web Client API Repository'
required: true
default: 'https://github.com/lejianwen/rustdesk-api-web'
push:
tags:
- 'v*.*.*' # 当推送带有版本号的 tag(例如 v1.0.0)时触发工作流
- 'test*'
env:
LATEST_TAG: latest
WEBCLIENT_SOURCE_LOCATION: ${{ github.event.inputs.WEBCLIENT_SOURCE_LOCATION || 'https://github.com/lejianwen/rustdesk-api-web' }}
BASE_IMAGE_NAMESPACE: ${{ github.event.inputs.BASE_IMAGE_NAMESPACE || github.actor }}
DOCKERHUB_IMAGE_NAMESPACE: ${{ github.event.inputs.DOCKERHUB_IMAGE_NAMESPACE || github.actor }}
GHCR_IMAGE_NAMESPACE: ${{ github.event.inputs.GHCR_IMAGE_NAMESPACE || github.actor }}
SKIP_DOCKER_HUB: ${{ github.event.inputs.SKIP_DOCKER_HUB || 'false' }}
SKIP_GHCR: ${{ github.event.inputs.SKIP_GHCR || 'false' }}
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
job:
- { platform: "amd64", goos: "linux", file_ext: "tar.gz" }
- { platform: "arm64", goos: "linux", file_ext: "tar.gz" }
- { platform: "armv7l", goos: "linux", file_ext: "tar.gz" }
- { platform: "amd64", goos: "windows", file_ext: "zip" }
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
with:
repository: lejianwen/rustdesk-api-web
path: rustdesk-api-web
ref: master
- name: Set up Go environment
uses: actions/setup-go@v4
with:
go-version: '1.23' # 选择 Go 版本
- name: Set up npm
uses: actions/setup-node@v2
with:
node-version: '20'
- name: build rustdesk-api-web
working-directory: rustdesk-api-web
run: |
npm install
npm run build
mkdir -p ../resources/admin/
cp -ar dist/* ../resources/admin/
- name: tidy
run: go mod tidy
- name: Get tag version
run: |
TAG_VERSION="${GITHUB_REF##*/}"
VERSION="${TAG_VERSION#v}"
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Write version to resources/version
run: echo $VERSION > resources/version
- name: swag
run: |
go install github.com/swaggo/swag/cmd/swag@latest
swag init -g cmd/apimain.go --output docs/api --instanceName api --exclude http/controller/admin
swag init -g cmd/apimain.go --output docs/admin --instanceName admin --exclude http/controller/api
- name: Build for ${{ matrix.job.goos }}-${{ matrix.job.platform }}
run: |
mkdir release -p
cp -ar resources release/
cp -ar docs release/
cp -ar conf release/
mkdir -p release/data
mkdir -p release/runtime
if [ "${{ matrix.job.goos }}" = "windows" ]; then
sudo apt-get install gcc-mingw-w64-x86-64 zip -y
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain.exe ./cmd/apimain.go
echo @echo off > release/start.bat
echo cmd /c \"%~dp0apimain.exe\" >> release/start.bat
zip -r ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
else
if [ "${{ matrix.job.platform }}" = "arm64" ]; then
wget https://musl.ljw.red/aarch64-linux-musl-cross.tgz
tar -xf aarch64-linux-musl-cross.tgz
export PATH=$PATH:$PWD/aarch64-linux-musl-cross/bin
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=aarch64-linux-musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
elif [ "${{ matrix.job.platform }}" = "armv7l" ]; then
wget https://musl.ljw.red/armv7l-linux-musleabihf-cross.tgz
tar -xf armv7l-linux-musleabihf-cross.tgz
export PATH=$PATH:$PWD/armv7l-linux-musleabihf-cross/bin
GOOS=${{ matrix.job.goos }} GOARCH=arm GOARM=7 CC=armv7l-linux-musleabihf-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
else
sudo apt-get install musl musl-dev musl-tools -y
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
fi
tar -czf ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: |
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Changelog
if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'push'
run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
deb-package:
name: debian package - ${{ matrix.job.platform }}
needs: build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
job:
- { platform: "amd64", goos: "linux", debian_platform: "amd64", crossbuild_package: ""}
- { platform: "arm64", goos: "linux", debian_platform: "arm64", crossbuild_package: "crossbuild-essential-arm64" }
- { platform: "armv7l", goos: "linux", debian_platform: "armhf", crossbuild_package: "crossbuild-essential-armhf" }
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Create packaging env
run: |
sudo apt update
DEBIAN_FRONTEND=noninteractive sudo apt install -y devscripts build-essential debhelper pkg-config ${{ matrix.job.crossbuild_package }}
mkdir -p debian-build/${{ matrix.job.platform }}/bin
- name: Get tag version
id: get_tag
run: |
TAG_VERSION="${GITHUB_REF##*/}"
VERSION="${TAG_VERSION#v}"
echo "TAG_VERSION=$TAG_VERSION" >> $GITHUB_ENV
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Update changelog
run: |
DATE=$(date -R)
sed -i "1i rustdesk-api-server (${VERSION}) stable; urgency=medium\n\n * Automatically generated release for version ${VERSION}.\n\n -- GitHub Actions <actions@github.com> ${DATE}\n" debian/changelog
- name: Download binaries
uses: actions/download-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: .
- name: Unzip binaries
run: |
mkdir -p ${{ matrix.job.platform }}
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
- name: Build package for ${{ matrix.job.platform }} arch
run: |
mv ${{ matrix.job.platform }}/release/apimain debian-build/${{ matrix.job.platform }}/bin/rustdesk-api
mv ${{ matrix.job.platform }}/release/resources/admin resources
chmod -v a+x debian-build/${{ matrix.job.platform }}/bin/*
mkdir -p data
cp -vr debian systemd conf data resources runtime debian-build/${{ matrix.job.platform }}/
cat debian/control.tpl | sed 's/{{ ARCH }}/${{ matrix.job.debian_platform }}/' > debian-build/${{ matrix.job.platform }}/debian/control
cd debian-build/${{ matrix.job.platform }}/
debuild -i -us -uc -b -a${{ matrix.job.debian_platform}}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.debian_platform }}
path: |
debian-build/*.deb
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: |
debian-build/rustdesk-api-server_*_${{ matrix.job.debian_platform }}.deb
docker:
name: Push Docker Image
needs: build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
job:
- { platform: "amd64", goos: "linux", docker_platform: "linux/amd64" }
- { platform: "arm64", goos: "linux", docker_platform: "linux/arm64" }
- { platform: "armv7l", goos: "linux", docker_platform: "linux/arm/v7" }
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if SKIP_DOCKER_HUB is false
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Log in to GitHub Container Registry
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
id: vars
run: |
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
else
echo "TAG=latest" >> $GITHUB_ENV # Default to 'latest' if not a tag
fi
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api
- name: Download binaries
uses: actions/download-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: ./
- name: Unzip binaries
run: |
mkdir -p ${{ matrix.job.platform }}
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
- name: Build and push Docker image to Docker Hub ${{ matrix.job.platform }}
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only run this step if SKIP_DOCKER_HUB is false
uses: docker/build-push-action@v5
with:
context: "."
file: ./Dockerfile
platforms: ${{ matrix.job.docker_platform }}
push: true
provenance: false
build-args: |
BUILDARCH=${{ matrix.job.platform }}
tags: |
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.LATEST_TAG }}-${{ matrix.job.platform }},
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build and push Docker Full S6 image to Docker Hub ${{ matrix.job.platform }}
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only run this step if SKIP_DOCKER_HUB is false
uses: docker/build-push-action@v5
with:
context: "."
file: ./Dockerfile_full_s6
platforms: ${{ matrix.job.docker_platform }}
push: true
provenance: false
build-args: |
BUILDARCH=${{ matrix.job.platform }}
tags: |
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-${{ matrix.job.platform }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build and push Docker image to GHCR ${{ matrix.job.platform }}
if: ${{ env.SKIP_GHCR == 'false' }} # Only run this step if SKIP_GHCR is false
uses: docker/build-push-action@v5
with:
context: "."
file: ./Dockerfile
platforms: ${{ matrix.job.docker_platform }}
push: true
provenance: false
build-args: |
BUILDARCH=${{ matrix.job.platform }}
tags: |
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.LATEST_TAG }}-${{ matrix.job.platform }},
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build and push Docker Full S6 image to GHCR ${{ matrix.job.platform }}
if: ${{ env.SKIP_GHCR == 'false' }} # Only run this step if SKIP_GHCR is false
uses: docker/build-push-action@v5
with:
context: "."
file: ./Dockerfile
platforms: ${{ matrix.job.docker_platform }}
push: true
provenance: false
build-args: |
BUILDARCH=${{ matrix.job.platform }}
tags: |
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-${{ matrix.job.platform }}
labels: ${{ steps.meta.outputs.labels }}
#
docker-manifest:
name: Push Docker Manifest
needs: docker
runs-on: ubuntu-latest
steps:
- name: Extract version from tag
id: vars
run: |
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
else
echo "TAG=latest" >> $GITHUB_ENV # Default to 'latest' if not a tag
fi
- name: Log in to Docker Hub
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if Docker Hub push is enabled
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Log in to GitHub Container Registry
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push manifest Docker Hub (:version)
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
push: true
- name: Create and push manifest GHCR (:version)
if: ${{ env.SKIP_GHCR == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
push: true
amend: true
- name: Create and push manifest Docker Hub (:latest)
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:latest
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:latest-amd64,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:latest-armv7l,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:latest-arm64
push: true
- name: Create and push manifest GHCR (:latest)
if: ${{ env.SKIP_GHCR == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:latest
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:latest-amd64,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:latest-armv7l,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:latest-arm64
push: true
amend: true
- name: Create and push Full S6 manifest Docker Hub (:version)
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:full-s6
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-amd64,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-armv7l,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-arm64
push: true
amend: true
- name: Create and push Full S6 manifest GHCR (:latest)
if: ${{ env.SKIP_GHCR == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:full-s6
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-amd64,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-armv7l,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-arm64
push: true
amend: true
+337
View File
@@ -0,0 +1,337 @@
name: Build Test
on:
workflow_dispatch:
inputs:
BASE_IMAGE_NAMESPACE:
description: 'Base image namespace (Default: Your Github username)'
required: false
default: ''
DOCKERHUB_IMAGE_NAMESPACE:
description: 'Docker Hub image namespace (Default: Your Github username)'
required: false
default: ''
GHCR_IMAGE_NAMESPACE:
description: 'GitHub Container Registry image namespace (Default: Your Github username)'
required: false
default: ''
SKIP_DOCKER_HUB:
description: 'Set to true to skip pushing to Docker Hub (default: false)'
required: false
default: 'false'
SKIP_GHCR:
description: 'Set to true to skip pushing to GHCR (default: false)'
required: false
default: 'false'
WEBCLIENT_SOURCE_LOCATION:
description: 'Web Client API Repository'
required: true
default: 'https://github.com/lejianwen/rustdesk-api-web'
env:
LATEST_TAG: latest
WEBCLIENT_SOURCE_LOCATION: ${{ github.event.inputs.WEBCLIENT_SOURCE_LOCATION || 'https://github.com/lejianwen/rustdesk-api-web' }}
BASE_IMAGE_NAMESPACE: ${{ github.event.inputs.BASE_IMAGE_NAMESPACE || github.actor }}
DOCKERHUB_IMAGE_NAMESPACE: ${{ github.event.inputs.DOCKERHUB_IMAGE_NAMESPACE || github.actor }}
GHCR_IMAGE_NAMESPACE: ${{ github.event.inputs.GHCR_IMAGE_NAMESPACE || github.actor }}
SKIP_DOCKER_HUB: ${{ github.event.inputs.SKIP_DOCKER_HUB || 'false' }}
SKIP_GHCR: ${{ github.event.inputs.SKIP_GHCR || 'false' }}
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
job:
- { platform: "amd64", goos: "linux", file_ext: "tar.gz" }
- { platform: "arm64", goos: "linux", file_ext: "tar.gz" }
- { platform: "armv7l", goos: "linux", file_ext: "tar.gz" }
- { platform: "amd64", goos: "windows", file_ext: "zip" }
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: lejianwen/rustdesk-api-web
path: rustdesk-api-web
ref: master
- name: Set up Go environment
uses: actions/setup-go@v4
with:
go-version: '1.23' # 选择 Go 版本
- name: Set up npm
uses: actions/setup-node@v2
with:
node-version: '20'
- name: build rustdesk-api-web
working-directory: rustdesk-api-web
run: |
npm install
npm run build
mkdir -p ../resources/admin/
cp -ar dist/* ../resources/admin/
- name: tidy
run: go mod tidy
- name: swag
run: |
go install github.com/swaggo/swag/cmd/swag@latest
swag init -g cmd/apimain.go --output docs/api --instanceName api --exclude http/controller/admin
swag init -g cmd/apimain.go --output docs/admin --instanceName admin --exclude http/controller/api
- name: Build for ${{ matrix.job.goos }}-${{ matrix.job.platform }}
run: |
mkdir release -p
cp -ar resources release/
cp -ar docs release/
cp -ar conf release/
mkdir -p release/data
mkdir -p release/runtime
if [ "${{ matrix.job.goos }}" = "windows" ]; then
sudo apt-get install gcc-mingw-w64-x86-64 zip -y
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain.exe ./cmd/apimain.go
echo @echo off > release/start.bat
echo cmd /c \"%~dp0apimain.exe\" >> release/start.bat
zip -r ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
else
if [ "${{ matrix.job.platform }}" = "arm64" ]; then
wget https://musl.ljw.red/aarch64-linux-musl-cross.tgz
tar -xf aarch64-linux-musl-cross.tgz
export PATH=$PATH:$PWD/aarch64-linux-musl-cross/bin
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=aarch64-linux-musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
elif [ "${{ matrix.job.platform }}" = "armv7l" ]; then
wget https://musl.ljw.red/armv7l-linux-musleabihf-cross.tgz
tar -xf armv7l-linux-musleabihf-cross.tgz
export PATH=$PATH:$PWD/armv7l-linux-musleabihf-cross/bin
GOOS=${{ matrix.job.goos }} GOARCH=arm GOARM=7 CC=armv7l-linux-musleabihf-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
else
sudo apt-get install musl musl-dev musl-tools -y
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
fi
tar -czf ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: |
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
tag_name: test
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
deb-package:
name: debian package - ${{ matrix.job.platform }}
needs: build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
job:
- { platform: "amd64", goos: "linux", debian_platform: "amd64", crossbuild_package: ""}
- { platform: "arm64", goos: "linux", debian_platform: "arm64", crossbuild_package: "crossbuild-essential-arm64" }
- { platform: "armv7l", goos: "linux", debian_platform: "armhf", crossbuild_package: "crossbuild-essential-armhf" }
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Create packaging env
run: |
sudo apt update
DEBIAN_FRONTEND=noninteractive sudo apt install -y devscripts build-essential debhelper pkg-config ${{ matrix.job.crossbuild_package }}
mkdir -p debian-build/${{ matrix.job.platform }}/bin
- name: Download binaries
uses: actions/download-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: .
- name: Unzip binaries
run: |
mkdir -p ${{ matrix.job.platform }}
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
- name: Build package for ${{ matrix.job.platform }} arch
run: |
mv ${{ matrix.job.platform }}/release/apimain debian-build/${{ matrix.job.platform }}/bin/rustdesk-api
chmod -v a+x debian-build/${{ matrix.job.platform }}/bin/*
mkdir -p data
cp -vr debian systemd conf data resources runtime debian-build/${{ matrix.job.platform }}/
cat debian/control.tpl | sed 's/{{ ARCH }}/${{ matrix.job.debian_platform }}/' > debian-build/${{ matrix.job.platform }}/debian/control
cd debian-build/${{ matrix.job.platform }}/
debuild -i -us -uc -b -a${{ matrix.job.debian_platform}}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.debian_platform }}
path: |
debian-build/*.deb
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: test
files: |
debian-build/rustdesk-api-server_*_${{ matrix.job.debian_platform }}.deb
docker:
name: Push Docker Image
needs: build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
job:
- { platform: "amd64", goos: "linux", docker_platform: "linux/amd64" }
- { platform: "arm64", goos: "linux", docker_platform: "linux/arm64" }
- { platform: "armv7l", goos: "linux", docker_platform: "linux/arm/v7" }
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if SKIP_DOCKER_HUB is false
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Log in to GitHub Container Registry
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
id: vars
run: |
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
else
echo "TAG=test" >> $GITHUB_ENV # Default to 'test' if not a tag
fi
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api
- name: Download binaries
uses: actions/download-artifact@v4
with:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: ./
- name: Unzip binaries
run: |
mkdir -p ${{ matrix.job.platform }}
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
- name: Build and push Docker image to Docker Hub ${{ matrix.job.platform }}
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only run this step if SKIP_DOCKER_HUB is false
uses: docker/build-push-action@v5
with:
context: "."
file: ./Dockerfile
platforms: ${{ matrix.job.docker_platform }}
push: true
provenance: false
build-args: |
BUILDARCH=${{ matrix.job.platform }}
tags: |
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build and push Docker image to GHCR ${{ matrix.job.platform }}
if: ${{ env.SKIP_GHCR == 'false' }} # Only run this step if SKIP_GHCR is false
uses: docker/build-push-action@v5
with:
context: "."
file: ./Dockerfile
platforms: ${{ matrix.job.docker_platform }}
push: true
provenance: false
build-args: |
BUILDARCH=${{ matrix.job.platform }}
tags: |
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
labels: ${{ steps.meta.outputs.labels }}
#
docker-manifest:
name: Push Docker Manifest
needs: docker
runs-on: ubuntu-latest
steps:
- name: Extract version from tag
id: vars
run: |
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
else
echo "TAG=test" >> $GITHUB_ENV # Default to 'test' if not a tag
fi
- name: Log in to Docker Hub
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if Docker Hub push is enabled
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Log in to GitHub Container Registry
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push manifest Docker Hub (:version)
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
push: true
- name: Create and push manifest GHCR (:version)
if: ${{ env.SKIP_GHCR == 'false' }}
uses: Noelware/docker-manifest-action@v0.2.3
with:
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
push: true
amend: true
+174 -184
View File
@@ -1,9 +1,8 @@
# RustDesk API
[中文文档](README_EN.md)
[English Doc](README_EN.md)
This project implements the RustDesk API using Go, and includes both a web UI and web client. RustDesk is a remote
desktop software that provides self-hosted solutions.
本项目使用 Go 实现了 RustDesk API,并包含了 Web Admin 和 Web 客户端。RustDesk 是一个远程桌面软件,提供了自托管的解决方案。
<div align=center>
<img src="https://img.shields.io/badge/golang-1.22-blue"/>
@@ -14,237 +13,232 @@ desktop software that provides self-hosted solutions.
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/build.yml/badge.svg"/>
</div>
## Better used with [lejianwen/rustdesk-server].
> [lejianwen/rustdesk-server] is a fork of the official RustDesk Server repository.
> 1. Solves the API connection timeout issue.
> 2. Can enforce login before initiating a connection.
> 3. Supports client websocket.
# 特性
# Features
- PC API
- Personal API
- Login
- Address Book
- Groups
- Authorized login,
- supports `GitHub`, `Google` and `OIDC` login,
- supports `web admin` authorized login,
- supports LDAP(test AD and openladp) if API Server config
- PC端API
- 个人版API
- 登录
- 地址簿
- 群组
- 授权登录
- 支持`github`, `google``OIDC` 登录,
- 支持`web后台`授权登录
- 支持`LDAP`(AD和OpenLDAP已测试), 如果API Server配置了LDAP
- i18n
- Web Admin
- User Management
- Device Management
- Address Book Management
- Tag Management
- Group Management
- OAuth Management
- LDAP Config by config file or ENV
- Login Logs
- Connection Logs
- File Transfer Logs
- Quick access to web client
- 用户管理
- 设备管理
- 地址簿管理
- 标签管理
- 群组管理
- Oauth 管理
- 配置LDAP, 配置文件或者环境变量
- 登录日志
- 链接日志
- 文件传输日志
- 快速使用web client
- i18n
- Share to guest by web client
- Server control (some simple official commands [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
- 通过 web client 分享给游客
- server控制(一些官方的简单的指令 [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
- Web Client
- Automatically obtain API server
- Automatically obtain ID server and KEY
- Automatically obtain address book
- Visitors are remotely to the device via a temporary sharing link
- 自动获取API server
- 自动获取ID服务器和KEY
- 自动获取地址簿
- 游客通过临时分享链接直接远程到设备
- v2 Preview
- CLI
- Reset admin password
- 重置管理员密码
## Overview
## 功能
### API Service
Basic implementation of the PC client's primary interfaces.Supports the Personal version api, which can be enabled by configuring the `rustdesk.personal` file or the `RUSTDESK_API_RUSTDESK_PERSONAL` environment variable.
### API 服务
基本实现了PC端基础的接口。支持Personal版本接口,可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
<table>
<tr>
<td width="50%" align="center" colspan="2"><b>Login</b></td>
<td width="50%" align="center" colspan="2"><b>登录</b></td>
</tr>
<tr>
<td width="50%" align="center" colspan="2"><img src="docs/en_img/pc_login.png"></td>
<td width="50%" align="center" colspan="2"><img src="docs/pc_login.png"></td>
</tr>
<tr>
<td width="50%" align="center"><b>Address Book</b></td>
<td width="50%" align="center"><b>Groups</b></td>
<td width="50%" align="center"><b>地址簿</b></td>
<td width="50%" align="center"><b>群组</b></td>
</tr>
<tr>
<td width="50%" align="center"><img src="docs/en_img/pc_ab.png"></td>
<td width="50%" align="center"><img src="docs/en_img/pc_gr.png"></td>
<td width="50%" align="center"><img src="docs/pc_ab.png"></td>
<td width="50%" align="center"><img src="docs/pc_gr.png"></td>
</tr>
</table>
### Web Admin
### Web Admin:
* The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and
displaying data.Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
* 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
* Admin panel URL: `http://<your server[:port]>/_admin/`
* For the initial installation, the admin username is `admin`, and the password will be printed in the console. You can change the password via the [command line](#CLI).
* 后台访问地址是`http://<your server>[:port]/_admin/`
* 初次安装管理员为用户名为`admin`,密码将在控制台打印,可以通过[命令行](#CLI)更改密码
![img.png](./docs/init_admin_pwd.png)
1. 管理员界面
![web_admin](docs/web_admin.png)
2. 普通用户界面
![web_user](docs/web_admin_user.png)
1. Admin interface:
![web_admin](docs/en_img/web_admin.png)
2. Regular user interface:
![web_user](docs/en_img/web_admin_user.png)
3. 每个用户可以多个地址簿,也可以将地址簿共享给其他用户
4. 分组可以自定义,方便管理,暂时支持两种类型: `共享组``普通组`
5. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
6. Oauth,支持了`Github`, `Google` 以及 `OIDC`, 需要创建一个`OAuth App`,然后配置到后台
- 对于`Google``Github`, `Issuer``Scopes`不需要填写.
- 对于`OIDC`, `Issuer`是必须的。`Scopes`是可选的,默认为 `openid,profile,email`. 确保可以获取 `sub`,`email``preferred_username`
- `github oauth app``Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App`
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
- `Authorization callback URL`填写`http://<your server[:port]>/api/oauth/callback`
,比如`http://127.0.0.1:21114/api/oauth/callback`
7. 登录日志
8. 链接日志
9. 文件传输日志
10. server控制
3. Each user can have multiple address books, which can also be shared with other users.
4. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
5. You can directly launch the client or open the web client for convenience; you can also share it with guests, who can remotely access the device via the web client.
6. OAuth support: Currently, `GitHub`, `Google` and `OIDC` are supported. You need to create an `OAuth App` and configure it in
the admin panel.
- For `Google` and `Github`, you don't need to fill the `Issuer` and `Scpoes`
- For `OIDC`, you must set the `Issuer`. And `Scopes` is optional which default is `openid,email,profile`, please make sure this `Oauth App` can access `sub`, `email` and `preferred_username`
- Create a `GitHub OAuth App`
at `Settings` -> `Developer settings` -> `OAuth Apps` -> `New OAuth App` [here](https://github.com/settings/developers).
- Set the `Authorization callback URL` to `http://<your server[:port]>/api/oidc/callback`,
e.g., `http://127.0.0.1:21114/api/oidc/callback`.
- `简易模式`,已经界面化了一些简单的指令,可以直接在后台执行
![rustdesk_command_simple](./docs/rustdesk_command_simple.png)
7. Login logs
8. Connection logs
9. File transfer logs
10. Server control
- `Simple mode`, some simple commands have been GUI-ized and can be executed directly in the backend
![rustdesk_command_simple](./docs/en_img/rustdesk_command_simple.png)
- `高级模式`,直接在后台执行指令
* 可以官方指令
* 可以添加自定义指令
* 可以执行自定义指令
- `Advanced mode`, commands can be executed directly in the backend
* Official commands can be used
* Custom commands can be added
* Custom commands can be executed
11. **LDAP Support**, When you setup the LDAP(test for OpenLDAP and AD), you can login with the LDAP's user. https://github.com/lejianwen/rustdesk-api/issues/114 , if LDAP fail fallback local user
11. **LDAP 支持**, 当在API Server上设置了LDAP(已测试AD和LDAP),可以通过LDAP中的用户信息进行登录 https://github.com/lejianwen/rustdesk-api/issues/114 ,如果LDAP验证失败,返回本地用户
### Web Client:
1. If you're already logged into the admin panel, the web client will log in automatically.
2. If you're not logged in, simply click the login button in the top right corner, and the API server will be
pre-configured.
3. After logging in, the ID server and key will be automatically synced.
4. The address book will also be automatically saved to the web client for convenient use.
1. 如果已经登录了后台,web client将自动直接登录
2. 如果没登录后台,点击右上角登录即可,api server已经自动配置好了
3. 登录后,会自动同步ID服务器和KEY
4. 登录后,会将地址簿自动保存到web client中,方便使用
5. 现已支持`v2 Preview`,访问路径是`/webclient2`
![webclientv2](./docs/webclientv2.png)
6. `v2 preview` 部署,参考[WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
### Automated Documentation : API documentation is generated using Swag, making it easier for developers to understand and use the API.
1. Admin panel docs: `<your server[:port]>/admin/swagger/index.html`
2. PC client docs: `<your server[:port]>/swagger/index.html`
### 自动化文档: 使用 Swag 生成 API 文档,方便开发者理解和使用 API。
1. 后台文档 `<youer server[:port]>/admin/swagger/index.html`
2. PC端文档 `<youer server[:port]>/swagger/index.html`
![api_swag](docs/api_swag.png)
### CLI
```bash
# help
# 查看帮助
./apimain -h
```
#### Reset admin password
#### 重置管理员密码
```bash
./apimain reset-admin-pwd <pwd>
```
## Installation and Setup
## 安装与运行
### Configuration
### 相关配置
* [Config File](./conf/config.yaml)
* Modify the configuration in `conf/config.yaml`.
* If `gorm.type` is set to `sqlite`, MySQL-related configurations are not required.
* Language support: `en` and `zh-CN` are supported. The default is `zh-CN`.
* [配置文件](./conf/config.yaml)
* 参考`conf/config.yaml`配置文件,修改相关配置。
* 如果`gorm.type``sqlite`,则不需要配置mysql相关配置。
* 语言如果不设置默认为`zh-CN`
### 环境变量
环境变量和配置文件`conf/config.yaml`中的配置一一对应,变量名前缀是`RUSTDESK_API`
下面表格并未全部列出,可以参考`conf/config.yaml`中的配置。
| 变量名 | 说明 | 示例 |
|--------------------------------------------------------|--------------------------------------------------------------------------------|------------------------------|
| TZ | 时区 | Asia/Shanghai |
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` |
| RUSTDESK_API_APP_SHOW_SWAGGER | 是否可见swagger文档;`1`显示,`0`不显示,默认`0`不显示 | `1` |
| RUSTDESK_API_APP_TOKEN_EXPIRE | token有效时长 | `168h` |
| RUSTDESK_API_APP_DISABLE_PWD_LOGIN | 是否禁用密码登录; `true`, `false` 默认`false` | `false` |
| RUSTDESK_API_APP_REGISTER_STATUS | 注册用户默认状态; 1 启用,2 禁用, 默认 1 | `1` |
| RUSTDESK_API_APP_CAPTCHA_THRESHOLD | 验证码触发次数; -1 不启用, 0 一直启用, >0 登录错误次数后启用 ;默认 `3` | `3` |
| RUSTDESK_API_APP_BAN_THRESHOLD | 封禁IP触发次数; 0 不启用, >0 登录错误次数后封禁IP; 默认 `0` | `0` |
| -----ADMIN配置----- | ---------- | ---------- |
| RUSTDESK_API_ADMIN_TITLE | 后台标题 | `RustDesk Api Admin` |
| RUSTDESK_API_ADMIN_HELLO | 后台欢迎语,可以使用`html` | |
| RUSTDESK_API_ADMIN_HELLO_FILE | 后台欢迎语文件,如果内容多,使用文件更方便。<br>会覆盖`RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
| -----GIN配置----- | ---------- | ---------- |
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
| -----GORM配置----- | ---------- | --------------------------- |
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API, 1:启用,0:不启用; 默认启用 | 1 |
| -----MYSQL配置----- | ---------- | ---------- |
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
| -----RUSTDESK配置----- | ---------- | ---------- |
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` |
| RUSTDESK_API_RUSTDESK_WEBCLIENT<br/>_MAGIC_QUERYONLINE | Web client v2 中是否启用新的在线状态查询方法; `1`:启用,`0`:不启用,默认不启用 | `0` |
| RUSTDESK_API_RUSTDESK_WS_HOST | 自定义Websocket Host | `wss://192.168.1.123:1234` |
| ----PROXY配置----- | ---------- | ---------- |
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
| ----JWT配置---- | -------- | -------- |
| RUSTDESK_API_JWT_KEY | 自定义JWT KEY,为空则不启用JWT<br/>如果没使用`lejianwen/rustdesk-server`中的`MUST_LOGIN`,建议设置为空 | |
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT有效时间 | `168h` |
### Environment Variables
The environment variables correspond one-to-one with the configurations in the `conf/config.yaml` file. The prefix for variable names is `RUSTDESK_API`.
The table below does not list all configurations. Please refer to the configurations in `conf/config.yaml`.
### 运行
| Variable Name | Description | Example |
|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|
| TZ | timezone | Asia/Shanghai |
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
| RUSTDESK_API_APP_TOKEN_EXPIRE | token expire duration | `168h` |
| RUSTDESK_API_APP_DISABLE_PWD_LOGIN | disable password login | `false` |
| RUSTDESK_API_APP_REGISTER_STATUS | register user default status ; 1 enabled , 2 disabled ; default 1 | `1` |
| RUSTDESK_API_APP_CAPTCHA_THRESHOLD | captcha threshold; -1 disabled, 0 always enable, >0 threshold ;default `3` | `3` |
| RUSTDESK_API_APP_BAN_THRESHOLD | ban ip threshold; 0 disabled, >0 threshold ; default `0` | `0` |
| ----- ADMIN Configuration----- | ---------- | ---------- |
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
| RUSTDESK_API_MYSQL_TLS | Whether to enable TLS, optional values: `true`, `false`, `skip-verify`, `custom` | `false` |
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
| RUSTDESK_API_RUSTDESK<br/>_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
| RUSTDESK_API_RUSTDESK_WS_HOST | Custom Websocket Host | `wss://192.168.1.123:1234` |
| ---- PROXY ----- | --------------- | ---------- |
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
| ----JWT---- | -------- | -------- |
| RUSTDESK_API_JWT_KEY | Custom JWT KEY, if empty JWT is not enabled.<br/>If `MUST_LOGIN` from `lejianwen/rustdesk-server` is not used, it is recommended to leave it empty. | |
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT expire duration | `168h` |
#### docker运行
### Installation Steps
#### Running via Docker
1. Run directly with Docker. Configuration can be modified by mounting the config file `/app/conf/config.yaml`, or by
using environment variables to override settings.
1. 直接docker运行,配置可以通过挂载配置文件`/app/conf/config.yaml`来修改,或者通过环境变量覆盖配置文件中的配置
```bash
docker run -d --name rustdesk-api -p 21114:21114 \
-v /data/rustdesk/api:/app/data \
-e RUSTDESK_API_LANG=en \
-e TZ=Asia/Shanghai \
-e RUSTDESK_API_LANG=zh-CN \
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
-e RUSTDESK_API_RUSTDESK_KEY=abc123456 \
-e RUSTDESK_API_RUSTDESK_KEY=<key> \
lejianwen/rustdesk-api
```
2. Using `docker-compose`,look [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
2. 使用`docker compose`,参考[WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
#### Running from Release
#### 下载release直接运行
Download the release from [release](https://github.com/lejianwen/rustdesk-api/releases).
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
#### Source Installation
#### 源码安装
1. Clone the repository:
1. 克隆仓库
```bash
git clone https://github.com/lejianwen/rustdesk-api.git
cd rustdesk-api
```
2. Install dependencies:
2. 安装依赖
```bash
go mod tidy
# Install Swag if you need to generate documentation; otherwise, you can skip this step
#安装swag,如果不需要生成文档,可以不安装
go install github.com/swaggo/swag/cmd/swag@latest
```
3. Build the admin front-end (the front-end code is
in [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)):
3. 编译后台前端,前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)中
```bash
cd resources
mkdir -p admin
@@ -254,33 +248,29 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
npm run build
cp -ar dist/* ../admin/
```
4. Run:
4. 运行
```bash
# Run directly
#直接运行
go run cmd/apimain.go
# Or generate and run the API using generate_api.go
#或者使用generate_api.go生成api并运行
go generate generate_api.go
```
> **Note:** When using `go run` or the compiled binary, the `conf` and `resources`
> directories must exist relative to the current working directory. If you run
> the program from another location, specify absolute paths with `-c` and the
> `RUSTDESK_API_GIN_RESOURCES_PATH` environment variable. Example:
> 注意:使用 `go run` 或编译后的二进制时,当前目录下必须存在 `conf` `resources`
> 目录。如果在其他目录运行,可通过 `-c` 和环境变量
> `RUSTDESK_API_GIN_RESOURCES_PATH` 指定绝对路径,例如:
> ```bash
> RUSTDESK_API_GIN_RESOURCES_PATH=/opt/rustdesk-api/resources ./apimain -c /opt/rustdesk-api/conf/config.yaml
> ```
5. 编译,如果想自己编译,先cd到项目根目录,然后windows下直接运行`build.bat`,linux下运行`build.sh`,编译后会在`release`
目录下生成对应的可执行文件。直接运行编译后的可执行文件即可。
5. To compile, change to the project root directory. For Windows, run `build.bat`, and for Linux, run `build.sh`. After
compiling, the corresponding executables will be generated in the `release` directory. Run the compiled executables
directly.
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
change the password promptly.
#### Running with my forked server-s6 image
#### 使用`lejianwen/server-s6`镜像运行
- Connection timeout issue resolved
- Can enforce login before initiating a connection
- 已解决链接超时问题
- 可以强制登录后才能发起链接
- github https://github.com/lejianwen/rustdesk-server
```yaml
@@ -310,28 +300,28 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
- RUSTDESK_API_JWT_KEY=xxxxxx # jwt key
volumes:
- /data/rustdesk/server:/data
- /data/rustdesk/api:/app/data # mount the database
- /data/rustdesk/api:/app/data #将数据库挂载
networks:
- rustdesk-net
restart: unless-stopped
```
## Others
## 其他
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
- [Connection Timeout](https://github.com/lejianwen/rustdesk-api/issues/92)
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
- [Web client source](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
- [链接超时问题](https://github.com/lejianwen/rustdesk-api/issues/92)
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
- [webclient来源](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
## Acknowledgements
Thanks to everyone who contributed!
## 鸣谢
感谢所有做过贡献的人!
<a href="https://github.com/lejianwen/rustdesk-api/graphs/contributors">
<img src="https://contrib.rocks/image?repo=lejianwen/rustdesk-api" />
</a>
## Thanks for your support! If you find this project useful, please give it a ⭐️. Thank you!
[lejianwen/rustdesk-server]: https://github.com/lejianwen/rustdesk-server
## 感谢你的支持!如果这个项目对你有帮助,请点个⭐️鼓励一下,谢谢!
+175 -182
View File
@@ -1,9 +1,7 @@
# RustDesk API
[English Doc](README.md)
本项目使用 Go 实现了 RustDesk 的 API,并包含了 Web Admin 和 Web 客户端。
This project implements the RustDesk API using Go, and includes both a web UI and web client. RustDesk is a remote
desktop software that provides self-hosted solutions.
<div align=center>
<img src="https://img.shields.io/badge/golang-1.22-blue"/>
@@ -14,237 +12,233 @@
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/build.yml/badge.svg"/>
</div>
## 搭配[lejianwen/rustdesk-server]使用更佳。
> [lejianwen/rustdesk-server]fork自RustDesk Server官方仓库
> 1. 解决了使用API链接超时问题
> 2. 可以强制登录后才能发起链接
> 3. 支持客户端websocket
# Features
# 特性
- PC端API
- 个人版API
- 登录
- 地址簿
- 群组
- 授权登录
- 支持`github`, `google``OIDC` 登录,
- 支持`web后台`授权登录
- 支持`LDAP`(AD和OpenLDAP已测试), 如果API Server配置了LDAP
- PC API
- Personal API
- Login
- Address Book
- Groups
- Authorized login,
- supports `GitHub`, `Google` and `OIDC` login,
- supports `web admin` authorized login,
- supports LDAP(test AD and openladp) if API Server config
- i18n
- Web Admin
- 用户管理
- 设备管理
- 地址簿管理
- 标签管理
- 群组管理
- Oauth 管理
- 配置LDAP, 配置文件或者环境变量
- 登录日志
- 链接日志
- 文件传输日志
- 快速使用web client
- User Management
- Device Management
- Address Book Management
- Tag Management
- Group Management
- OAuth Management
- LDAP Config by config file or ENV
- Login Logs
- Connection Logs
- File Transfer Logs
- Quick access to web client
- i18n
- 通过 web client 分享给游客
- server控制(一些官方的简单的指令 [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
- Share to guest by web client
- Server control (some simple official commands [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
- Web Client
- 自动获取API server
- 自动获取ID服务器和KEY
- 自动获取地址簿
- 游客通过临时分享链接直接远程到设备
- Automatically obtain API server
- Automatically obtain ID server and KEY
- Automatically obtain address book
- Visitors are remotely to the device via a temporary sharing link
- CLI
- 重置管理员密码
- Reset admin password
## 功能
## Overview
### API 服务
基本实现了PC端基础的接口。支持Personal版本接口,可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
### API Service
Basic implementation of the PC client's primary interfaces.Supports the Personal version api, which can be enabled by configuring the `rustdesk.personal` file or the `RUSTDESK_API_RUSTDESK_PERSONAL` environment variable.
<table>
<tr>
<td width="50%" align="center" colspan="2"><b>登录</b></td>
<td width="50%" align="center" colspan="2"><b>Login</b></td>
</tr>
<tr>
<td width="50%" align="center" colspan="2"><img src="docs/pc_login.png"></td>
<td width="50%" align="center" colspan="2"><img src="docs/en_img/pc_login.png"></td>
</tr>
<tr>
<td width="50%" align="center"><b>地址簿</b></td>
<td width="50%" align="center"><b>群组</b></td>
<td width="50%" align="center"><b>Address Book</b></td>
<td width="50%" align="center"><b>Groups</b></td>
</tr>
<tr>
<td width="50%" align="center"><img src="docs/pc_ab.png"></td>
<td width="50%" align="center"><img src="docs/pc_gr.png"></td>
<td width="50%" align="center"><img src="docs/en_img/pc_ab.png"></td>
<td width="50%" align="center"><img src="docs/en_img/pc_gr.png"></td>
</tr>
</table>
### Web Admin:
### Web Admin
* 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
* The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and
displaying data.Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
* 后台访问地址是`http://<your server>[:port]/_admin/`
* 初次安装管理员为用户名为`admin`,密码将在控制台打印,可以通过[命令行](#CLI)更改密码
* Admin panel URL: `http://<your server[:port]>/_admin/`
* For the initial installation, the admin username is `admin`, and the password will be printed in the console. You can change the password via the [command line](#CLI).
![img.png](./docs/init_admin_pwd.png)
1. 管理员界面
![web_admin](docs/web_admin.png)
2. 普通用户界面
![web_user](docs/web_admin_user.png)
3. 每个用户可以多个地址簿,也可以将地址簿共享给其他用户
4. 分组可以自定义,方便管理,暂时支持两种类型: `共享组``普通组`
5. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
6. Oauth,支持了`Github`, `Google` 以及 `OIDC`, 需要创建一个`OAuth App`,然后配置到后台
- 对于`Google``Github`, `Issuer``Scopes`不需要填写.
- 对于`OIDC`, `Issuer`是必须的。`Scopes`是可选的,默认为 `openid,profile,email`. 确保可以获取 `sub`,`email``preferred_username`
- `github oauth app``Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App`
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
- `Authorization callback URL`填写`http://<your server[:port]>/api/oidc/callback`
,比如`http://127.0.0.1:21114/api/oidc/callback`
7. 登录日志
8. 链接日志
9. 文件传输日志
10. server控制
1. Admin interface:
![web_admin](docs/en_img/web_admin.png)
2. Regular user interface:
![web_user](docs/en_img/web_admin_user.png)
- `简易模式`,已经界面化了一些简单的指令,可以直接在后台执行
![rustdesk_command_simple](./docs/rustdesk_command_simple.png)
3. Each user can have multiple address books, which can also be shared with other users.
4. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
5. You can directly launch the client or open the web client for convenience; you can also share it with guests, who can remotely access the device via the web client.
6. OAuth support: Currently, `GitHub`, `Google` and `OIDC` are supported. You need to create an `OAuth App` and configure it in
the admin panel.
- For `Google` and `Github`, you don't need to fill the `Issuer` and `Scpoes`
- For `OIDC`, you must set the `Issuer`. And `Scopes` is optional which default is `openid,email,profile`, please make sure this `Oauth App` can access `sub`, `email` and `preferred_username`
- Create a `GitHub OAuth App`
at `Settings` -> `Developer settings` -> `OAuth Apps` -> `New OAuth App` [here](https://github.com/settings/developers).
- Set the `Authorization callback URL` to `http://<your server[:port]>/api/oauth/callback`,
e.g., `http://127.0.0.1:21114/api/oauth/callback`.
- `高级模式`,直接在后台执行指令
* 可以官方指令
* 可以添加自定义指令
* 可以执行自定义指令
7. Login logs
8. Connection logs
9. File transfer logs
10. Server control
- `Simple mode`, some simple commands have been GUI-ized and can be executed directly in the backend
![rustdesk_command_simple](./docs/en_img/rustdesk_command_simple.png)
- `Advanced mode`, commands can be executed directly in the backend
* Official commands can be used
* Custom commands can be added
* Custom commands can be executed
11. **LDAP 支持**, 当在API Server上设置了LDAP(已测试AD和LDAP),可以通过LDAP中的用户信息进行登录 https://github.com/lejianwen/rustdesk-api/issues/114 ,如果LDAP验证失败,返回本地用户
11. **LDAP Support**, When you setup the LDAP(test for OpenLDAP and AD), you can login with the LDAP's user. https://github.com/lejianwen/rustdesk-api/issues/114 , if LDAP fail fallback local user
### Web Client:
1. 如果已经登录了后台,web client将自动直接登录
2. 如果没登录后台,点击右上角登录即可,api server已经自动配置好了
3. 登录后,会自动同步ID服务器和KEY
4. 登录后,会将地址簿自动保存到web client中,方便使用
1. If you're already logged into the admin panel, the web client will log in automatically.
2. If you're not logged in, simply click the login button in the top right corner, and the API server will be
pre-configured.
3. After logging in, the ID server and key will be automatically synced.
4. The address book will also be automatically saved to the web client for convenient use.
5. Now supports `v2 Preview`, accessible at `/webclient2`
![webclientv2](./docs/webclientv2.png)
6. `v2 preview` deployment, [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
### Automated Documentation : API documentation is generated using Swag, making it easier for developers to understand and use the API.
### 自动化文档: 使用 Swag 生成 API 文档,方便开发者理解和使用 API。
1. 后台文档 `<youer server[:port]>/admin/swagger/index.html`
2. PC端文档 `<youer server[:port]>/swagger/index.html`
1. Admin panel docs: `<your server[:port]>/admin/swagger/index.html`
2. PC client docs: `<your server[:port]>/swagger/index.html`
![api_swag](docs/api_swag.png)
### CLI
```bash
# 查看帮助
# help
./apimain -h
```
#### 重置管理员密码
#### Reset admin password
```bash
./apimain reset-admin-pwd <pwd>
```
## 安装与运行
## Installation and Setup
### 相关配置
### Configuration
* [配置文件](./conf/config.yaml)
* 参考`conf/config.yaml`配置文件,修改相关配置。
* 如果`gorm.type``sqlite`,则不需要配置mysql相关配置。
* 语言如果不设置默认为`zh-CN`
### 环境变量
环境变量和配置文件`conf/config.yaml`中的配置一一对应,变量名前缀是`RUSTDESK_API`
下面表格并未全部列出,可以参考`conf/config.yaml`中的配置。
| 变量名 | 说明 | 示例 |
|--------------------------------------------------------|--------------------------------------------------------------------------------|------------------------------|
| TZ | 时区 | Asia/Shanghai |
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` |
| RUSTDESK_API_APP_SHOW_SWAGGER | 是否可见swagger文档;`1`显示,`0`不显示,默认`0`不显示 | `1` |
| RUSTDESK_API_APP_TOKEN_EXPIRE | token有效时长 | `168h` |
| RUSTDESK_API_APP_DISABLE_PWD_LOGIN | 是否禁用密码登录; `true`, `false` 默认`false` | `false` |
| RUSTDESK_API_APP_REGISTER_STATUS | 注册用户默认状态; 1 启用,2 禁用, 默认 1 | `1` |
| RUSTDESK_API_APP_CAPTCHA_THRESHOLD | 验证码触发次数; -1 不启用, 0 一直启用, >0 登录错误次数后启用 ;默认 `3` | `3` |
| RUSTDESK_API_APP_BAN_THRESHOLD | 封禁IP触发次数; 0 不启用, >0 登录错误次数后封禁IP; 默认 `0` | `0` |
| -----ADMIN配置----- | ---------- | ---------- |
| RUSTDESK_API_ADMIN_TITLE | 后台标题 | `RustDesk Api Admin` |
| RUSTDESK_API_ADMIN_HELLO | 后台欢迎语,可以使用`html` | |
| RUSTDESK_API_ADMIN_HELLO_FILE | 后台欢迎语文件,如果内容多,使用文件更方便。<br>会覆盖`RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
| -----GIN配置----- | ---------- | ---------- |
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
| -----GORM配置----- | ---------- | --------------------------- |
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API, 1:启用,0:不启用; 默认启用 | 1 |
| -----MYSQL配置----- | ---------- | ---------- |
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
| RUSTDESK_API_MYSQL_TLS | 是否启用TLS, 可选值: `true`, `false`, `skip-verify`, `custom` | `false` |
| -----RUSTDESK配置----- | ---------- | ---------- |
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` |
| RUSTDESK_API_RUSTDESK_WEBCLIENT<br/>_MAGIC_QUERYONLINE | Web client v2 中是否启用新的在线状态查询方法; `1`:启用,`0`:不启用,默认不启用 | `0` |
| RUSTDESK_API_RUSTDESK_WS_HOST | 自定义Websocket Host | `wss://192.168.1.123:1234` |
| ----PROXY配置----- | ---------- | ---------- |
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
| ----JWT配置---- | -------- | -------- |
| RUSTDESK_API_JWT_KEY | 自定义JWT KEY,为空则不启用JWT<br/>如果没使用`lejianwen/rustdesk-server`中的`MUST_LOGIN`,建议设置为空 | |
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT有效时间 | `168h` |
* [Config File](./conf/config.yaml)
* Modify the configuration in `conf/config.yaml`.
* If `gorm.type` is set to `sqlite`, MySQL-related configurations are not required.
* Language support: `en` and `zh-CN` are supported. The default is `zh-CN`.
### 运行
### Environment Variables
The environment variables correspond one-to-one with the configurations in the `conf/config.yaml` file. The prefix for variable names is `RUSTDESK_API`.
The table below does not list all configurations. Please refer to the configurations in `conf/config.yaml`.
#### docker运行
| Variable Name | Description | Example |
|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|
| TZ | timezone | Asia/Shanghai |
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
| RUSTDESK_API_APP_TOKEN_EXPIRE | token expire duration | `168h` |
| RUSTDESK_API_APP_DISABLE_PWD_LOGIN | disable password login | `false` |
| RUSTDESK_API_APP_REGISTER_STATUS | register user default status ; 1 enabled , 2 disabled ; default 1 | `1` |
| RUSTDESK_API_APP_CAPTCHA_THRESHOLD | captcha threshold; -1 disabled, 0 always enable, >0 threshold ;default `3` | `3` |
| RUSTDESK_API_APP_BAN_THRESHOLD | ban ip threshold; 0 disabled, >0 threshold ; default `0`
| `0` |
| ----- ADMIN Configuration----- | ---------- | ---------- |
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
| RUSTDESK_API_RUSTDESK<br/>_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
| RUSTDESK_API_RUSTDESK_WS_HOST | Custom Websocket Host | `wss://192.168.1.123:1234` |
| ---- PROXY ----- | --------------- | ---------- |
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
| ----JWT---- | -------- | -------- |
| RUSTDESK_API_JWT_KEY | Custom JWT KEY, if empty JWT is not enabled.<br/>If `MUST_LOGIN` from `lejianwen/rustdesk-server` is not used, it is recommended to leave it empty. | |
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT expire duration | `168h` |
1. 直接docker运行,配置可以通过挂载配置文件`/app/conf/config.yaml`来修改,或者通过环境变量覆盖配置文件中的配置
### Installation Steps
#### Running via Docker
1. Run directly with Docker. Configuration can be modified by mounting the config file `/app/conf/config.yaml`, or by
using environment variables to override settings.
```bash
docker run -d --name rustdesk-api -p 21114:21114 \
-v /data/rustdesk/api:/app/data \
-e TZ=Asia/Shanghai \
-e RUSTDESK_API_LANG=zh-CN \
-e RUSTDESK_API_LANG=en \
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
-e RUSTDESK_API_RUSTDESK_KEY=<key> \
-e RUSTDESK_API_RUSTDESK_KEY=abc123456 \
lejianwen/rustdesk-api
```
2. 使用`docker compose`,参考[WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
2. Using `docker-compose`,look [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
#### 下载release直接运行
#### Running from Release
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
Download the release from [release](https://github.com/lejianwen/rustdesk-api/releases).
#### 源码安装
#### Source Installation
1. 克隆仓库
1. Clone the repository:
```bash
git clone https://github.com/lejianwen/rustdesk-api.git
cd rustdesk-api
```
2. 安装依赖
2. Install dependencies:
```bash
go mod tidy
#安装swag,如果不需要生成文档,可以不安装
# Install Swag if you need to generate documentation; otherwise, you can skip this step
go install github.com/swaggo/swag/cmd/swag@latest
```
3. 编译后台前端,前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)中
3. Build the admin front-end (the front-end code is
in [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)):
```bash
cd resources
mkdir -p admin
@@ -254,29 +248,33 @@
npm run build
cp -ar dist/* ../admin/
```
4. 运行
4. Run:
```bash
#直接运行
# Run directly
go run cmd/apimain.go
#或者使用generate_api.go生成api并运行
# Or generate and run the API using generate_api.go
go generate generate_api.go
```
> 注意:使用 `go run` 或编译后的二进制时,当前目录下必须存在 `conf` `resources`
> 目录。如果在其他目录运行,可通过 `-c` 和环境变量
> `RUSTDESK_API_GIN_RESOURCES_PATH` 指定绝对路径,例如:
> **Note:** When using `go run` or the compiled binary, the `conf` and `resources`
> directories must exist relative to the current working directory. If you run
> the program from another location, specify absolute paths with `-c` and the
> `RUSTDESK_API_GIN_RESOURCES_PATH` environment variable. Example:
> ```bash
> RUSTDESK_API_GIN_RESOURCES_PATH=/opt/rustdesk-api/resources ./apimain -c /opt/rustdesk-api/conf/config.yaml
> ```
5. 编译,如果想自己编译,先cd到项目根目录,然后windows下直接运行`build.bat`,linux下运行`build.sh`,编译后会在`release`
目录下生成对应的可执行文件。直接运行编译后的可执行文件即可。
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
5. To compile, change to the project root directory. For Windows, run `build.bat`, and for Linux, run `build.sh`. After
compiling, the corresponding executables will be generated in the `release` directory. Run the compiled executables
directly.
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
change the password promptly.
#### 使用`lejianwen/server-s6`镜像运行
#### Running with my forked server-s6 image
- 已解决链接超时问题
- 可以强制登录后才能发起链接
- Connection timeout issue resolved
- Can enforce login before initiating a connection
- github https://github.com/lejianwen/rustdesk-server
```yaml
@@ -312,24 +310,19 @@
restart: unless-stopped
```
## 其他
## Others
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
- [链接超时问题](https://github.com/lejianwen/rustdesk-api/issues/92)
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
- [webclient来源](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
- [Connection Timeout](https://github.com/lejianwen/rustdesk-api/issues/92)
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
- [Web client source](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
## Acknowledgements
## 鸣谢
感谢所有做过贡献的人!
Thanks to everyone who contributed!
<a href="https://github.com/lejianwen/rustdesk-api/graphs/contributors">
<img src="https://contrib.rocks/image?repo=lejianwen/rustdesk-api" />
</a>
## 感谢你的支持!如果这个项目对你有帮助,请点个⭐️鼓励一下,谢谢!
[lejianwen/rustdesk-server]: https://github.com/lejianwen/rustdesk-server
## Thanks for your support! If you find this project useful, please give it a ⭐️. Thank you!
+19 -20
View File
@@ -23,11 +23,11 @@ import (
"github.com/spf13/cobra"
)
const DatabaseVersion = 265
const DatabaseVersion = 264
// @title Management System API
// @title 管理系统API
// @version 1.0
// @description API
// @description 接口
// @basePath /api
// @securityDefinitions.apikey token
// @in header
@@ -111,10 +111,10 @@ func main() {
}
func InitGlobal() {
// config parsing
//配置解析
global.Viper = config.Init(&global.Config, global.ConfigPath)
// logging
//日志
global.Logger = logger.New(&logger.Config{
Path: global.Config.Logger.Path,
Level: global.Config.Logger.Level,
@@ -145,12 +145,11 @@ func InitGlobal() {
//gorm
if global.Config.Gorm.Type == config.TypeMysql {
dsn := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local&tls=%s",
dsn := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
global.Config.Mysql.Username,
global.Config.Mysql.Password,
global.Config.Mysql.Addr,
global.Config.Mysql.Dbname,
global.Config.Mysql.Tls,
)
global.DB = orm.NewMysql(&orm.MysqlConfig{
@@ -219,11 +218,11 @@ func DatabaseAutoUpdate() {
db := global.DB
if global.Config.Gorm.Type == config.TypeMysql {
// check whether the database exists; create it if not
//检查存不存在数据库,不存在则创建
dbName := db.Migrator().CurrentDatabase()
if dbName == "" {
dbName = global.Config.Mysql.Dbname
// remove the database name from the DSN so the initial connection does not specify a database
// 移除 DSN 中的数据库名称,以便初始连接时不指定数据库
dsnWithoutDB := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
global.Config.Mysql.Username,
global.Config.Mysql.Password,
@@ -231,19 +230,19 @@ func DatabaseAutoUpdate() {
"",
)
// new connection
//新链接
dbWithoutDB := orm.NewMysql(&orm.MysqlConfig{
Dsn: dsnWithoutDB,
}, global.Logger)
// get the underlying *sql.DB object and ensure the connection is closed when the program exits
// 获取底层的 *sql.DB 对象,并确保在程序退出时关闭连接
sqlDBWithoutDB, err := dbWithoutDB.DB()
if err != nil {
global.Logger.Errorf("failed to get underlying *sql.DB object: %v", err)
global.Logger.Errorf("获取底层 *sql.DB 对象失败: %v", err)
return
}
defer func() {
if err := sqlDBWithoutDB.Close(); err != nil {
global.Logger.Errorf("failed to close connection: %v", err)
global.Logger.Errorf("关闭连接失败: %v", err)
}
}()
@@ -258,20 +257,20 @@ func DatabaseAutoUpdate() {
if !db.Migrator().HasTable(&model.Version{}) {
Migrate(uint(version))
} else {
// find the last version
//查找最后一个version
var v model.Version
db.Last(&v)
if v.Version < uint(version) {
Migrate(uint(version))
}
// 245 migration
// 245迁移
if v.Version < 245 {
// set the oauths table's oauth_type field to the same value as op
//oauths 表的 oauth_type 字段设置为 op同样的值
db.Exec("update oauths set oauth_type = op")
db.Exec("update oauths set issuer = 'https://accounts.google.com' where op = 'google'")
db.Exec("update user_thirds set oauth_type = third_type, op = third_type")
// migrate old google authorizations by email
//通过email迁移旧的google授权
uts := make([]model.UserThird, 0)
db.Where("oauth_type = ?", "google").Find(&uts)
for _, ut := range uts {
@@ -311,7 +310,7 @@ func Migrate(version uint) {
global.Logger.Error("migrate err :=>", err)
}
global.DB.Create(&model.Version{Version: version})
// if this is the first run, create a default user
//如果是初次则创建一个默认用户
var vc int64
global.DB.Model(&model.Version{}).Count(&vc)
if vc == 1 {
@@ -333,7 +332,7 @@ func Migrate(version uint) {
Type: model.GroupTypeShare,
}
service.AllService.GroupService.Create(groupShare)
// is true
//true
is_admin := true
admin := &model.User{
Username: "admin",
@@ -343,7 +342,7 @@ func Migrate(version uint) {
GroupId: 1,
}
// generate a random password
// 生成随机密码
pwd := utils.RandomString(8)
global.Logger.Info("Admin Password Is: ", pwd)
var err error
+1
View File
@@ -0,0 +1 @@
### 👏👏👏 你好 ***{{username}}*** 欢迎使用 [RustDesk API](https://github.com/lejianwen/rustdesk-api)
+9 -10
View File
@@ -1,18 +1,18 @@
lang: "en"
lang: "zh-CN"
app:
web-client: 1 # 1:enable 0:disable
register: false #whether registration is enabled
register-status: 1 # default status for registered users 1:enable 2:disable
web-client: 1 # 1:启用 0:禁用
register: false #是否开启注册
register-status: 1 # 注册用户默认状态 1:启用 2:禁用
captcha-threshold: 3 # <0:disabled, 0 always, >0:enabled
ban-threshold: 0 # 0:disabled, >0:enabled
show-swagger: 0 # 1:enable 0:disable
show-swagger: 0 # 1:启用 0:禁用
token-expire: 168h
web-sso: true #web auth sso
disable-pwd-login: false #disable password login
disable-pwd-login: false #禁用密码登录
admin:
title: "RustDesk API Admin"
hello-file: "./conf/admin/hello.html" #prefer to use a file for the welcome message
hello-file: "./conf/admin/hello.html" #优先使用file
hello: ""
# ID Server and Relay Server ports https://github.com/lejianwen/rustdesk-api/issues/257
id-server-port: 21116 # ID Server port (for server cmd)
@@ -20,7 +20,7 @@ admin:
gin:
api-addr: "0.0.0.0:21114"
mode: "release" #release,debug,test
resources-path: 'resources' #public static file directory
resources-path: 'resources' #对外静态文件目录
trust-proxy: ""
gorm:
type: "sqlite"
@@ -31,7 +31,6 @@ mysql:
password: ""
addr: ""
dbname: ""
tls: "false" # true / false / skip-verify / custom
postgresql:
host: "127.0.0.1"
@@ -81,4 +80,4 @@ ldap:
last-name: "sn"
sync: false # If true, the user will be synchronized to the database when the user logs in. If false, the user will be synchronized to the database when the user be created.
admin-group: "cn=admin,dc=example,dc=com" # The group name of the admin group, if the user is in this group, the user will be an admin.
allow-group: "cn=users,dc=example,dc=com" # The group name of the users group, if the user is in this group, the user will be an login.
+4 -4
View File
@@ -58,7 +58,7 @@ func (a *Admin) Init() {
}
}
// Init initializes the configuration
// Init 初始化配置
func Init(rowVal *Config, path string) *viper.Viper {
if path == "" {
path = DefaultConfig
@@ -77,9 +77,9 @@ func Init(rowVal *Config, path string) *viper.Viper {
v.WatchConfig()
// watching for config changes is not really necessary
//监听配置修改没什么必要
v.OnConfigChange(func(e fsnotify.Event) {
// watch for config file changes
//配置文件修改监听
fmt.Println("config file changed:", e.Name)
if err2 := v.Unmarshal(rowVal); err2 != nil {
fmt.Println(err2)
@@ -96,7 +96,7 @@ func Init(rowVal *Config, path string) *viper.Viper {
return v
}
// ReadEnv reads environment variables
// ReadEnv 读取环境变量
func ReadEnv(rowVal interface{}) *viper.Viper {
v := viper.New()
v.AutomaticEnv()
-1
View File
@@ -17,7 +17,6 @@ type Mysql struct {
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Dbname string `mapstructure:"dbname"`
Tls string `mapstructure:"tls"` // true / false / skip-verify / custom
}
type Postgresql struct {
-1
View File
@@ -11,7 +11,6 @@ type LdapUser struct {
LastName string `mapstructure:"last-name"`
Sync bool `mapstructure:"sync"` // Will sync the user's information to the internal database
AdminGroup string `mapstructure:"admin-group"` // Which group is the admin group
AllowGroup string `mapstructure:"allow-group"` // Which group is allowed to login
}
// type LdapGroup struct {
+2 -2
View File
@@ -18,7 +18,7 @@ services:
ports:
- 21114:21114
volumes:
- ./data/rustdesk/api:/app/data #mount the database out for easy backup
- ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份
- ./conf:/app/conf # config
# - ./resources:/app/resources # static resources
# - ./resources:/app/resources # 静态资源
restart: unless-stopped
+1 -1
View File
@@ -13,5 +13,5 @@ services:
volumes:
- ./data/rustdesk/api:/app/data # database
# - ./conf:/app/conf # config
# - ./resources:/app/resources # static resources
# - ./resources:/app/resources # 静态资源
restart: unless-stopped
-64
View File
@@ -1,64 +0,0 @@
# RustDesk full stack (server + relay + API/Web Admin) — self-contained example.
#
# Copy to docker-compose.yml and adjust the public IP / keys / secrets:
# cp docker-compose.yml.example docker-compose.yml
#
# Everything is inline (no .env). The Ed25519 key below is an EXAMPLE — generate
# your own for production. The two keys belong together:
# - hbbs/hbbr get the SECRET key via -k
# - rustdesk-api gets the matching PUBLIC key via RUSTDESK_API_RUSTDESK_KEY
# (the public key is also what clients see as their "Key").
services:
hbbs:
container_name: hbbs
image: rustdesk/rustdesk-server:latest
command: hbbs -r 194.164.204.114:21117 -k 1jqLELJaIjaRtt1Tcj6BhqJ7DhT9WszBH/XUHrqJdhdg4K98HmANQFOpUx/vPZFRWnHPTYYHyIB8uH3Xxr8PTw==
environment:
- TZ=Europe/Berlin
- ENCRYPTED_ONLY=1
- MUST_LOGIN=Y
volumes:
- ./data/server:/root
ports:
- "21115:21115"
- "21116:21116"
- "21116:21116/udp"
- "21118:21118"
depends_on:
- hbbr
restart: unless-stopped
hbbr:
container_name: hbbr
image: rustdesk/rustdesk-server:latest
command: hbbr -k 1jqLELJaIjaRtt1Tcj6BhqJ7DhT9WszBH/XUHrqJdhdg4K98HmANQFOpUx/vPZFRWnHPTYYHyIB8uH3Xxr8PTw==
environment:
- TZ=Europe/Berlin
volumes:
- ./data/server:/root
ports:
- "21117:21117"
- "21119:21119"
restart: unless-stopped
rustdesk-api:
container_name: rustdesk-api
image: git.hackner.dev/thomas/rustdesk-api:latest
command: ["./apimain"]
environment:
- TZ=Europe/Berlin
- RUSTDESK_API_LANG=en
- RUSTDESK_API_RUSTDESK_ID_SERVER=194.164.204.114:21116
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=194.164.204.114:21117
- RUSTDESK_API_RUSTDESK_API_SERVER=http://194.164.204.114:21114
- RUSTDESK_API_RUSTDESK_KEY=YOCvfB5gDUBTqVMf7z2RUVpxz02GB8iAfLh918a/D08=
- RUSTDESK_API_JWT_KEY=z5rt4z465rtzdh5sudtuzrutd66zz6
ports:
- "21114:21114"
volumes:
- ./api:/app/data
depends_on:
- hbbs
- hbbr
restart: unless-stopped
+428 -428
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+138 -138
View File
@@ -17,7 +17,7 @@ const docTemplateapi = `{
"paths": {
"/": {
"get": {
"description": "home",
"description": "首页",
"consumes": [
"application/json"
],
@@ -25,9 +25,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"home"
"首页"
],
"summary": "home",
"summary": "首页",
"responses": {
"200": {
"description": "OK",
@@ -51,7 +51,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "address list",
"description": "地址列表",
"consumes": [
"application/json"
],
@@ -59,9 +59,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address"
"地址"
],
"summary": "address list",
"summary": "地址列表",
"responses": {
"200": {
"description": "OK",
@@ -83,7 +83,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "address update",
"description": "地址更新",
"consumes": [
"application/json"
],
@@ -91,12 +91,12 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address"
"地址"
],
"summary": "address update",
"summary": "地址更新",
"parameters": [
{
"description": "address form",
"description": "地址表单",
"name": "body",
"in": "body",
"required": true,
@@ -128,7 +128,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "add address",
"description": "添加地址",
"consumes": [
"application/json"
],
@@ -136,9 +136,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "add address",
"summary": "添加地址",
"parameters": [
{
"type": "string",
@@ -169,7 +169,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "delete address",
"description": "删除地址",
"consumes": [
"application/json"
],
@@ -177,9 +177,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "delete address",
"summary": "删除地址",
"parameters": [
{
"type": "string",
@@ -212,7 +212,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "update address",
"description": "更新地址",
"consumes": [
"application/json"
],
@@ -220,9 +220,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "update address",
"summary": "更新地址",
"parameters": [
{
"type": "string",
@@ -255,7 +255,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "address",
"description": "地址",
"consumes": [
"application/json"
],
@@ -263,19 +263,19 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "address list",
"summary": "地址列表",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "current",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
@@ -309,7 +309,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "personal address",
"description": "个人地址",
"consumes": [
"application/json"
],
@@ -317,9 +317,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "personal address",
"summary": "个人地址",
"parameters": [
{
"description": "string valid",
@@ -353,7 +353,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "settings",
"description": "设置",
"consumes": [
"application/json"
],
@@ -361,9 +361,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "settings",
"summary": "设置",
"parameters": [
{
"description": "string valid",
@@ -397,7 +397,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "shared",
"description": "共享",
"consumes": [
"application/json"
],
@@ -405,19 +405,19 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "shared address book",
"summary": "共享地址簿",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "current",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
}
@@ -445,7 +445,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -453,9 +453,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "add tag",
"summary": "标签添加",
"parameters": [
{
"type": "string",
@@ -488,7 +488,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -496,9 +496,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "rename tag",
"summary": "标签重命名",
"parameters": [
{
"type": "string",
@@ -531,7 +531,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -539,9 +539,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "change tag color",
"summary": "标签修改颜色",
"parameters": [
{
"type": "string",
@@ -574,7 +574,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -582,9 +582,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "delete tag",
"summary": "标签删除",
"parameters": [
{
"type": "string",
@@ -617,7 +617,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -625,9 +625,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "tag",
"summary": "标签",
"parameters": [
{
"type": "string",
@@ -655,7 +655,7 @@ const docTemplateapi = `{
},
"/audit/conn": {
"post": {
"description": "audit connection",
"description": "审计连接",
"consumes": [
"application/json"
],
@@ -663,12 +663,12 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"audit"
"审计"
],
"summary": "audit connection",
"summary": "审计连接",
"parameters": [
{
"description": "audit connection",
"description": "审计连接",
"name": "body",
"in": "body",
"required": true,
@@ -695,7 +695,7 @@ const docTemplateapi = `{
},
"/audit/file": {
"post": {
"description": "audit file",
"description": "审计文件",
"consumes": [
"application/json"
],
@@ -703,12 +703,12 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"audit"
"审计"
],
"summary": "audit file",
"summary": "审计文件",
"parameters": [
{
"description": "audit file",
"description": "审计文件",
"name": "body",
"in": "body",
"required": true,
@@ -740,7 +740,7 @@ const docTemplateapi = `{
"token": []
}
],
"description": "user info",
"description": "用户信息",
"consumes": [
"application/json"
],
@@ -748,9 +748,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"user"
"用户"
],
"summary": "user info",
"summary": "用户信息",
"responses": {
"200": {
"description": "OK",
@@ -774,7 +774,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "machine",
"description": "机器",
"consumes": [
"application/json"
],
@@ -782,25 +782,25 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"group"
"群组"
],
"summary": "device",
"summary": "设备",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
{
"type": "integer",
"description": "status",
"description": "状态",
"name": "status",
"in": "query"
},
@@ -829,7 +829,7 @@ const docTemplateapi = `{
},
"/heartbeat": {
"post": {
"description": "heartbeat",
"description": "心跳",
"consumes": [
"application/json"
],
@@ -837,9 +837,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"home"
"首页"
],
"summary": "heartbeat",
"summary": "心跳",
"responses": {
"200": {
"description": "OK"
@@ -855,7 +855,7 @@ const docTemplateapi = `{
},
"/login": {
"post": {
"description": "login",
"description": "登录",
"consumes": [
"application/json"
],
@@ -863,12 +863,12 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"login"
"登录"
],
"summary": "login",
"summary": "登录",
"parameters": [
{
"description": "login form",
"description": "登录表单",
"name": "body",
"in": "body",
"required": true,
@@ -895,7 +895,7 @@ const docTemplateapi = `{
},
"/login-options": {
"get": {
"description": "login options",
"description": "登录选项",
"consumes": [
"application/json"
],
@@ -903,9 +903,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"login"
"登录"
],
"summary": "login options",
"summary": "登录选项",
"responses": {
"200": {
"description": "OK",
@@ -927,7 +927,7 @@ const docTemplateapi = `{
},
"/logout": {
"post": {
"description": "logout",
"description": "登出",
"consumes": [
"application/json"
],
@@ -935,9 +935,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"login"
"登录"
],
"summary": "logout",
"summary": "登出",
"responses": {
"200": {
"description": "OK",
@@ -954,6 +954,35 @@ const docTemplateapi = `{
}
}
},
"/oauth/callback": {
"get": {
"description": "OauthCallback",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Oauth"
],
"summary": "OauthCallback",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.LoginRes"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/oidc/auth": {
"post": {
"description": "OidcAuth",
@@ -1012,35 +1041,6 @@ const docTemplateapi = `{
}
}
},
"/oidc/callback": {
"get": {
"description": "OauthCallback",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Oauth"
],
"summary": "OauthCallback",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.LoginRes"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/peers": {
"get": {
"security": [
@@ -1048,7 +1048,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "machine",
"description": "机器",
"consumes": [
"application/json"
],
@@ -1056,25 +1056,25 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"group"
"群组"
],
"summary": "machine",
"summary": "机器",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
{
"type": "integer",
"description": "status",
"description": "状态",
"name": "status",
"in": "query"
},
@@ -1108,7 +1108,7 @@ const docTemplateapi = `{
"token": []
}
],
"description": "service config, provides an api-server for the webclient",
"description": "服务配置,给webclient提供api-server",
"consumes": [
"application/json"
],
@@ -1118,7 +1118,7 @@ const docTemplateapi = `{
"tags": [
"WEBCLIENT"
],
"summary": "service config",
"summary": "服务配置",
"responses": {
"200": {
"description": "OK",
@@ -1142,7 +1142,7 @@ const docTemplateapi = `{
"token": []
}
],
"description": "service config, provides an api-server for the webclient",
"description": "服务配置,给webclient提供api-server",
"consumes": [
"application/json"
],
@@ -1152,7 +1152,7 @@ const docTemplateapi = `{
"tags": [
"WEBCLIENT_V2"
],
"summary": "service config",
"summary": "服务配置",
"responses": {
"200": {
"description": "OK",
@@ -1171,7 +1171,7 @@ const docTemplateapi = `{
},
"/shared-peer": {
"post": {
"description": "shared peer",
"description": "分享的peer",
"consumes": [
"application/json"
],
@@ -1181,7 +1181,7 @@ const docTemplateapi = `{
"tags": [
"WEBCLIENT"
],
"summary": "shared peer",
"summary": "分享的peer",
"responses": {
"200": {
"description": "OK",
@@ -1200,7 +1200,7 @@ const docTemplateapi = `{
},
"/sysinfo": {
"post": {
"description": "submit system info",
"description": "提交系统信息",
"consumes": [
"application/json"
],
@@ -1210,10 +1210,10 @@ const docTemplateapi = `{
"tags": [
"System"
],
"summary": "submit system info",
"summary": "提交系统信息",
"parameters": [
{
"description": "system info form",
"description": "系统信息表单",
"name": "body",
"in": "body",
"required": true,
@@ -1240,7 +1240,7 @@ const docTemplateapi = `{
},
"/sysinfo_ver": {
"post": {
"description": "get system version info",
"description": "获取系统版本信息",
"consumes": [
"application/json"
],
@@ -1250,7 +1250,7 @@ const docTemplateapi = `{
"tags": [
"System"
],
"summary": "get system version info",
"summary": "获取系统版本信息",
"responses": {
"200": {
"description": "OK",
@@ -1274,7 +1274,7 @@ const docTemplateapi = `{
"BearerAuth": []
}
],
"description": "user list",
"description": "用户列表",
"consumes": [
"application/json"
],
@@ -1282,25 +1282,25 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"group"
"群组"
],
"summary": "user list",
"summary": "用户列表",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
{
"type": "integer",
"description": "status",
"description": "状态",
"name": "status",
"in": "query"
},
@@ -1344,7 +1344,7 @@ const docTemplateapi = `{
},
"/version": {
"get": {
"description": "version",
"description": "版本",
"consumes": [
"application/json"
],
@@ -1352,9 +1352,9 @@ const docTemplateapi = `{
"application/json"
],
"tags": [
"home"
"首页"
],
"summary": "version",
"summary": "版本",
"responses": {
"200": {
"description": "OK",
@@ -1593,7 +1593,7 @@ const docTemplateapi = `{
"type": "integer"
},
"color": {
"description": "color is flutter's color value,from 0x00000000 to 0xFFFFFFFF; the first two digits represent transparency, the following 6 digits represent the color, can be converted to rgba",
"description": "color flutter的颜色值,从0x00000000 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
"type": "integer"
},
"created_at": {
@@ -1683,8 +1683,8 @@ var SwaggerInfoapi = &swag.Spec{
Host: "",
BasePath: "/api",
Schemes: []string{},
Title: "management systemAPI",
Description: "API",
Title: "管理系统API",
Description: "接口",
InfoInstanceName: "api",
SwaggerTemplate: docTemplateapi,
LeftDelim: "{{",
+138 -138
View File
@@ -1,8 +1,8 @@
{
"swagger": "2.0",
"info": {
"description": "API",
"title": "management systemAPI",
"description": "接口",
"title": "管理系统API",
"contact": {},
"version": "1.0"
},
@@ -10,7 +10,7 @@
"paths": {
"/": {
"get": {
"description": "home",
"description": "首页",
"consumes": [
"application/json"
],
@@ -18,9 +18,9 @@
"application/json"
],
"tags": [
"home"
"首页"
],
"summary": "home",
"summary": "首页",
"responses": {
"200": {
"description": "OK",
@@ -44,7 +44,7 @@
"BearerAuth": []
}
],
"description": "address list",
"description": "地址列表",
"consumes": [
"application/json"
],
@@ -52,9 +52,9 @@
"application/json"
],
"tags": [
"address"
"地址"
],
"summary": "address list",
"summary": "地址列表",
"responses": {
"200": {
"description": "OK",
@@ -76,7 +76,7 @@
"BearerAuth": []
}
],
"description": "address update",
"description": "地址更新",
"consumes": [
"application/json"
],
@@ -84,12 +84,12 @@
"application/json"
],
"tags": [
"address"
"地址"
],
"summary": "address update",
"summary": "地址更新",
"parameters": [
{
"description": "address form",
"description": "地址表单",
"name": "body",
"in": "body",
"required": true,
@@ -121,7 +121,7 @@
"BearerAuth": []
}
],
"description": "add address",
"description": "添加地址",
"consumes": [
"application/json"
],
@@ -129,9 +129,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "add address",
"summary": "添加地址",
"parameters": [
{
"type": "string",
@@ -162,7 +162,7 @@
"BearerAuth": []
}
],
"description": "delete address",
"description": "删除地址",
"consumes": [
"application/json"
],
@@ -170,9 +170,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "delete address",
"summary": "删除地址",
"parameters": [
{
"type": "string",
@@ -205,7 +205,7 @@
"BearerAuth": []
}
],
"description": "update address",
"description": "更新地址",
"consumes": [
"application/json"
],
@@ -213,9 +213,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "update address",
"summary": "更新地址",
"parameters": [
{
"type": "string",
@@ -248,7 +248,7 @@
"BearerAuth": []
}
],
"description": "address",
"description": "地址",
"consumes": [
"application/json"
],
@@ -256,19 +256,19 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "address list",
"summary": "地址列表",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "current",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
@@ -302,7 +302,7 @@
"BearerAuth": []
}
],
"description": "personal address",
"description": "个人地址",
"consumes": [
"application/json"
],
@@ -310,9 +310,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "personal address",
"summary": "个人地址",
"parameters": [
{
"description": "string valid",
@@ -346,7 +346,7 @@
"BearerAuth": []
}
],
"description": "settings",
"description": "设置",
"consumes": [
"application/json"
],
@@ -354,9 +354,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "settings",
"summary": "设置",
"parameters": [
{
"description": "string valid",
@@ -390,7 +390,7 @@
"BearerAuth": []
}
],
"description": "shared",
"description": "共享",
"consumes": [
"application/json"
],
@@ -398,19 +398,19 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "shared address book",
"summary": "共享地址簿",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "current",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
}
@@ -438,7 +438,7 @@
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -446,9 +446,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "add tag",
"summary": "标签添加",
"parameters": [
{
"type": "string",
@@ -481,7 +481,7 @@
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -489,9 +489,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "rename tag",
"summary": "标签重命名",
"parameters": [
{
"type": "string",
@@ -524,7 +524,7 @@
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -532,9 +532,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "change tag color",
"summary": "标签修改颜色",
"parameters": [
{
"type": "string",
@@ -567,7 +567,7 @@
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -575,9 +575,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "delete tag",
"summary": "标签删除",
"parameters": [
{
"type": "string",
@@ -610,7 +610,7 @@
"BearerAuth": []
}
],
"description": "tag",
"description": "标签",
"consumes": [
"application/json"
],
@@ -618,9 +618,9 @@
"application/json"
],
"tags": [
"address[Personal]"
"地址[Personal]"
],
"summary": "tag",
"summary": "标签",
"parameters": [
{
"type": "string",
@@ -648,7 +648,7 @@
},
"/audit/conn": {
"post": {
"description": "audit connection",
"description": "审计连接",
"consumes": [
"application/json"
],
@@ -656,12 +656,12 @@
"application/json"
],
"tags": [
"audit"
"审计"
],
"summary": "audit connection",
"summary": "审计连接",
"parameters": [
{
"description": "audit connection",
"description": "审计连接",
"name": "body",
"in": "body",
"required": true,
@@ -688,7 +688,7 @@
},
"/audit/file": {
"post": {
"description": "audit file",
"description": "审计文件",
"consumes": [
"application/json"
],
@@ -696,12 +696,12 @@
"application/json"
],
"tags": [
"audit"
"审计"
],
"summary": "audit file",
"summary": "审计文件",
"parameters": [
{
"description": "audit file",
"description": "审计文件",
"name": "body",
"in": "body",
"required": true,
@@ -733,7 +733,7 @@
"token": []
}
],
"description": "user info",
"description": "用户信息",
"consumes": [
"application/json"
],
@@ -741,9 +741,9 @@
"application/json"
],
"tags": [
"user"
"用户"
],
"summary": "user info",
"summary": "用户信息",
"responses": {
"200": {
"description": "OK",
@@ -767,7 +767,7 @@
"BearerAuth": []
}
],
"description": "machine",
"description": "机器",
"consumes": [
"application/json"
],
@@ -775,25 +775,25 @@
"application/json"
],
"tags": [
"group"
"群组"
],
"summary": "device",
"summary": "设备",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
{
"type": "integer",
"description": "status",
"description": "状态",
"name": "status",
"in": "query"
},
@@ -822,7 +822,7 @@
},
"/heartbeat": {
"post": {
"description": "heartbeat",
"description": "心跳",
"consumes": [
"application/json"
],
@@ -830,9 +830,9 @@
"application/json"
],
"tags": [
"home"
"首页"
],
"summary": "heartbeat",
"summary": "心跳",
"responses": {
"200": {
"description": "OK"
@@ -848,7 +848,7 @@
},
"/login": {
"post": {
"description": "login",
"description": "登录",
"consumes": [
"application/json"
],
@@ -856,12 +856,12 @@
"application/json"
],
"tags": [
"login"
"登录"
],
"summary": "login",
"summary": "登录",
"parameters": [
{
"description": "login form",
"description": "登录表单",
"name": "body",
"in": "body",
"required": true,
@@ -888,7 +888,7 @@
},
"/login-options": {
"get": {
"description": "login options",
"description": "登录选项",
"consumes": [
"application/json"
],
@@ -896,9 +896,9 @@
"application/json"
],
"tags": [
"login"
"登录"
],
"summary": "login options",
"summary": "登录选项",
"responses": {
"200": {
"description": "OK",
@@ -920,7 +920,7 @@
},
"/logout": {
"post": {
"description": "logout",
"description": "登出",
"consumes": [
"application/json"
],
@@ -928,9 +928,9 @@
"application/json"
],
"tags": [
"login"
"登录"
],
"summary": "logout",
"summary": "登出",
"responses": {
"200": {
"description": "OK",
@@ -947,6 +947,35 @@
}
}
},
"/oauth/callback": {
"get": {
"description": "OauthCallback",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Oauth"
],
"summary": "OauthCallback",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.LoginRes"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/oidc/auth": {
"post": {
"description": "OidcAuth",
@@ -1005,35 +1034,6 @@
}
}
},
"/oidc/callback": {
"get": {
"description": "OauthCallback",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Oauth"
],
"summary": "OauthCallback",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.LoginRes"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/peers": {
"get": {
"security": [
@@ -1041,7 +1041,7 @@
"BearerAuth": []
}
],
"description": "machine",
"description": "机器",
"consumes": [
"application/json"
],
@@ -1049,25 +1049,25 @@
"application/json"
],
"tags": [
"group"
"群组"
],
"summary": "machine",
"summary": "机器",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
{
"type": "integer",
"description": "status",
"description": "状态",
"name": "status",
"in": "query"
},
@@ -1101,7 +1101,7 @@
"token": []
}
],
"description": "service config, provides an api-server for the webclient",
"description": "服务配置,给webclient提供api-server",
"consumes": [
"application/json"
],
@@ -1111,7 +1111,7 @@
"tags": [
"WEBCLIENT"
],
"summary": "service config",
"summary": "服务配置",
"responses": {
"200": {
"description": "OK",
@@ -1135,7 +1135,7 @@
"token": []
}
],
"description": "service config, provides an api-server for the webclient",
"description": "服务配置,给webclient提供api-server",
"consumes": [
"application/json"
],
@@ -1145,7 +1145,7 @@
"tags": [
"WEBCLIENT_V2"
],
"summary": "service config",
"summary": "服务配置",
"responses": {
"200": {
"description": "OK",
@@ -1164,7 +1164,7 @@
},
"/shared-peer": {
"post": {
"description": "shared peer",
"description": "分享的peer",
"consumes": [
"application/json"
],
@@ -1174,7 +1174,7 @@
"tags": [
"WEBCLIENT"
],
"summary": "shared peer",
"summary": "分享的peer",
"responses": {
"200": {
"description": "OK",
@@ -1193,7 +1193,7 @@
},
"/sysinfo": {
"post": {
"description": "submit system info",
"description": "提交系统信息",
"consumes": [
"application/json"
],
@@ -1203,10 +1203,10 @@
"tags": [
"System"
],
"summary": "submit system info",
"summary": "提交系统信息",
"parameters": [
{
"description": "system info form",
"description": "系统信息表单",
"name": "body",
"in": "body",
"required": true,
@@ -1233,7 +1233,7 @@
},
"/sysinfo_ver": {
"post": {
"description": "get system version info",
"description": "获取系统版本信息",
"consumes": [
"application/json"
],
@@ -1243,7 +1243,7 @@
"tags": [
"System"
],
"summary": "get system version info",
"summary": "获取系统版本信息",
"responses": {
"200": {
"description": "OK",
@@ -1267,7 +1267,7 @@
"BearerAuth": []
}
],
"description": "user list",
"description": "用户列表",
"consumes": [
"application/json"
],
@@ -1275,25 +1275,25 @@
"application/json"
],
"tags": [
"group"
"群组"
],
"summary": "user list",
"summary": "用户列表",
"parameters": [
{
"type": "integer",
"description": "page number",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "items per page",
"description": "每页数量",
"name": "pageSize",
"in": "query"
},
{
"type": "integer",
"description": "status",
"description": "状态",
"name": "status",
"in": "query"
},
@@ -1337,7 +1337,7 @@
},
"/version": {
"get": {
"description": "version",
"description": "版本",
"consumes": [
"application/json"
],
@@ -1345,9 +1345,9 @@
"application/json"
],
"tags": [
"home"
"首页"
],
"summary": "version",
"summary": "版本",
"responses": {
"200": {
"description": "OK",
@@ -1586,7 +1586,7 @@
"type": "integer"
},
"color": {
"description": "color is flutter's color value,from 0x00000000 to 0xFFFFFFFF; the first two digits represent transparency, the following 6 digits represent the color, can be converted to rgba",
"description": "color flutter的颜色值,从0x00000000 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
"type": "integer"
},
"created_at": {
+129 -129
View File
@@ -146,8 +146,8 @@ definitions:
collection_id:
type: integer
color:
description: color is flutter's color value,from 0x00000000 to 0xFFFFFFFF; the first two digits represent transparency, the following 6 digits represent the color,
can be converted to rgba
description: color flutter的颜色值,从0x00000000 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色,
可以转成rgba
type: integer
created_at:
type: string
@@ -194,15 +194,15 @@ definitions:
type: object
info:
contact: {}
description: API
title: management systemAPI
description: 接口
title: 管理系统API
version: "1.0"
paths:
/:
get:
consumes:
- application/json
description: home
description: 首页
produces:
- application/json
responses:
@@ -214,14 +214,14 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
summary: home
summary: 首页
tags:
- home
- 首页
/ab:
get:
consumes:
- application/json
description: address list
description: 地址列表
produces:
- application/json
responses:
@@ -235,15 +235,15 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: address list
summary: 地址列表
tags:
- address
- 地址
post:
consumes:
- application/json
description: address update
description: 地址更新
parameters:
- description: address form
- description: 地址表单
in: body
name: body
required: true
@@ -262,14 +262,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: address update
summary: 地址更新
tags:
- address
- 地址
/ab/peer/add/{guid}:
delete:
consumes:
- application/json
description: delete address
description: 删除地址
parameters:
- description: guid
in: path
@@ -289,13 +289,13 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: delete address
summary: 删除地址
tags:
- address[Personal]
- 地址[Personal]
post:
consumes:
- application/json
description: add address
description: 添加地址
parameters:
- description: guid
in: path
@@ -315,14 +315,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: add address
summary: 添加地址
tags:
- address[Personal]
- 地址[Personal]
/ab/peer/update/{guid}:
put:
consumes:
- application/json
description: update address
description: 更新地址
parameters:
- description: guid
in: path
@@ -342,20 +342,20 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: update address
summary: 更新地址
tags:
- address[Personal]
- 地址[Personal]
/ab/peers:
post:
consumes:
- application/json
description: address
description: 地址
parameters:
- description: page number
- description: 页码
in: query
name: current
type: integer
- description: items per page
- description: 每页数量
in: query
name: pageSize
type: integer
@@ -376,14 +376,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: address list
summary: 地址列表
tags:
- address[Personal]
- 地址[Personal]
/ab/personal:
post:
consumes:
- application/json
description: personal address
description: 个人地址
parameters:
- description: string valid
in: body
@@ -403,14 +403,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: personal address
summary: 个人地址
tags:
- address[Personal]
- 地址[Personal]
/ab/settings:
post:
consumes:
- application/json
description: settings
description: 设置
parameters:
- description: string valid
in: body
@@ -430,20 +430,20 @@ paths:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: settings
summary: 设置
tags:
- address[Personal]
- 地址[Personal]
/ab/shared/profiles:
post:
consumes:
- application/json
description: shared
description: 共享
parameters:
- description: page number
- description: 页码
in: query
name: current
type: integer
- description: items per page
- description: 每页数量
in: query
name: pageSize
type: integer
@@ -460,14 +460,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: shared address book
summary: 共享地址簿
tags:
- address[Personal]
- 地址[Personal]
/ab/tag/{guid}:
delete:
consumes:
- application/json
description: tag
description: 标签
parameters:
- description: guid
in: path
@@ -487,14 +487,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: delete tag
summary: 标签删除
tags:
- address[Personal]
- 地址[Personal]
/ab/tag/add/{guid}:
post:
consumes:
- application/json
description: tag
description: 标签
parameters:
- description: guid
in: path
@@ -514,14 +514,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: add tag
summary: 标签添加
tags:
- address[Personal]
- 地址[Personal]
/ab/tag/rename/{guid}:
put:
consumes:
- application/json
description: tag
description: 标签
parameters:
- description: guid
in: path
@@ -541,14 +541,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: rename tag
summary: 标签重命名
tags:
- address[Personal]
- 地址[Personal]
/ab/tag/update/{guid}:
put:
consumes:
- application/json
description: tag
description: 标签
parameters:
- description: guid
in: path
@@ -568,14 +568,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: change tag color
summary: 标签修改颜色
tags:
- address[Personal]
- 地址[Personal]
/ab/tags/{guid}:
post:
consumes:
- application/json
description: tag
description: 标签
parameters:
- description: guid
in: path
@@ -595,16 +595,16 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: tag
summary: 标签
tags:
- address[Personal]
- 地址[Personal]
/audit/conn:
post:
consumes:
- application/json
description: audit connection
description: 审计连接
parameters:
- description: audit connection
- description: 审计连接
in: body
name: body
required: true
@@ -621,16 +621,16 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
summary: audit connection
summary: 审计连接
tags:
- audit
- 审计
/audit/file:
post:
consumes:
- application/json
description: audit file
description: 审计文件
parameters:
- description: audit file
- description: 审计文件
in: body
name: body
required: true
@@ -647,14 +647,14 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
summary: audit file
summary: 审计文件
tags:
- audit
- 审计
/currentUser:
get:
consumes:
- application/json
description: user info
description: 用户信息
produces:
- application/json
responses:
@@ -668,24 +668,24 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: user info
summary: 用户信息
tags:
- user
- 用户
/device-group/accessible:
get:
consumes:
- application/json
description: machine
description: 机器
parameters:
- description: page number
- description: 页码
in: query
name: page
type: integer
- description: items per page
- description: 每页数量
in: query
name: pageSize
type: integer
- description: status
- description: 状态
in: query
name: status
type: integer
@@ -706,14 +706,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: device
summary: 设备
tags:
- group
- 群组
/heartbeat:
post:
consumes:
- application/json
description: heartbeat
description: 心跳
produces:
- application/json
responses:
@@ -723,16 +723,16 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
summary: heartbeat
summary: 心跳
tags:
- home
- 首页
/login:
post:
consumes:
- application/json
description: login
description: 登录
parameters:
- description: login form
- description: 登录表单
in: body
name: body
required: true
@@ -749,14 +749,14 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: login
summary: 登录
tags:
- login
- 登录
/login-options:
get:
consumes:
- application/json
description: login options
description: 登录选项
produces:
- application/json
responses:
@@ -770,14 +770,14 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: login options
summary: 登录选项
tags:
- login
- 登录
/logout:
post:
consumes:
- application/json
description: logout
description: 登出
produces:
- application/json
responses:
@@ -789,9 +789,28 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: logout
summary: 登出
tags:
- login
- 登录
/oauth/callback:
get:
consumes:
- application/json
description: OauthCallback
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/api.LoginRes'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: OauthCallback
tags:
- Oauth
/oidc/auth:
post:
consumes:
@@ -830,40 +849,21 @@ paths:
summary: OidcAuthQuery
tags:
- Oauth
/oidc/callback:
get:
consumes:
- application/json
description: OauthCallback
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/api.LoginRes'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: OauthCallback
tags:
- Oauth
/peers:
get:
consumes:
- application/json
description: machine
description: 机器
parameters:
- description: page number
- description: 页码
in: query
name: page
type: integer
- description: items per page
- description: 每页数量
in: query
name: pageSize
type: integer
- description: status
- description: 状态
in: query
name: status
type: integer
@@ -884,14 +884,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: machine
summary: 机器
tags:
- group
- 群组
/server-config:
get:
consumes:
- application/json
description: service config, provides an api-server for the webclient
description: 服务配置,给webclient提供api-server
produces:
- application/json
responses:
@@ -905,14 +905,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: service config
summary: 服务配置
tags:
- WEBCLIENT
/server-config-v2:
get:
consumes:
- application/json
description: service config, provides an api-server for the webclient
description: 服务配置,给webclient提供api-server
produces:
- application/json
responses:
@@ -926,14 +926,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: service config
summary: 服务配置
tags:
- WEBCLIENT_V2
/shared-peer:
post:
consumes:
- application/json
description: shared peer
description: 分享的peer
produces:
- application/json
responses:
@@ -945,16 +945,16 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
summary: shared peer
summary: 分享的peer
tags:
- WEBCLIENT
/sysinfo:
post:
consumes:
- application/json
description: submit system info
description: 提交系统信息
parameters:
- description: system info form
- description: 系统信息表单
in: body
name: body
required: true
@@ -971,14 +971,14 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: submit system info
summary: 提交系统信息
tags:
- System
/sysinfo_ver:
post:
consumes:
- application/json
description: get system version info
description: 获取系统版本信息
produces:
- application/json
responses:
@@ -990,24 +990,24 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
summary: get system version info
summary: 获取系统版本信息
tags:
- System
/users:
get:
consumes:
- application/json
description: user list
description: 用户列表
parameters:
- description: page number
- description: 页码
in: query
name: page
type: integer
- description: items per page
- description: 每页数量
in: query
name: pageSize
type: integer
- description: status
- description: 状态
in: query
name: status
type: integer
@@ -1035,14 +1035,14 @@ paths:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: user list
summary: 用户列表
tags:
- group
- 群组
/version:
get:
consumes:
- application/json
description: version
description: 版本
produces:
- application/json
responses:
@@ -1054,9 +1054,9 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
summary: version
summary: 版本
tags:
- home
- 首页
securityDefinitions:
BearerAuth:
in: header
+2 -2
View File
@@ -24,7 +24,7 @@ import (
func ApiInitValidator() {
validate := validator.New()
// define translations for different languages
// 定义不同的语言翻译
enT := en.New()
cn := zh_Hans_CN.New()
koT := ko.New()
@@ -81,7 +81,7 @@ func ApiInitValidator() {
return label
})
Validator.Validate = validate
Validator.UT = uni // store the Universal Translator
Validator.UT = uni // 存储 Universal Translator
Validator.VTrans = zhTrans
Validator.ValidStruct = func(ctx *gin.Context, i interface{}) []string {
+2 -2
View File
@@ -10,14 +10,14 @@ import (
func InitI18n() {
bundle := i18n.NewBundle(language.English)
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
// read all language files under global.Config.Gin.ResourcesPath
//读取global.Config.Gin.ResourcesPath下的所有语言文件
dir := Config.Gin.ResourcesPath + "/i18n"
fileInfos, err := os.ReadDir(dir)
if err != nil {
panic(err)
}
for _, fileInfo := range fileInfos {
// if the file name does not end with .toml
//如果文件名不是.toml结尾
if fileInfo.IsDir() || fileInfo.Name()[len(fileInfo.Name())-5:] != ".toml" {
continue
}
+1 -1
View File
@@ -25,7 +25,6 @@ require (
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/swaggo/swag v1.16.3
golang.org/x/crypto v0.33.0
golang.org/x/oauth2 v0.23.0
golang.org/x/text v0.22.0
gorm.io/driver/mysql v1.5.7
@@ -85,6 +84,7 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/image v0.13.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/sync v0.11.0 // indirect
+39 -39
View File
@@ -15,10 +15,10 @@ import (
type AddressBook struct {
}
// Detail address book
// @Tags address book
// @Summary address book details
// @Description address book details
// Detail 地址簿
// @Tags 地址簿
// @Summary 地址簿详情
// @Description 地址簿详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -38,13 +38,13 @@ func (ct *AddressBook) Detail(c *gin.Context) {
return
}
// Create create address book
// @Tags address book
// @Summary create address book
// @Description create address book
// Create 创建地址簿
// @Tags 地址簿
// @Summary 创建地址簿
// @Description 创建地址簿
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response{data=model.AddressBook}
// @Failure 500 {object} response.Response
// @Router /admin/address_book/create [post]
@@ -84,13 +84,13 @@ func (ct *AddressBook) Create(c *gin.Context) {
response.Success(c, nil)
}
// BatchCreate batch create address books
// @Tags address book
// @Summary batch create address books
// @Description batch create address books
// BatchCreate 批量创建地址簿
// @Tags 地址簿
// @Summary 批量创建地址簿
// @Description 批量创建地址簿
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response{data=model.AddressBook}
// @Failure 500 {object} response.Response
// @Router /admin/address_book/batchCreate [post]
@@ -113,13 +113,13 @@ func (ct *AddressBook) BatchCreate(c *gin.Context) {
return
}
if ul > 1 {
//clear tags in multi-user mode
//多用户置空标签
f.Tags = []string{}
//in multi-user mode, can only create in the default address book
//多用户只能创建到默认地址簿
f.CollectionId = 0
}
//create tag
//创建标签
/*for _, fu := range f.UserIds {
if fu == 0 {
continue
@@ -148,16 +148,16 @@ func (ct *AddressBook) BatchCreate(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags address book
// @Summary address book list
// @Description address book list
// List 列表
// @Tags 地址簿
// @Summary 地址簿列表
// @Description 地址簿列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param user_id query int false "userid"
// @Param is_my query int false "whether it is mine"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param user_id query int false "用户id"
// @Param is_my query int false "是否是我的"
// @Success 200 {object} response.Response{data=model.AddressBookList}
// @Failure 500 {object} response.Response
// @Router /admin/address_book/list [get]
@@ -196,13 +196,13 @@ func (ct *AddressBook) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags address book
// @Summary edit address book
// @Description edit address book
// Update 编辑
// @Tags 地址簿
// @Summary 地址簿编辑
// @Description 地址簿编辑
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response{data=model.AddressBook}
// @Failure 500 {object} response.Response
// @Router /admin/address_book/update [post]
@@ -240,13 +240,13 @@ func (ct *AddressBook) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags address book
// @Summary delete address book
// @Description delete address book
// Delete 删除
// @Tags 地址簿
// @Summary 地址簿删除
// @Description 地址簿删除
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/address_book/delete [post]
@@ -277,12 +277,12 @@ func (ct *AddressBook) Delete(c *gin.Context) {
}
// ShareByWebClient
// @Tags address book
// @Summary share address book
// @Description share address book
// @Tags 地址簿
// @Summary 地址簿分享
// @Description 地址簿分享
// @Accept json
// @Produce json
// @Param body body admin.ShareByWebClientForm true "address book info"
// @Param body body admin.ShareByWebClientForm true "地址簿信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/address_book/share [post]
+27 -27
View File
@@ -14,10 +14,10 @@ import (
type AddressBookCollection struct {
}
// Detail address book name
// @Tags address book name
// @Summary address book name details
// @Description address book name details
// Detail 地址簿名称
// @Tags 地址簿名称
// @Summary 地址簿名称详情
// @Description 地址簿名称详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -37,13 +37,13 @@ func (abc *AddressBookCollection) Detail(c *gin.Context) {
return
}
// Create create address book name
// @Tags address book name
// @Summary create address book name
// @Description create address book name
// Create 创建地址簿名称
// @Tags 地址簿名称
// @Summary 创建地址簿名称
// @Description 创建地址簿名称
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollection true "address book name info"
// @Param body body model.AddressBookCollection true "地址簿名称信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection/create [post]
@@ -72,16 +72,16 @@ func (abc *AddressBookCollection) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags address book name
// @Summary address book name list
// @Description address book name list
// List 列表
// @Tags 地址簿名称
// @Summary 地址簿名称列表
// @Description 地址簿名称列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param is_my query int false "whether it is mine"
// @Param user_id query int false "userid"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param is_my query int false "是否是我的"
// @Param user_id query int false "用户id"
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection/list [get]
@@ -100,13 +100,13 @@ func (abc *AddressBookCollection) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags address book name
// @Summary edit address book name
// @Description edit address book name
// Update 编辑
// @Tags 地址簿名称
// @Summary 地址簿名称编辑
// @Description 地址簿名称编辑
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollection true "address book name info"
// @Param body body model.AddressBookCollection true "地址簿名称信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection/update [post]
@@ -135,13 +135,13 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags address book name
// @Summary delete address book name
// @Description delete address book name
// Delete 删除
// @Tags 地址簿名称
// @Summary 地址簿名称删除
// @Description 地址簿名称删除
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollection true "address book name info"
// @Param body body model.AddressBookCollection true "地址簿名称信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection/delete [post]
@@ -14,17 +14,17 @@ import (
type AddressBookCollectionRule struct {
}
// List list
// @Tags address book rules
// @Summary address book rule list
// @Description address book rule list
// List 列表
// @Tags 地址簿规则
// @Summary 地址簿规则列表
// @Description 地址簿规则列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param is_my query int false "whether it is mine"
// @Param user_id query int false "userid"
// @Param collection_id query int false "address book collectionid"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param is_my query int false "是否是我的"
// @Param user_id query int false "用户id"
// @Param collection_id query int false "地址簿集合id"
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection_rule/list [get]
@@ -47,10 +47,10 @@ func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
response.Success(c, res)
}
// Detail address book rules
// @Tags address book rules
// @Summary address book rule details
// @Description address book rule details
// Detail 地址簿规则
// @Tags 地址簿规则
// @Summary 地址簿规则详情
// @Description 地址簿规则详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -69,13 +69,13 @@ func (abcr *AddressBookCollectionRule) Detail(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// Create create address book rule
// @Tags address book rules
// @Summary create address book rule
// @Description create address book rule
// Create 创建地址簿规则
// @Tags 地址簿规则
// @Summary 创建地址簿规则
// @Description 创建地址簿规则
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollectionRule true "address book rule info"
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection_rule/create [post]
@@ -134,7 +134,7 @@ func (abcr *AddressBookCollectionRule) CheckForm(t *model.AddressBookCollectionR
} else {
return "ParamsError", false
}
// duplicate check
// 重复检查
ex := service.AllService.AddressBookService.RuleInfoByToIdAndCid(t.Type, t.ToId, t.CollectionId)
if t.Id == 0 && ex.Id > 0 {
return "ItemExists", false
@@ -145,13 +145,13 @@ func (abcr *AddressBookCollectionRule) CheckForm(t *model.AddressBookCollectionR
return "", true
}
// Update edit
// @Tags address book rules
// @Summary edit address book rule
// @Description edit address book rule
// Update 编辑
// @Tags 地址簿规则
// @Summary 地址簿规则编辑
// @Description 地址簿规则编辑
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollectionRule true "address book rule info"
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection_rule/update [post]
@@ -185,13 +185,13 @@ func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags address book rules
// @Summary delete address book rule
// @Description delete address book rule
// Delete 删除
// @Tags 地址簿规则
// @Summary 地址簿规则删除
// @Description 地址簿规则删除
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollectionRule true "address book rule info"
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/address_book_collection_rule/delete [post]
+36 -36
View File
@@ -13,16 +13,16 @@ import (
type Audit struct {
}
// ConnList list
// @Tags connection log
// @Summary connection log list
// @Description connection log list
// ConnList 列表
// @Tags 链接日志
// @Summary 链接日志列表
// @Description 链接日志列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param peer_id query int false "target device"
// @Param from_peer query int false "source device"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param peer_id query int false "目标设备"
// @Param from_peer query int false "来源设备"
// @Success 200 {object} response.Response{data=model.AuditConnList}
// @Failure 500 {object} response.Response
// @Router /admin/audit_conn/list [get]
@@ -45,13 +45,13 @@ func (a *Audit) ConnList(c *gin.Context) {
response.Success(c, res)
}
// ConnDelete delete
// @Tags connection log
// @Summary delete connection log
// @Description delete connection log
// ConnDelete 删除
// @Tags 链接日志
// @Summary 链接日志删除
// @Description 链接日志删除
// @Accept json
// @Produce json
// @Param body body model.AuditConn true "connection log info"
// @Param body body model.AuditConn true "链接日志信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/audit_conn/delete [post]
@@ -81,13 +81,13 @@ func (a *Audit) ConnDelete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchConnDelete delete
// @Tags connection log
// @Summary batch delete connection logs
// @Description batch delete connection logs
// BatchConnDelete 删除
// @Tags 链接日志
// @Summary 链接日志批量删除
// @Description 链接日志批量删除
// @Accept json
// @Produce json
// @Param body body admin.AuditConnLogIds true "connection log"
// @Param body body admin.AuditConnLogIds true "链接日志"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/audit_conn/batchDelete [post]
@@ -112,16 +112,16 @@ func (a *Audit) BatchConnDelete(c *gin.Context) {
return
}
// FileList list
// @Tags file log
// @Summary file log list
// @Description file log list
// FileList 列表
// @Tags 文件日志
// @Summary 文件日志列表
// @Description 文件日志列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param peer_id query int false "target device"
// @Param from_peer query int false "source device"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param peer_id query int false "目标设备"
// @Param from_peer query int false "来源设备"
// @Success 200 {object} response.Response{data=model.AuditFileList}
// @Failure 500 {object} response.Response
// @Router /admin/audit_file/list [get]
@@ -144,13 +144,13 @@ func (a *Audit) FileList(c *gin.Context) {
response.Success(c, res)
}
// FileDelete delete
// @Tags file log
// @Summary delete file log
// @Description delete file log
// FileDelete 删除
// @Tags 文件日志
// @Summary 文件日志删除
// @Description 文件日志删除
// @Accept json
// @Produce json
// @Param body body model.AuditFile true "file log info"
// @Param body body model.AuditFile true "文件日志信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/audit_file/delete [post]
@@ -180,13 +180,13 @@ func (a *Audit) FileDelete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchFileDelete delete
// @Tags file log
// @Summary batch delete file logs
// @Description batch delete file logs
// BatchFileDelete 删除
// @Tags 文件日志
// @Summary 文件日志批量删除
// @Description 文件日志批量删除
// @Accept json
// @Produce json
// @Param body body admin.AuditFileLogIds true "file log"
// @Param body body admin.AuditFileLogIds true "文件日志"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/audit_file/batchDelete [post]
+9 -9
View File
@@ -13,10 +13,10 @@ import (
type Config struct {
}
// ServerConfig RUSTDESKservice config
// ServerConfig RUSTDESK服务配置
// @Tags ADMIN
// @Summary RUSTDESKservice config
// @Description service config, provides an api-server for the webclient
// @Summary RUSTDESK服务配置
// @Description 服务配置,给webclient提供api-server
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -33,10 +33,10 @@ func (co *Config) ServerConfig(c *gin.Context) {
response.Success(c, cf)
}
// AppConfig APPservice config
// AppConfig APP服务配置
// @Tags ADMIN
// @Summary APPservice config
// @Description APPservice config
// @Summary APP服务配置
// @Description APP服务配置
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -49,10 +49,10 @@ func (co *Config) AppConfig(c *gin.Context) {
})
}
// AdminConfig ADMINservice config
// AdminConfig ADMIN服务配置
// @Tags ADMIN
// @Summary ADMINservice config
// @Description ADMINservice config
// @Summary ADMIN服务配置
// @Description ADMIN服务配置
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
+25 -25
View File
@@ -12,10 +12,10 @@ import (
type DeviceGroup struct {
}
// Detail device group
// @Tags device group
// @Summary device group details
// @Description device group details
// Detail 设备群组
// @Tags 设备群组
// @Summary 设备群组详情
// @Description 设备群组详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -35,13 +35,13 @@ func (ct *DeviceGroup) Detail(c *gin.Context) {
return
}
// Create create device group
// @Tags device group
// @Summary create device group
// @Description create device group
// Create 创建设备群组
// @Tags 设备群组
// @Summary 创建设备群组
// @Description 创建设备群组
// @Accept json
// @Produce json
// @Param body body admin.DeviceGroupForm true "device group info"
// @Param body body admin.DeviceGroupForm true "设备群组信息"
// @Success 200 {object} response.Response{data=model.DeviceGroup}
// @Failure 500 {object} response.Response
// @Router /admin/device_group/create [post]
@@ -66,14 +66,14 @@ func (ct *DeviceGroup) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags group
// @Summary group list
// @Description group list
// List 列表
// @Tags 群组
// @Summary 群组列表
// @Description 群组列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response{data=model.GroupList}
// @Failure 500 {object} response.Response
// @Router /admin/device_group/list [get]
@@ -88,13 +88,13 @@ func (ct *DeviceGroup) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags device group
// @Summary edit device group
// @Description edit device group
// Update 编辑
// @Tags 设备群组
// @Summary 设备群组编辑
// @Description 设备群组编辑
// @Accept json
// @Produce json
// @Param body body admin.DeviceGroupForm true "group info"
// @Param body body admin.DeviceGroupForm true "群组信息"
// @Success 200 {object} response.Response{data=model.Group}
// @Failure 500 {object} response.Response
// @Router /admin/device_group/update [post]
@@ -123,13 +123,13 @@ func (ct *DeviceGroup) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags device group
// @Summary delete device group
// @Description delete device group
// Delete 删除
// @Tags 设备群组
// @Summary 设备群组删除
// @Description 设备群组删除
// @Accept json
// @Produce json
// @Param body body admin.DeviceGroupForm true "group info"
// @Param body body admin.DeviceGroupForm true "群组信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/device_group/delete [post]
+12 -12
View File
@@ -13,10 +13,10 @@ import (
type File struct {
}
// OssToken file
// @Tags file
// @Summary getossToken
// @Description getossToken
// OssToken 文件
// @Tags 文件
// @Summary 获取ossToken
// @Description 获取ossToken
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -33,7 +33,7 @@ type FileBack struct {
Url string `json:"url"`
}
// Notify callback after successful upload
// Notify 上传成功后回调
func (f *File) Notify(c *gin.Context) {
res := global.Oss.Verify(c.Request)
@@ -50,13 +50,13 @@ func (f *File) Notify(c *gin.Context) {
}
// Upload upload file to local
// @Tags file
// @Summary upload file to local
// @Description upload file to local
// Upload 上传文件到本地
// @Tags 文件
// @Summary 上传文件到本地
// @Description 上传文件到本地
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "file upload example"
// @Param file formData file true "上传文件示例"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/file/upload [post]
@@ -71,12 +71,12 @@ func (f *File) Upload(c *gin.Context) {
if err != nil {
return
}
// upload the file to the specified directory
// 上传文件至指定目录
err = c.SaveUploadedFile(file, dst)
if err != nil {
return
}
// return filewebaddress
// 返回文件web地址
response.Success(c, gin.H{
"url": webPath + file.Filename,
})
+25 -25
View File
@@ -12,10 +12,10 @@ import (
type Group struct {
}
// Detail group
// @Tags group
// @Summary group details
// @Description group details
// Detail 群组
// @Tags 群组
// @Summary 群组详情
// @Description 群组详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -35,13 +35,13 @@ func (ct *Group) Detail(c *gin.Context) {
return
}
// Create create group
// @Tags group
// @Summary create group
// @Description create group
// Create 创建群组
// @Tags 群组
// @Summary 创建群组
// @Description 创建群组
// @Accept json
// @Produce json
// @Param body body admin.GroupForm true "group info"
// @Param body body admin.GroupForm true "群组信息"
// @Success 200 {object} response.Response{data=model.Group}
// @Failure 500 {object} response.Response
// @Router /admin/group/create [post]
@@ -66,14 +66,14 @@ func (ct *Group) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags group
// @Summary group list
// @Description group list
// List 列表
// @Tags 群组
// @Summary 群组列表
// @Description 群组列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response{data=model.GroupList}
// @Failure 500 {object} response.Response
// @Router /admin/group/list [get]
@@ -88,13 +88,13 @@ func (ct *Group) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags group
// @Summary edit group
// @Description edit group
// Update 编辑
// @Tags 群组
// @Summary 群组编辑
// @Description 群组编辑
// @Accept json
// @Produce json
// @Param body body admin.GroupForm true "group info"
// @Param body body admin.GroupForm true "群组信息"
// @Success 200 {object} response.Response{data=model.Group}
// @Failure 500 {object} response.Response
// @Router /admin/group/update [post]
@@ -123,13 +123,13 @@ func (ct *Group) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags group
// @Summary delete group
// @Description delete group
// Delete 删除
// @Tags 群组
// @Summary 群组删除
// @Description 群组删除
// @Accept json
// @Produce json
// @Param body body admin.GroupForm true "group info"
// @Param body body admin.GroupForm true "群组信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/group/delete [post]
+16 -18
View File
@@ -17,13 +17,13 @@ import (
type Login struct {
}
// Login login
// @Tags login
// @Summary login
// @Description login
// Login 登录
// @Tags 登录
// @Summary 登录
// @Description 登录
// @Accept json
// @Produce json
// @Param body body admin.Login true "login info"
// @Param body body admin.Login true "登录信息"
// @Success 200 {object} response.Response{data=adResp.LoginPayload}
// @Failure 500 {object} response.Response
// @Router /admin/login [post]
@@ -34,7 +34,7 @@ func (ct *Login) Login(c *gin.Context) {
return
}
// check login limit
// 检查登录限制
loginLimiter := global.LoginLimiter
clientIp := c.ClientIP()
_, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
@@ -56,7 +56,7 @@ func (ct *Login) Login(c *gin.Context) {
return
}
// check whether a captcha is required
// 检查是否需要验证码
if needCaptcha {
if f.CaptchaId == "" || f.Captcha == "" || !loginLimiter.VerifyCaptcha(f.CaptchaId, f.Captcha) {
response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError"))
@@ -95,7 +95,7 @@ func (ct *Login) Login(c *gin.Context) {
Platform: f.Platform,
})
// login successful, clear the login limit
// 登录成功,清除登录限制
loginLimiter.RemoveAttempts(clientIp)
responseLoginSuccess(c, u, ut.Token)
}
@@ -129,10 +129,10 @@ func (ct *Login) Captcha(c *gin.Context) {
})
}
// Logout logout
// @Tags login
// @Summary logout
// @Description logout
// Logout 登出
// @Tags 登录
// @Summary 登出
// @Description 登出
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -148,9 +148,9 @@ func (ct *Login) Logout(c *gin.Context) {
}
// LoginOptions
// @Tags login
// @Summary login options
// @Description login options
// @Tags 登录
// @Summary 登录选项
// @Description 登录选项
// @Accept json
// @Produce json
// @Success 200 {object} []string
@@ -169,8 +169,6 @@ func (ct *Login) LoginOptions(c *gin.Context) {
"ops": ops,
"register": global.Config.App.Register,
"need_captcha": needCaptcha,
"disable_pwd": global.Config.App.DisablePwdLogin,
"auto_oidc": global.Config.App.DisablePwdLogin && len(ops) == 1,
})
}
@@ -191,7 +189,7 @@ func (ct *Login) OidcAuth(c *gin.Context) {
return
}
err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(f.Op)
err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(c, f.Op)
if err != nil {
response.Error(c, response.TranslateMsg(c, err.Error()))
return
+21 -21
View File
@@ -14,10 +14,10 @@ import (
type LoginLog struct {
}
// Detail login log
// @Tags login log
// @Summary login log details
// @Description login log details
// Detail 登录日志
// @Tags 登录日志
// @Summary 登录日志详情
// @Description 登录日志详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -37,15 +37,15 @@ func (ct *LoginLog) Detail(c *gin.Context) {
return
}
// List list
// @Tags login log
// @Summary login log list
// @Description login log list
// List 列表
// @Tags 登录日志
// @Summary 登录日志列表
// @Description 登录日志列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param user_id query int false "userID"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param user_id query int false "用户ID"
// @Success 200 {object} response.Response{data=model.LoginLogList}
// @Failure 500 {object} response.Response
// @Router /admin/login_log/list [get]
@@ -65,13 +65,13 @@ func (ct *LoginLog) List(c *gin.Context) {
response.Success(c, res)
}
// Delete delete
// @Tags login log
// @Summary delete login log
// @Description delete login log
// Delete 删除
// @Tags 登录日志
// @Summary 登录日志删除
// @Description 登录日志删除
// @Accept json
// @Produce json
// @Param body body model.LoginLog true "login log info"
// @Param body body model.LoginLog true "登录日志信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/login_log/delete [post]
@@ -101,13 +101,13 @@ func (ct *LoginLog) Delete(c *gin.Context) {
response.Fail(c, 101, err.Error())
}
// BatchDelete delete
// @Tags login log
// @Summary batch delete login logs
// @Description batch delete login logs
// BatchDelete 删除
// @Tags 登录日志
// @Summary 登录日志批量删除
// @Description 登录日志批量删除
// @Accept json
// @Produce json
// @Param body body admin.LoginLogIds true "login log"
// @Param body body admin.LoginLogIds true "登录日志"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/login_log/batchDelete [post]
+23 -23
View File
@@ -12,15 +12,15 @@ import (
type AddressBook struct{}
// List list
// @Tags my address book
// @Summary address book list
// @Description address book list
// List 列表
// @Tags 我的地址簿
// @Summary 地址簿列表
// @Description 地址簿列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param user_id query int false "userid"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param user_id query int false "用户id"
// @Success 200 {object} response.Response{data=model.AddressBookList}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book/list [get]
@@ -34,7 +34,7 @@ func (ct *AddressBook) List(c *gin.Context) {
u := service.AllService.UserService.CurUser(c)
query.UserId = int(u.Id)
res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
//preload address book name
//预加载地址簿名称
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
return txc.Select("id,name")
})
@@ -60,13 +60,13 @@ func (ct *AddressBook) List(c *gin.Context) {
response.Success(c, res)
}
// Create create address book
// @Tags my address book
// @Summary create address book
// @Description create address book
// Create 创建地址簿
// @Tags 我的地址簿
// @Summary 创建地址簿
// @Description 创建地址簿
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response{data=model.AddressBook}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book/create [post]
@@ -104,13 +104,13 @@ func (ct *AddressBook) Create(c *gin.Context) {
response.Success(c, nil)
}
// Update edit
// @Tags my address book
// @Summary edit address book
// @Description edit address book
// Update 编辑
// @Tags 我的地址簿
// @Summary 地址簿编辑
// @Description 地址簿编辑
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response{data=model.AddressBook}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book/update [post]
@@ -158,13 +158,13 @@ func (ct *AddressBook) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags my address book
// @Summary delete address book
// @Description delete address book
// Delete 删除
// @Tags 我的地址簿
// @Summary 地址簿删除
// @Description 地址簿删除
// @Accept json
// @Produce json
// @Param body body admin.AddressBookForm true "address book info"
// @Param body body admin.AddressBookForm true "地址簿信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book/delete [post]
@@ -13,13 +13,13 @@ import (
type AddressBookCollection struct {
}
// Create create address book name
// @Tags my address book name
// @Summary create address book name
// @Description create address book name
// Create 创建地址簿名称
// @Tags 我的地址簿名称
// @Summary 创建地址簿名称
// @Description 创建地址簿名称
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollection true "address book name info"
// @Param body body model.AddressBookCollection true "地址簿名称信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection/create [post]
@@ -45,14 +45,14 @@ func (abc *AddressBookCollection) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags my address book name
// @Summary address book name list
// @Description address book name list
// List 列表
// @Tags 我的地址簿名称
// @Summary 地址簿名称列表
// @Description 地址簿名称列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection/list [get]
@@ -71,13 +71,13 @@ func (abc *AddressBookCollection) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags my address book name
// @Summary edit address book name
// @Description edit address book name
// Update 编辑
// @Tags 我的地址簿名称
// @Summary 地址簿名称编辑
// @Description 地址簿名称编辑
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollection true "address book name info"
// @Param body body model.AddressBookCollection true "地址簿名称信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection/update [post]
@@ -98,10 +98,10 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
return
}
u := service.AllService.UserService.CurUser(c)
//if f.UserId != u.Id {
// response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
// return
//}
if f.UserId != u.Id {
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
ex := service.AllService.AddressBookService.CollectionInfoById(f.Id)
if ex.Id == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
@@ -120,13 +120,13 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags my address book name
// @Summary delete address book name
// @Description delete address book name
// Delete 删除
// @Tags 我的地址簿名称
// @Summary 地址簿名称删除
// @Description 地址簿名称删除
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollection true "address book name info"
// @Param body body model.AddressBookCollection true "地址簿名称信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection/delete [post]
@@ -13,17 +13,17 @@ import (
type AddressBookCollectionRule struct {
}
// List list
// @Tags my address book rules
// @Summary address book rule list
// @Description address book rule list
// List 列表
// @Tags 我的地址簿规则
// @Summary 地址簿规则列表
// @Description 地址簿规则列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param is_my query int false "whether it is mine"
// @Param user_id query int false "userid"
// @Param collection_id query int false "address book collectionid"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param is_my query int false "是否是我的"
// @Param user_id query int false "用户id"
// @Param collection_id query int false "地址簿集合id"
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection_rule/list [get]
@@ -46,13 +46,13 @@ func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
response.Success(c, res)
}
// Create create address book rule
// @Tags my address book rules
// @Summary create address book rule
// @Description create address book rule
// Create 创建地址簿规则
// @Tags 我的地址簿规则
// @Summary 创建地址簿规则
// @Description 创建地址簿规则
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollectionRule true "address book rule info"
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection_rule/create [post]
@@ -106,12 +106,12 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
if tou.Id == 0 {
return "ItemNotFound", false
}
//non-admins cannot share with users outside their own organization
//非管理员不能分享给非本组织用户
//if tou.GroupId != u.GroupId {
// return "NoAccess", false
//}
} else if t.Type == model.ShareAddressBookRuleTypeGroup {
//non-admins cannot share with other groups
//非管理员不能分享给其他组
//if t.ToId != u.GroupId {
// return "NoAccess", false
//}
@@ -123,7 +123,7 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
} else {
return "ParamsError", false
}
// duplicate check
// 重复检查
ex := service.AllService.AddressBookService.RuleInfoByToIdAndCid(t.Type, t.ToId, t.CollectionId)
if t.Id == 0 && ex.Id > 0 {
return "ItemExists", false
@@ -134,13 +134,13 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
return "", true
}
// Update edit
// @Tags my address book rules
// @Summary edit address book rule
// @Description edit address book rule
// Update 编辑
// @Tags 我的地址簿规则
// @Summary 地址簿规则编辑
// @Description 地址簿规则编辑
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollectionRule true "address book rule info"
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection_rule/update [post]
@@ -185,13 +185,13 @@ func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags my address book rules
// @Summary delete address book rule
// @Description delete address book rule
// Delete 删除
// @Tags 我的地址簿规则
// @Summary 地址簿规则删除
// @Description 地址簿规则删除
// @Accept json
// @Produce json
// @Param body body model.AddressBookCollectionRule true "address book rule info"
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/address_book_collection_rule/delete [post]
+17 -17
View File
@@ -13,15 +13,15 @@ import (
type LoginLog struct {
}
// List list
// @Tags my login logs
// @Summary login log list
// @Description login log list
// List 列表
// @Tags 我的登录日志
// @Summary 登录日志列表
// @Description 登录日志列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param user_id query int false "userID"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param user_id query int false "用户ID"
// @Success 200 {object} response.Response{data=model.LoginLogList}
// @Failure 500 {object} response.Response
// @Router /admin/my/login_log/list [get]
@@ -40,13 +40,13 @@ func (ct *LoginLog) List(c *gin.Context) {
response.Success(c, res)
}
// Delete delete
// @Tags my login logs
// @Summary delete login log
// @Description delete login log
// Delete 删除
// @Tags 我的登录日志
// @Summary 登录日志删除
// @Description 登录日志删除
// @Accept json
// @Produce json
// @Param body body model.LoginLog true "login log info"
// @Param body body model.LoginLog true "登录日志信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/login_log/delete [post]
@@ -81,13 +81,13 @@ func (ct *LoginLog) Delete(c *gin.Context) {
response.Fail(c, 101, err.Error())
}
// BatchDelete delete
// @Tags my login logs
// @Summary batch delete login logs
// @Description batch delete login logs
// BatchDelete 删除
// @Tags 我的登录日志
// @Summary 登录日志批量删除
// @Description 登录日志批量删除
// @Accept json
// @Produce json
// @Param body body admin.LoginLogIds true "login log"
// @Param body body admin.LoginLogIds true "登录日志"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/login_log/batchDelete [post]
+9 -9
View File
@@ -12,18 +12,18 @@ import (
type Peer struct {
}
// List list
// @Tags my devices
// @Summary device list
// @Description device list
// List 列表
// @Tags 我的设备
// @Summary 设备列表
// @Description 设备列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param time_ago query int false "time"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param time_ago query int false "时间"
// @Param id query string false "ID"
// @Param hostname query string false "hostname"
// @Param uuids query string false "uuids separated by commas"
// @Param hostname query string false "主机名"
// @Param uuids query string false "uuids 用逗号分隔"
// @Success 200 {object} response.Response{data=model.PeerList}
// @Failure 500 {object} response.Response
// @Router /admin/my/peer/list [get]
+15 -15
View File
@@ -12,14 +12,14 @@ import (
type ShareRecord struct {
}
// List share record list
// @Tags my share records
// @Summary share record list
// @Description share record list
// List 分享记录列表
// @Tags 我的分享记录
// @Summary 分享记录列表
// @Description 分享记录列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/share_record/list [get]
@@ -37,13 +37,13 @@ func (sr *ShareRecord) List(c *gin.Context) {
response.Success(c, res)
}
// Delete delete share record
// @Tags my share records
// @Summary delete share record
// @Description delete share record
// Delete 分享记录删除
// @Tags 我的分享记录
// @Summary 分享记录删除
// @Description 分享记录删除
// @Accept json
// @Produce json
// @Param body body admin.ShareRecordForm true "share record info"
// @Param body body admin.ShareRecordForm true "分享记录信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/share_record/delete [post]
@@ -78,10 +78,10 @@ func (sr *ShareRecord) Delete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
}
// BatchDelete batch delete my share records
// @Tags my
// @Summary batch delete my share records
// @Description batch delete my share records
// BatchDelete 批量删除我的分享记录
// @Tags 我的
// @Summary 批量删除我的分享记录
// @Description 批量删除我的分享记录
// @Accept json
// @Produce json
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
+23 -23
View File
@@ -11,16 +11,16 @@ import (
type Tag struct{}
// List list
// @Tags my tags
// @Summary tag list
// @Description tag list
// List 列表
// @Tags 我的标签
// @Summary 标签列表
// @Description 标签列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param is_my query int false "whether it is mine"
// @Param user_id query int false "userid"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param is_my query int false "是否是我的"
// @Param user_id query int false "用户id"
// @Success 200 {object} response.Response{data=model.TagList}
// @Failure 500 {object} response.Response
// @Router /admin/my/tag/list [get]
@@ -45,13 +45,13 @@ func (ct *Tag) List(c *gin.Context) {
response.Success(c, res)
}
// Create create tag
// @Tags my tags
// @Summary create tag
// @Description create tag
// Create 创建标签
// @Tags 我的标签
// @Summary 创建标签
// @Description 创建标签
// @Accept json
// @Produce json
// @Param body body admin.TagForm true "tag info"
// @Param body body admin.TagForm true "标签信息"
// @Success 200 {object} response.Response{data=model.Tag}
// @Failure 500 {object} response.Response
// @Router /admin/my/tag/create [post]
@@ -78,13 +78,13 @@ func (ct *Tag) Create(c *gin.Context) {
response.Success(c, nil)
}
// Update edit
// @Tags my tags
// @Summary edit tag
// @Description edit tag
// Update 编辑
// @Tags 我的标签
// @Summary 标签编辑
// @Description 标签编辑
// @Accept json
// @Produce json
// @Param body body admin.TagForm true "tag info"
// @Param body body admin.TagForm true "标签信息"
// @Success 200 {object} response.Response{data=model.Tag}
// @Failure 500 {object} response.Response
// @Router /admin/my/tag/update [post]
@@ -133,13 +133,13 @@ func (ct *Tag) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags tag
// @Summary delete tag
// @Description delete tag
// Delete 删除
// @Tags 标签
// @Summary 标签删除
// @Description 标签删除
// @Accept json
// @Produce json
// @Param body body admin.TagForm true "tag info"
// @Param body body admin.TagForm true "标签信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/tag/delete [post]
+21 -21
View File
@@ -44,7 +44,7 @@ func (o *Oauth) ToBind(c *gin.Context) {
return
}
err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(f.Op)
err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(c, f.Op)
if err != nil {
response.Error(c, response.TranslateMsg(c, err.Error()))
return
@@ -64,7 +64,7 @@ func (o *Oauth) ToBind(c *gin.Context) {
})
}
// Confirm confirm authorized login
// Confirm 确认授权登录
func (o *Oauth) Confirm(c *gin.Context) {
j := &adminReq.OauthConfirmForm{}
err := c.ShouldBindJSON(j)
@@ -140,8 +140,8 @@ func (o *Oauth) Unbind(c *gin.Context) {
// Detail Oauth
// @Tags Oauth
// @Summary Oauthdetails
// @Description Oauthdetails
// @Summary Oauth详情
// @Description Oauth详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -161,13 +161,13 @@ func (o *Oauth) Detail(c *gin.Context) {
return
}
// Create createOauth
// Create 创建Oauth
// @Tags Oauth
// @Summary createOauth
// @Description createOauth
// @Summary 创建Oauth
// @Description 创建Oauth
// @Accept json
// @Produce json
// @Param body body admin.OauthForm true "Oauthinfo"
// @Param body body admin.OauthForm true "Oauth信息"
// @Success 200 {object} response.Response{data=model.Oauth}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/create [post]
@@ -202,14 +202,14 @@ func (o *Oauth) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// List 列表
// @Tags Oauth
// @Summary Oauthlist
// @Description Oauthlist
// @Summary Oauth列表
// @Description Oauth列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response{data=model.OauthList}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/list [get]
@@ -224,13 +224,13 @@ func (o *Oauth) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// Update 编辑
// @Tags Oauth
// @Summary Oauthedit
// @Description Oauthedit
// @Summary Oauth编辑
// @Description Oauth编辑
// @Accept json
// @Produce json
// @Param body body admin.OauthForm true "Oauthinfo"
// @Param body body admin.OauthForm true "Oauth信息"
// @Success 200 {object} response.Response{data=model.OauthList}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/update [post]
@@ -259,13 +259,13 @@ func (o *Oauth) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// Delete 删除
// @Tags Oauth
// @Summary Oauthdelete
// @Description Oauthdelete
// @Summary Oauth删除
// @Description Oauth删除
// @Accept json
// @Produce json
// @Param body body admin.OauthForm true "Oauthinfo"
// @Param body body admin.OauthForm true "Oauth信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/oauth/delete [post]
+34 -37
View File
@@ -14,10 +14,10 @@ import (
type Peer struct {
}
// Detail device
// @Tags device
// @Summary device details
// @Description device details
// Detail 设备
// @Tags 设备
// @Summary 设备详情
// @Description 设备详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -37,13 +37,13 @@ func (ct *Peer) Detail(c *gin.Context) {
return
}
// Create create device
// @Tags device
// @Summary create device
// @Description create device
// Create 创建设备
// @Tags 设备
// @Summary 创建设备
// @Description 创建设备
// @Accept json
// @Produce json
// @Param body body admin.PeerForm true "device info"
// @Param body body admin.PeerForm true "设备信息"
// @Success 200 {object} response.Response{data=model.Peer}
// @Failure 500 {object} response.Response
// @Router /admin/peer/create [post]
@@ -68,18 +68,18 @@ func (ct *Peer) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags device
// @Summary device list
// @Description device list
// List 列表
// @Tags 设备
// @Summary 设备列表
// @Description 设备列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param time_ago query int false "time"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param time_ago query int false "时间"
// @Param id query string false "ID"
// @Param hostname query string false "hostname"
// @Param uuids query string false "uuids separated by commas"
// @Param hostname query string false "主机名"
// @Param uuids query string false "uuids 用逗号分隔"
// @Success 200 {object} response.Response{data=model.PeerList}
// @Failure 500 {object} response.Response
// @Router /admin/peer/list [get]
@@ -114,20 +114,17 @@ func (ct *Peer) List(c *gin.Context) {
if query.Ip != "" {
tx.Where("last_online_ip like ?", "%"+query.Ip+"%")
}
if query.Alias != "" {
tx.Where("alias like ?", "%"+query.Alias+"%")
}
})
response.Success(c, res)
}
// Update edit
// @Tags device
// @Summary edit device
// @Description edit device
// Update 编辑
// @Tags 设备
// @Summary 设备编辑
// @Description 设备编辑
// @Accept json
// @Produce json
// @Param body body admin.PeerForm true "device info"
// @Param body body admin.PeerForm true "设备信息"
// @Success 200 {object} response.Response{data=model.Peer}
// @Failure 500 {object} response.Response
// @Router /admin/peer/update [post]
@@ -156,13 +153,13 @@ func (ct *Peer) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags device
// @Summary delete device
// @Description delete device
// Delete 删除
// @Tags 设备
// @Summary 设备删除
// @Description 设备删除
// @Accept json
// @Produce json
// @Param body body admin.PeerForm true "device info"
// @Param body body admin.PeerForm true "设备信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/peer/delete [post]
@@ -192,13 +189,13 @@ func (ct *Peer) Delete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchDelete batch delete
// @Tags device
// @Summary batch delete devices
// @Description batch delete devices
// BatchDelete 批量删除
// @Tags 设备
// @Summary 批量设备删除
// @Description 批量设备删除
// @Accept json
// @Produce json
// @Param body body admin.PeerBatchDeleteForm true "deviceid"
// @Param body body admin.PeerBatchDeleteForm true "设备id"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/peer/batchDelete [post]
@@ -232,7 +229,7 @@ func (ct *Peer) SimpleData(c *gin.Context) {
return
}
res := service.AllService.PeerService.List(1, 99999, func(tx *gorm.DB) {
//information that can be made public
//可以公开的情报
tx.Select("id,version")
tx.Where("id in (?)", f.Ids)
})
+1 -1
View File
@@ -25,7 +25,7 @@ func (r *Rustdesk) CmdList(c *gin.Context) {
return
}
res := service.AllService.ServerCmdService.List(q.Page, 9999)
//add system commands before the list
//在列表前添加系统命令
list := make([]*model.ServerCmd, 0)
list = append(list, model.SysIdServerCmds...)
list = append(list, model.SysRelayServerCmds...)
+16 -16
View File
@@ -12,15 +12,15 @@ import (
type ShareRecord struct {
}
// List list
// @Tags share record
// @Summary share record list
// @Description share record list
// List 列表
// @Tags 分享记录
// @Summary 分享记录列表
// @Description 分享记录列表
// @Accept json
// @Produce json
// @Param user_id query int false "userID"
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param user_id query int false "用户ID"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/share_record/list [get]
@@ -39,13 +39,13 @@ func (sr *ShareRecord) List(c *gin.Context) {
response.Success(c, res)
}
// Delete delete
// @Tags share record
// @Summary delete share record
// @Description delete share record
// Delete 删除
// @Tags 分享记录
// @Summary 分享记录删除
// @Description 分享记录删除
// @Accept json
// @Produce json
// @Param body body admin.ShareRecordForm true "share record info"
// @Param body body admin.ShareRecordForm true "分享记录信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/share_record/delete [post]
@@ -75,10 +75,10 @@ func (sr *ShareRecord) Delete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchDelete batch delete
// @Tags share record
// @Summary batch share records
// @Description batch share records
// BatchDelete 批量删除
// @Tags 分享记录
// @Summary 批量分享记录
// @Description 批量分享记录
// @Accept json
// @Produce json
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
+27 -27
View File
@@ -13,10 +13,10 @@ import (
type Tag struct {
}
// Detail tag
// @Tags tag
// @Summary tag details
// @Description tag details
// Detail 标签
// @Tags 标签
// @Summary 标签详情
// @Description 标签详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -41,13 +41,13 @@ func (ct *Tag) Detail(c *gin.Context) {
return
}
// Create create tag
// @Tags tag
// @Summary create tag
// @Description create tag
// Create 创建标签
// @Tags 标签
// @Summary 创建标签
// @Description 创建标签
// @Accept json
// @Produce json
// @Param body body admin.TagForm true "tag info"
// @Param body body admin.TagForm true "标签信息"
// @Success 200 {object} response.Response{data=model.Tag}
// @Failure 500 {object} response.Response
// @Router /admin/tag/create [post]
@@ -76,16 +76,16 @@ func (ct *Tag) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags tag
// @Summary tag list
// @Description tag list
// List 列表
// @Tags 标签
// @Summary 标签列表
// @Description 标签列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param is_my query int false "whether it is mine"
// @Param user_id query int false "userid"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param is_my query int false "是否是我的"
// @Param user_id query int false "用户id"
// @Success 200 {object} response.Response{data=model.TagList}
// @Failure 500 {object} response.Response
// @Router /admin/tag/list [get]
@@ -110,13 +110,13 @@ func (ct *Tag) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags tag
// @Summary edit tag
// @Description edit tag
// Update 编辑
// @Tags 标签
// @Summary 标签编辑
// @Description 标签编辑
// @Accept json
// @Produce json
// @Param body body admin.TagForm true "tag info"
// @Param body body admin.TagForm true "标签信息"
// @Success 200 {object} response.Response{data=model.Tag}
// @Failure 500 {object} response.Response
// @Router /admin/tag/update [post]
@@ -150,13 +150,13 @@ func (ct *Tag) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags tag
// @Summary delete tag
// @Description delete tag
// Delete 删除
// @Tags 标签
// @Summary 标签删除
// @Description 标签删除
// @Accept json
// @Produce json
// @Param body body admin.TagForm true "tag info"
// @Param body body admin.TagForm true "标签信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/tag/delete [post]
+46 -46
View File
@@ -16,10 +16,10 @@ import (
type User struct {
}
// Detail administrator
// @Tags user
// @Summary administrator details
// @Description administrator details
// Detail 管理员
// @Tags 用户
// @Summary 管理员详情
// @Description 管理员详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -39,13 +39,13 @@ func (ct *User) Detail(c *gin.Context) {
return
}
// Create administrator
// @Tags user
// @Summary create administrator
// @Description create administrator
// Create 管理员
// @Tags 用户
// @Summary 创建管理员
// @Description 创建管理员
// @Accept json
// @Produce json
// @Param body body admin.UserForm true "administrator info"
// @Param body body admin.UserForm true "管理员信息"
// @Success 200 {object} response.Response{data=model.User}
// @Failure 500 {object} response.Response
// @Router /admin/user/create [post]
@@ -70,15 +70,15 @@ func (ct *User) Create(c *gin.Context) {
response.Success(c, nil)
}
// List list
// @Tags user
// @Summary administrator list
// @Description administrator list
// List 列表
// @Tags 用户
// @Summary 管理员列表
// @Description 管理员列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param username query int false "account"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param username query int false "账户"
// @Success 200 {object} response.Response{data=model.UserList}
// @Failure 500 {object} response.Response
// @Router /admin/user/list [get]
@@ -97,13 +97,13 @@ func (ct *User) List(c *gin.Context) {
response.Success(c, res)
}
// Update edit
// @Tags user
// @Summary edit administrator
// @Description edit administrator
// Update 编辑
// @Tags 用户
// @Summary 管理员编辑
// @Description 管理员编辑
// @Accept json
// @Produce json
// @Param body body admin.UserForm true "user info"
// @Param body body admin.UserForm true "用户信息"
// @Success 200 {object} response.Response{data=model.User}
// @Failure 500 {object} response.Response
// @Router /admin/user/update [post]
@@ -132,13 +132,13 @@ func (ct *User) Update(c *gin.Context) {
response.Success(c, nil)
}
// Delete delete
// @Tags user
// @Summary delete administrator
// @Description delete administrator
// Delete 删除
// @Tags 用户
// @Summary 管理员删除
// @Description 管理员编删除
// @Accept json
// @Produce json
// @Param body body admin.UserForm true "user info"
// @Param body body admin.UserForm true "用户信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/user/delete [post]
@@ -168,13 +168,13 @@ func (ct *User) Delete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// UpdatePassword change password
// @Tags user
// @Summary change password
// @Description change password
// UpdatePassword 修改密码
// @Tags 用户
// @Summary 修改密码
// @Description 修改密码
// @Accept json
// @Produce json
// @Param body body admin.UserPasswordForm true "user info"
// @Param body body admin.UserPasswordForm true "用户信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/user/updatePassword [post]
@@ -203,10 +203,10 @@ func (ct *User) UpdatePassword(c *gin.Context) {
response.Success(c, nil)
}
// Current current user
// @Tags user
// @Summary current user
// @Description current user
// Current 当前用户
// @Tags 用户
// @Summary 当前用户
// @Description 当前用户
// @Accept json
// @Produce json
// @Success 200 {object} response.Response{data=adResp.LoginPayload}
@@ -220,13 +220,13 @@ func (ct *User) Current(c *gin.Context) {
responseLoginSuccess(c, u, t)
}
// ChangeCurPwd change the current user's password
// @Tags user
// @Summary change the current user's password
// @Description change the current user's password
// ChangeCurPwd 修改当前用户密码
// @Tags 用户
// @Summary 修改当前用户密码
// @Description 修改当前用户密码
// @Accept json
// @Produce json
// @Param body body admin.ChangeCurPasswordForm true "user info"
// @Param body body admin.ChangeCurPasswordForm true "用户信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/user/changeCurPwd [post]
@@ -261,9 +261,9 @@ func (ct *User) ChangeCurPwd(c *gin.Context) {
}
// MyOauth
// @Tags user
// @Summary my authorizations
// @Description my authorizations
// @Tags 用户
// @Summary 我的授权
// @Description 我的授权
// @Accept json
// @Produce json
// @Success 200 {object} response.Response{data=[]adResp.UserOauthItem}
@@ -321,7 +321,7 @@ func (ct *User) Register(c *gin.Context) {
return
}
regStatus := model.StatusCode(global.Config.App.RegisterStatus)
// the registration status may not be configured; enabled by default
// 注册状态可能未配置,默认启用
if regStatus != model.COMMON_STATUS_DISABLED && regStatus != model.COMMON_STATUS_ENABLE {
regStatus = model.COMMON_STATUS_ENABLE
}
@@ -332,11 +332,11 @@ func (ct *User) Register(c *gin.Context) {
return
}
if regStatus == model.COMMON_STATUS_DISABLED {
// requires administrator approval
// 需要管理员审核
response.Fail(c, 101, response.TranslateMsg(c, "RegisterSuccessWaitAdminConfirm"))
return
}
// automatically log in after successful registration
// 注册成功后自动登录
ut := service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
Client: model.LoginLogClientWebAdmin,
+17 -17
View File
@@ -13,15 +13,15 @@ import (
type UserToken struct {
}
// List list
// @Tags login credential
// @Summary login credential list
// @Description login credential list
// List 列表
// @Tags 登录凭证
// @Summary 登录凭证列表
// @Description 登录凭证列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param page_size query int false "page size"
// @Param user_id query int false "userID"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param user_id query int false "用户ID"
// @Success 200 {object} response.Response{data=model.UserTokenList}
// @Failure 500 {object} response.Response
// @Router /admin/user_token/list [get]
@@ -41,13 +41,13 @@ func (ct *UserToken) List(c *gin.Context) {
response.Success(c, res)
}
// Delete delete
// @Tags login credential
// @Summary delete login credential
// @Description delete login credential
// Delete 删除
// @Tags 登录凭证
// @Summary 登录凭证删除
// @Description 登录凭证删除
// @Accept json
// @Produce json
// @Param body body model.UserToken true "login credential info"
// @Param body body model.UserToken true "登录凭证信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/user_token/delete [post]
@@ -82,13 +82,13 @@ func (ct *UserToken) Delete(c *gin.Context) {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchDelete batch delete
// @Tags login credential
// @Summary batch delete login credentials
// @Description batch delete login credentials
// BatchDelete 批量删除
// @Tags 登录凭证
// @Summary 登录凭证批量删除
// @Description 登录凭证批量删除
// @Accept json
// @Produce json
// @Param body body admin.UserTokenBatchDeleteForm true "login credential info"
// @Param body body admin.UserTokenBatchDeleteForm true "登录凭证信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/user_token/batchDelete [post]
+58 -58
View File
@@ -20,9 +20,9 @@ type Ab struct {
}
// Ab
// @Tags address
// @Summary address list
// @Description address list
// @Tags 地址
// @Summary 地址列表
// @Description 地址列表
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -36,7 +36,7 @@ func (a *Ab) Ab(c *gin.Context) {
tags := service.AllService.TagService.ListByUserIdAndCollectionId(user.Id, 0)
tagColors := map[string]uint{}
// convert the name in tags into a comma-separated string
//将tags中的name转成一个以逗号分割的字符串
var tagNames []string
for _, tag := range tags.Tags {
tagNames = append(tagNames, tag.Name)
@@ -56,12 +56,12 @@ func (a *Ab) Ab(c *gin.Context) {
}
// UpAb
// @Tags address
// @Summary address update
// @Description address update
// @Tags 地址
// @Summary 地址更新
// @Description 地址更新
// @Accept json
// @Produce json
// @Param body body requstform.AddressBookForm true "address form"
// @Param body body requstform.AddressBookForm true "地址表单"
// @Success 200 {string} string "null"
// @Failure 500 {object} response.ErrorResponse
// @Router /ab [post]
@@ -99,9 +99,9 @@ func (a *Ab) UpAb(c *gin.Context) {
}
// PTags
// @Tags address[Personal]
// @Summary tag
// @Description tag
// @Tags 地址[Personal]
// @Summary 标签
// @Description 标签
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -128,9 +128,9 @@ func (a *Ab) PTags(c *gin.Context) {
}
// TagAdd
// @Tags address[Personal]
// @Summary add tag
// @Description tag
// @Tags 地址[Personal]
// @Summary 标签添加
// @Description 标签
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -177,9 +177,9 @@ func (a *Ab) TagAdd(c *gin.Context) {
}
// TagRename
// @Tags address[Personal]
// @Summary rename tag
// @Description tag
// @Tags 地址[Personal]
// @Summary 标签重命名
// @Description 标签
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -229,9 +229,9 @@ func (a *Ab) TagRename(c *gin.Context) {
}
// TagUpdate
// @Tags address[Personal]
// @Summary change tag color
// @Description tag
// @Tags 地址[Personal]
// @Summary 标签修改颜色
// @Description 标签
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -275,9 +275,9 @@ func (a *Ab) TagUpdate(c *gin.Context) {
}
// TagDel
// @Tags address[Personal]
// @Summary delete tag
// @Description tag
// @Tags 地址[Personal]
// @Summary 标签删除
// @Description 标签
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -324,9 +324,9 @@ func (a *Ab) TagDel(c *gin.Context) {
}
// Personal
// @Tags address[Personal]
// @Summary personal address
// @Description personal address
// @Tags 地址[Personal]
// @Summary 个人地址
// @Description 个人地址
// @Accept json
// @Produce json
// @Param string body string false "string valid"
@@ -345,7 +345,7 @@ func (a *Ab) Personal(c *gin.Context) {
*/
if global.Config.Rustdesk.Personal == 1 {
guid := a.ComposeGuid(user.GroupId, user.Id, 0)
//if it returns guid, subsequent requests will change
//如果返回了guid,后面的请求会有变化
c.JSON(http.StatusOK, gin.H{
"guid": guid,
"name": user.Username,
@@ -358,9 +358,9 @@ func (a *Ab) Personal(c *gin.Context) {
}
// Settings
// @Tags address[Personal]
// @Summary settings
// @Description settings
// @Tags 地址[Personal]
// @Summary 设置
// @Description 设置
// @Accept json
// @Produce json
// @Param string body string false "string valid"
@@ -370,18 +370,18 @@ func (a *Ab) Personal(c *gin.Context) {
// @Security BearerAuth
func (a *Ab) Settings(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"max_peer_one_ab": 0, //max peer count, 0 means no limit
"max_peer_one_ab": 0, //最大peer数,0表示不限制
})
}
// SharedProfiles
// @Tags address[Personal]
// @Summary shared address book
// @Description shared
// @Tags 地址[Personal]
// @Summary 共享地址簿
// @Description 共享
// @Accept json
// @Produce json
// @Param current query int false "page number"
// @Param pageSize query int false "items per page"
// @Param current query int false "页码"
// @Param pageSize query int false "每页数量"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /ab/shared/profiles [post]
@@ -401,14 +401,14 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
})
}
allAbIds := make(map[uint]int) //use map to deduplicate and keep the maximum Rule
allAbIds := make(map[uint]int) //用map去重,并保留最大Rule
allUserIds := make(map[uint]*model.User)
rules := service.AllService.AddressBookService.CollectionReadRules(user)
for _, rule := range rules {
//first check whether it exists
//先判断是否存在
r, ok := allAbIds[rule.CollectionId]
if ok {
//then check the permission level
//再判断权限大小
if r < rule.Rule {
allAbIds[rule.CollectionId] = rule.Rule
}
@@ -448,7 +448,7 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
// ParseGuid
func (a *Ab) ParseGuid(guid string) (gid, uid, cid uint) {
// split guid by -
//用-切割 guid
guids := strings.Split(guid, "-")
if len(guids) < 2 {
return 0, 0, 0
@@ -521,13 +521,13 @@ func (a *Ab) CheckGuid(cu *model.User, guid string) (gid, uid, cid uint, err err
}
// Peers
// @Tags address[Personal]
// @Summary address list
// @Description address
// @Tags 地址[Personal]
// @Summary 地址列表
// @Description 地址
// @Accept json
// @Produce json
// @Param current query int false "page number"
// @Param pageSize query int false "items per page"
// @Param current query int false "页码"
// @Param pageSize query int false "每页数量"
// @Param ab query string false "guid"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
@@ -557,9 +557,9 @@ func (a *Ab) Peers(c *gin.Context) {
}
// PeerAdd
// @Tags address[Personal]
// @Summary add address
// @Description add address
// @Tags 地址[Personal]
// @Summary 添加地址
// @Description 添加地址
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -568,7 +568,7 @@ func (a *Ab) Peers(c *gin.Context) {
// @Router /ab/peer/add/{guid} [post]
// @Security BearerAuth
func (a *Ab) PeerAdd(c *gin.Context) {
// forceAlwaysRelay is always the string "false"
// forceAlwaysRelay永远是字符串"false"
//f := &gin.H{}
f := &requstform.PersonalAddressBookForm{}
err := c.ShouldBindJSON(f)
@@ -613,9 +613,9 @@ func (a *Ab) PeerAdd(c *gin.Context) {
}
// PeerDel
// @Tags address[Personal]
// @Summary delete address
// @Description delete address
// @Tags 地址[Personal]
// @Summary 删除地址
// @Description 删除地址
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -661,9 +661,9 @@ func (a *Ab) PeerDel(c *gin.Context) {
}
// PeerUpdate
// @Tags address[Personal]
// @Summary update address
// @Description update address
// @Tags 地址[Personal]
// @Summary 更新地址
// @Description 更新地址
// @Accept json
// @Produce json
// @Param guid path string true "guid"
@@ -693,7 +693,7 @@ func (a *Ab) PeerUpdate(c *gin.Context) {
return
}
//fmt.Println(f)
// determine whether f["Id"] exists
//判断f["Id"]是否存在
fid, ok := f["id"]
if !ok {
response.Error(c, response.TranslateMsg(c, "ParamsError"))
@@ -706,9 +706,9 @@ func (a *Ab) PeerUpdate(c *gin.Context) {
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
return
}
//allowed fields
//允许的字段
allowUp := []string{"password", "hash", "tags", "alias"}
// if a field in f is not in allowUp, delete it
//f中的字段如果不在allowUp中,就删除
for k := range f {
if !utils.InArray(k, allowUp) {
delete(f, k)
+8 -8
View File
@@ -14,12 +14,12 @@ type Audit struct {
}
// AuditConn
// @Tags audit
// @Summary audit connection
// @Description audit connection
// @Tags 审计
// @Summary 审计连接
// @Description 审计连接
// @Accept json
// @Produce json
// @Param body body request.AuditConnForm true "audit connection"
// @Param body body request.AuditConnForm true "审计连接"
// @Success 200 {string} string ""
// @Failure 500 {object} response.Response
// @Router /audit/conn [post]
@@ -59,12 +59,12 @@ func (a *Audit) AuditConn(c *gin.Context) {
}
// AuditFile
// @Tags audit
// @Summary audit file
// @Description audit file
// @Tags 审计
// @Summary 审计文件
// @Description 审计文件
// @Accept json
// @Produce json
// @Param body body request.AuditFileForm true "audit file"
// @Param body body request.AuditFileForm true "审计文件"
// @Success 200 {string} string ""
// @Failure 500 {object} response.Response
// @Router /audit/file [post]
+21 -21
View File
@@ -13,15 +13,15 @@ import (
type Group struct {
}
// Users user list
// @Tags group
// @Summary user list
// @Description user list
// Users 用户列表
// @Tags 群组
// @Summary 用户列表
// @Description 用户列表
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param status query int false "status"
// @Param page query int false "页码"
// @Param pageSize query int false "每页数量"
// @Param status query int false "状态"
// @Param accessible query string false "accessible"
// @Success 200 {object} response.DataResponse{data=[]apiResp.UserPayload}
// @Failure 500 {object} response.ErrorResponse
@@ -38,7 +38,7 @@ func (g *Group) Users(c *gin.Context) {
gr := service.AllService.GroupService.InfoById(u.GroupId)
userList := &model.UserList{}
if !*u.IsAdmin && gr.Type != model.GroupTypeShare {
//can only retrieve one's own
//仅能获取到自己
userList.Users = append(userList.Users, u)
userList.Total = 1
} else {
@@ -58,14 +58,14 @@ func (g *Group) Users(c *gin.Context) {
}
// Peers
// @Tags group
// @Summary machine
// @Description machine
// @Tags 群组
// @Summary 机器
// @Description 机器
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param status query int false "status"
// @Param page query int false "页码"
// @Param pageSize query int false "每页数量"
// @Param status query int false "状态"
// @Param accessible query string false "accessible"
// @Success 200 {object} response.DataResponse
// @Failure 500 {object} response.Response
@@ -82,7 +82,7 @@ func (g *Group) Peers(c *gin.Context) {
gr := service.AllService.GroupService.InfoById(u.GroupId)
users := make([]*model.User, 0, 1)
if !*u.IsAdmin && gr.Type != model.GroupTypeShare {
//can only retrieve one's own
//仅能获取到自己
users = append(users, u)
} else {
users = service.AllService.UserService.ListIdAndNameByGroupId(u.GroupId)
@@ -122,14 +122,14 @@ func (g *Group) Peers(c *gin.Context) {
}
// Device
// @Tags group
// @Summary device
// @Description machine
// @Tags 群组
// @Summary 设备
// @Description 机器
// @Accept json
// @Produce json
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param status query int false "status"
// @Param page query int false "页码"
// @Param pageSize query int false "每页数量"
// @Param status query int false "状态"
// @Param accessible query string false "accessible"
// @Success 200 {object} response.DataResponse
// @Failure 500 {object} response.Response
+15 -15
View File
@@ -13,10 +13,10 @@ import (
type Index struct {
}
// Index home
// @Tags home
// @Summary home
// @Description home
// Index 首页
// @Tags 首页
// @Summary 首页
// @Description 首页
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -29,10 +29,10 @@ func (i *Index) Index(c *gin.Context) {
)
}
// Heartbeat heartbeat
// @Tags home
// @Summary heartbeat
// @Description heartbeat
// Heartbeat 心跳
// @Tags 首页
// @Summary 心跳
// @Description 心跳
// @Accept json
// @Produce json
// @Success 200 {object} nil
@@ -49,12 +49,12 @@ func (i *Index) Heartbeat(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
return
}
peer := service.AllService.PeerService.FindById(info.Id)
peer := service.AllService.PeerService.FindByUuid(info.Uuid)
if peer == nil || peer.RowId == 0 {
c.JSON(http.StatusOK, gin.H{})
return
}
// do not update if within 40s
//如果在40s以内则不更新
if time.Now().Unix()-peer.LastOnlineTime >= 30 {
upp := &model.Peer{RowId: peer.RowId, LastOnlineTime: time.Now().Unix(), LastOnlineIp: c.ClientIP()}
service.AllService.PeerService.Update(upp)
@@ -62,17 +62,17 @@ func (i *Index) Heartbeat(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
}
// Version version
// @Tags home
// @Summary version
// @Description version
// Version 版本
// @Tags 首页
// @Summary 版本
// @Description 版本
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /version [get]
func (i *Index) Version(c *gin.Context) {
// read the resources/version file
//读取resources/version文件
v := service.AllService.AppService.GetAppVersion()
response.Success(
c,
+13 -13
View File
@@ -16,13 +16,13 @@ import (
type Login struct {
}
// Login login
// @Tags login
// @Summary login
// @Description login
// Login 登录
// @Tags 登录
// @Summary 登录
// @Description 登录
// @Accept json
// @Produce json
// @Param body body api.LoginForm true "login form"
// @Param body body api.LoginForm true "登录表单"
// @Success 200 {object} apiResp.LoginRes
// @Failure 500 {object} response.ErrorResponse
// @Router /login [post]
@@ -32,7 +32,7 @@ func (l *Login) Login(c *gin.Context) {
return
}
// check login limit
// 检查登录限制
loginLimiter := global.LoginLimiter
clientIp := c.ClientIP()
@@ -68,7 +68,7 @@ func (l *Login) Login(c *gin.Context) {
return
}
// determine whether it is webclient or app based on refer
//根据refer判断是webclient还是app
ref := c.GetHeader("referer")
if ref != "" {
f.DeviceInfo.Type = model.LoginLogClientWeb
@@ -92,9 +92,9 @@ func (l *Login) Login(c *gin.Context) {
}
// LoginOptions
// @Tags login
// @Summary login options
// @Description login options
// @Tags 登录
// @Summary 登录选项
// @Description 登录选项
// @Accept json
// @Produce json
// @Success 200 {object} []string
@@ -123,9 +123,9 @@ func (l *Login) LoginOptions(c *gin.Context) {
}
// Logout
// @Tags login
// @Summary logout
// @Description logout
// @Tags 登录
// @Summary 登出
// @Description 登出
// @Accept json
// @Produce json
// @Success 200 {string} string
+22 -23
View File
@@ -36,7 +36,7 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
oauthService := service.AllService.OauthService
err, state, verifier, nonce, url := oauthService.BeginAuth(f.Op)
err, state, verifier, nonce, url := oauthService.BeginAuth(c, f.Op)
if err != nil {
response.Error(c, response.TranslateMsg(c, err.Error()))
return
@@ -65,37 +65,36 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
var ut *model.UserToken
q := &api.OidcAuthQuery{}
// parse query parameters and handle errors
// 解析查询参数并处理错误
if err := c.ShouldBindQuery(q); err != nil {
response.Error(c, response.TranslateMsg(c, "ParamsError")+": "+err.Error())
return nil, nil
}
// get OAuth cache
// 获取 OAuth 缓存
v := service.AllService.OauthService.GetOauthCache(q.Code)
if v == nil {
response.Error(c, response.TranslateMsg(c, "OauthExpired"))
return nil, nil
}
// if UserId is 0, authorization is still in progress
// 如果 UserId 为 0,说明还在授权中
if v.UserId == 0 {
//fix: 1.4.2 webclient oidc
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind", "error": "No authed oidc is found"})
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind"})
return nil, nil
}
// get user info
// 获取用户信息
u = service.AllService.UserService.InfoById(v.UserId)
if u == nil {
response.Error(c, response.TranslateMsg(c, "UserNotFound"))
return nil, nil
}
// delete OAuth cache
// 删除 OAuth 缓存
service.AllService.OauthService.DeleteOauthCache(q.Code)
// create a login log and generate a user token
// 创建登录日志并生成用户令牌
ut = service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
Client: v.DeviceType,
@@ -111,7 +110,7 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
return nil, nil
}
// return user token
// 返回用户令牌
return u, ut
}
@@ -136,7 +135,7 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
})
}
// OauthCallback callback
// OauthCallback 回调
// @Tags Oauth
// @Summary OauthCallback
// @Description OauthCallback
@@ -144,7 +143,7 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
// @Produce json
// @Success 200 {object} apiResp.LoginRes
// @Failure 500 {object} response.ErrorResponse
// @Router /oidc/callback [get]
// @Router /oauth/callback [get]
func (o *Oauth) OauthCallback(c *gin.Context) {
state := c.Query("state")
if state == "" {
@@ -156,7 +155,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
}
cacheKey := state
oauthService := service.AllService.OauthService
//get from cache
//从缓存中获取
oauthCache := oauthService.GetOauthCache(cacheKey)
if oauthCache == nil {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
@@ -169,9 +168,9 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
action := oauthCache.Action
verifier := oauthCache.Verifier
var user *model.User
// get user info
// 获取用户信息
code := c.Query("code")
err, oauthUser := oauthService.Callback(code, verifier, op, nonce)
err, oauthUser := oauthService.Callback(c, code, verifier, op, nonce)
if err != nil {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
"message": "OauthFailed",
@@ -184,7 +183,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
if action == service.OauthActionTypeBind {
//fmt.Println("bind", ty, userData)
// check whether this openid has already been bound
// 检查此openid是否已经绑定过
utr := oauthService.UserThirdInfo(op, openid)
if utr.UserId > 0 {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
@@ -192,7 +191,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
})
return
}
//bind
//绑定
user = service.AllService.UserService.InfoById(userId)
if user == nil {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
@@ -200,7 +199,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
})
return
}
//bind
//绑定
err := oauthService.BindOauthUser(userId, oauthUser, op)
if err != nil {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
@@ -214,7 +213,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
return
} else if action == service.OauthActionTypeLogin {
//login
//登录
if userId != 0 {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
"message": "OauthHasBeenSuccess",
@@ -225,13 +224,13 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
if user == nil {
oauthConfig := oauthService.InfoByOp(op)
if !*oauthConfig.AutoRegister {
//c.String(http.StatusInternalServerError, "not yet bound to a user, please bind first")
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
oauthCache.UpdateFromOauthUser(oauthUser)
c.Redirect(http.StatusFound, "/_admin/#/oauth/bind/"+cacheKey)
return
}
//auto register
//自动注册
err, user = service.AllService.UserService.RegisterByOauth(oauthUser, op)
if err != nil {
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
@@ -242,7 +241,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
}
oauthCache.UserId = user.Id
oauthService.SetOauthCache(cacheKey, oauthCache, 0)
// if it is webadmin, after successful login redirect to webadmin
// 如果是webadmin,登录成功后跳转到webadmin
if oauthCache.DeviceType == model.LoginLogClientWebAdmin {
/*service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
@@ -299,7 +298,7 @@ func (o *Oauth) Message(c *gin.Context) {
}
}
//returnjscontent
//返回js内容
c.Header("Content-Type", "application/javascript")
c.String(http.StatusOK, res)
}
+13 -13
View File
@@ -15,11 +15,11 @@ type Peer struct {
// SysInfo
// @Tags System
// @Summary submit system info
// @Description submit system info
// @Summary 提交系统信息
// @Description 提交系统信息
// @Accept json
// @Produce json
// @Param body body requstform.PeerForm true "system info form"
// @Param body body requstform.PeerForm true "系统信息表单"
// @Success 200 {string} string "SYSINFO_UPDATED,ID_NOT_FOUND"
// @Failure 500 {object} response.ErrorResponse
// @Router /sysinfo [post]
@@ -31,10 +31,10 @@ func (p *Peer) SysInfo(c *gin.Context) {
return
}
fpe := f.ToPeer()
pe := service.AllService.PeerService.FindById(f.Id)
pe := service.AllService.PeerService.FindByUuid(f.Uuid)
if pe.RowId == 0 {
pe = f.ToPeer()
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid, pe.Id)
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid)
err = service.AllService.PeerService.Create(pe)
if err != nil {
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
@@ -42,7 +42,7 @@ func (p *Peer) SysInfo(c *gin.Context) {
}
} else {
if pe.UserId == 0 {
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid, pe.Id)
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid)
}
fpe.RowId = pe.RowId
fpe.UserId = pe.UserId
@@ -52,25 +52,25 @@ func (p *Peer) SysInfo(c *gin.Context) {
return
}
}
//SYSINFO_UPDATED upload successful
//ID_NOT_FOUND will be uploaded on the next heartbeat
//respond with text directly
//SYSINFO_UPDATED 上传成功
//ID_NOT_FOUND 下次心跳会上传
//直接响应文本
c.String(http.StatusOK, "SYSINFO_UPDATED")
}
// SysInfoVer
// @Tags System
// @Summary get system version info
// @Description get system version info
// @Summary 获取系统版本信息
// @Description 获取系统版本信息
// @Accept json
// @Produce json
// @Success 200 {string} string ""
// @Failure 500 {object} response.ErrorResponse
// @Router /sysinfo_ver [post]
func (p *Peer) SysInfoVer(c *gin.Context) {
// read the resources/version file
//读取resources/version文件
v := service.AllService.AppService.GetAppVersion()
// add the start time so the client can conveniently upload info
// 加上启动时间,方便client上传信息
v = fmt.Sprintf("%s\n%s", v, service.AllService.AppService.GetStartTime())
c.String(http.StatusOK, v)
}
+8 -8
View File
@@ -10,10 +10,10 @@ import (
type User struct {
}
// currentUser current user
// @Tags user
// @Summary user info
// @Description user info
// currentUser 当前用户
// @Tags 用户
// @Summary 用户信息
// @Description 用户信息
// @Accept json
// @Produce json
// @Success 200 {object} apiResp.UserPayload
@@ -26,10 +26,10 @@ type User struct {
// c.JSON(http.StatusOK, up)
//}
// Info user info
// @Tags user
// @Summary user info
// @Description user info
// Info 用户信息
// @Tags 用户
// @Summary 用户信息
// @Description 用户信息
// @Accept json
// @Produce json
// @Success 200 {object} apiResp.UserPayload
+10 -10
View File
@@ -12,10 +12,10 @@ import (
type WebClient struct {
}
// ServerConfig service config
// ServerConfig 服务配置
// @Tags WEBCLIENT
// @Summary service config
// @Description service config, provides an api-server for the webclient
// @Summary 服务配置
// @Description 服务配置,给webclient提供api-server
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -42,10 +42,10 @@ func (i *WebClient) ServerConfig(c *gin.Context) {
)
}
// SharedPeer shared peer
// SharedPeer 分享的peer
// @Tags WEBCLIENT
// @Summary shared peer
// @Description shared peer
// @Summary 分享的peer
// @Description 分享的peer
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
@@ -65,7 +65,7 @@ func (i *WebClient) SharedPeer(c *gin.Context) {
return
}
if sr.Expire != 0 {
//check whether expired,created_at + expire > now
//判断是否过期,created_at + expire > now
ca := time.Time(sr.CreatedAt)
if ca.Add(time.Second * time.Duration(sr.Expire)).Before(time.Now()) {
response.Fail(c, 101, "share expired")
@@ -89,10 +89,10 @@ func (i *WebClient) SharedPeer(c *gin.Context) {
})
}
// ServerConfigV2 service config
// ServerConfigV2 服务配置
// @Tags WEBCLIENT_V2
// @Summary service config
// @Description service config, provides an api-server for the webclient
// @Summary 服务配置
// @Description 服务配置,给webclient提供api-server
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
+1 -1
View File
@@ -25,7 +25,7 @@ func ApiInit() {
}
if global.Config.Gin.Mode == gin.ReleaseMode {
// redirect gin's Recovery log output to the logger's output
//修改gin Recovery日志 输出为logger的输出点
if global.Logger != nil {
gin.DefaultErrorWriter = global.Logger.WriterLevel(logrus.ErrorLevel)
}
+3 -3
View File
@@ -6,11 +6,11 @@ import (
"github.com/lejianwen/rustdesk-api/v2/service"
)
// BackendUserAuth backend permission verification middleware
// BackendUserAuth 后台权限验证中间件
func BackendUserAuth() gin.HandlerFunc {
return func(c *gin.Context) {
//disabled for testing
//测试先关闭
token := c.GetHeader("api-token")
if token == "" {
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
@@ -34,7 +34,7 @@ func BackendUserAuth() gin.HandlerFunc {
c.Set("curUser", user)
c.Set("token", token)
// if the remaining time is less than 1 day, the token is auto-renewed
//如果时间小于1天,token自动续期
service.AllService.UserService.AutoRefreshAccessToken(ut)
c.Next()
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"net/http"
)
// Cors CORS
// Cors 跨域
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
origin := c.GetHeader("Origin")
+2 -2
View File
@@ -9,7 +9,7 @@ import (
func JwtAuth() gin.HandlerFunc {
return func(c *gin.Context) {
//disabled for testing
//测试先关闭
token := c.GetHeader("api-token")
if token == "" {
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
@@ -31,7 +31,7 @@ func JwtAuth() gin.HandlerFunc {
user := service.AllService.UserService.InfoById(uid)
//user := &model.User{
// Id: uid,
// Username: "test user",
// Username: "测试用户",
//}
if user.Id == 0 {
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/sirupsen/logrus"
)
// Logger logging middleware
// Logger 日志中间件
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
global.Logger.WithFields(
+5 -5
View File
@@ -9,7 +9,7 @@ import (
func RustAuth() gin.HandlerFunc {
return func(c *gin.Context) {
//fmt.Println(c.Request.URL, c.Request.Header)
//getHTTP_AUTHORIZATION
//获取HTTP_AUTHORIZATION
token := c.GetHeader("Authorization")
if token == "" {
c.JSON(401, gin.H{
@@ -25,13 +25,13 @@ func RustAuth() gin.HandlerFunc {
c.Abort()
return
}
//extracttoken, format is Bearer {token}
//this is just a simple extraction
//提取token,格式是Bearer {token}
//这里只是简单的提取
token = token[7:]
// verify the token
//验证token
//check whether it is set jwt key
//检查是否设置了jwt key
if len(global.Jwt.Key) > 0 {
uid, _ := service.AllService.UserService.VerifyJWT(token)
if uid == 0 {
+3 -3
View File
@@ -27,7 +27,7 @@ type AddressBookForm struct {
}
func (a AddressBookForm) ToAddressBook() *model.AddressBook {
//tagsconvert
//tags转换
tags, _ := json.Marshal(a.Tags)
return &model.AddressBook{
@@ -52,7 +52,7 @@ func (a AddressBookForm) ToAddressBook() *model.AddressBook {
}
func (a AddressBookForm) ToAddressBooks() []*model.AddressBook {
//tagsconvert
//tags转换
tags, _ := json.Marshal(a.Tags)
abs := make([]*model.AddressBook, 0, len(a.UserIds))
@@ -92,7 +92,7 @@ type AddressBookQuery struct {
type ShareByWebClientForm struct {
Id string `json:"id" validate:"required"`
PasswordType string `json:"password_type" validate:"required,oneof=once fixed"` //can only be once,fixed
PasswordType string `json:"password_type" validate:"required,oneof=once fixed"` //只能是once,fixed
Password string `json:"password" validate:"required"`
Expire int64 `json:"expire"`
}
+4 -4
View File
@@ -1,10 +1,10 @@
package admin
type Login struct {
Username string `json:"username" validate:"required" label:"username"`
Password string `json:"password,omitempty" validate:"required" label:"password"`
Platform string `json:"platform" label:"platform"`
Captcha string `json:"captcha,omitempty" label:"captcha"`
Username string `json:"username" validate:"required" label:"用户名"`
Password string `json:"password,omitempty" validate:"required" label:"密码"`
Platform string `json:"platform" label:"平台"`
Captcha string `json:"captcha,omitempty" label:"验证码"`
CaptchaId string `json:"captcha_id,omitempty"`
}
-3
View File
@@ -13,7 +13,6 @@ type PeerForm struct {
Uuid string `json:"uuid"`
Version string `json:"version"`
GroupId uint `json:"group_id"`
Alias string `json:"alias"`
}
type PeerBatchDeleteForm struct {
@@ -33,7 +32,6 @@ func (f *PeerForm) ToPeer() *model.Peer {
Uuid: f.Uuid,
Version: f.Version,
GroupId: f.GroupId,
Alias: f.Alias,
}
}
@@ -45,7 +43,6 @@ type PeerQuery struct {
Uuids string `json:"uuids" form:"uuids"`
Ip string `json:"ip" form:"ip"`
Username string `json:"username" form:"username"`
Alias string `json:"alias" form:"alias"`
}
type SimpleDataQuery struct {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
type UserForm struct {
Id uint `json:"id"`
Username string `json:"username" validate:"required,gte=2,lte=32"`
Email string `json:"email"` //validate:"required,email" emailnot enforced
Email string `json:"email"` //validate:"required,email" email不强制
//Password string `json:"password" validate:"required,gte=4,lte=20"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
+1 -1
View File
@@ -1,7 +1,7 @@
package api
type OidcAuthRequest struct {
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"device info"`
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"设备信息"`
Id string `json:"id" label:"id"`
Op string `json:"op" label:"op"`
Uuid string `json:"uuid" label:"uuid"`
+1 -1
View File
@@ -36,7 +36,7 @@ func (pf *PeerForm) ToPeer() *model.Peer {
}
}
// PersonalAddressBookForm personal address book form
// PersonalAddressBookForm 个人地址簿表单
type PersonalAddressBookForm struct {
model.AddressBook
ForceAlwaysRelay string `json:"forceAlwaysRelay"`
+10 -10
View File
@@ -29,25 +29,25 @@ type DeviceInfoInLogin struct {
}
type LoginForm struct {
AutoLogin bool `json:"autoLogin" label:"auto login"`
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"device info"`
AutoLogin bool `json:"autoLogin" label:"自动登录"`
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"设备信息"`
Id string `json:"id" label:"id"`
Type string `json:"type" label:"type"`
Uuid string `json:"uuid" label:"uuid"`
Username string `json:"username" validate:"required,gte=2,lte=32" label:"username"`
Password string `json:"password,omitempty" validate:"gte=4,lte=32" label:"password"`
Username string `json:"username" validate:"required,gte=2,lte=32" label:"用户名"`
Password string `json:"password,omitempty" validate:"gte=4,lte=32" label:"密码"`
}
type UserListQuery struct {
Page uint `json:"page" form:"page" validate:"required" label:"page number"`
PageSize uint `json:"pageSize" form:"pageSize" validate:"required" label:"items per page"`
Status int `json:"status" form:"status" label:"status"`
Page uint `json:"page" form:"page" validate:"required" label:"页码"`
PageSize uint `json:"pageSize" form:"pageSize" validate:"required" label:"每页数量"`
Status int `json:"status" form:"status" label:"状态"`
Accessible string `json:"accessible" form:"accessible"`
}
type PeerListQuery struct {
Page uint `json:"page" form:"page" validate:"required" label:"page number"`
PageSize uint `json:"pageSize" form:"pageSize" validate:"required" label:"items per page"`
Status int `json:"status" form:"status" label:"status"`
Page uint `json:"page" form:"page" validate:"required" label:"页码"`
PageSize uint `json:"pageSize" form:"pageSize" validate:"required" label:"每页数量"`
Status int `json:"status" form:"status" label:"状态"`
Accessible string `json:"accessible" form:"accessible"`
}
+2 -2
View File
@@ -22,7 +22,7 @@ type WebClientPeerInfoPayload struct {
func (wcpp *WebClientPeerPayload) FromAddressBook(a *model.AddressBook) {
wcpp.ViewStyle = "shrink"
//24 hours ago
//24小时前
wcpp.Tm = time.Now().Add(-time.Hour * 24).UnixNano()
wcpp.Info = WebClientPeerInfoPayload{
Username: a.Username,
@@ -34,7 +34,7 @@ func (wcpp *WebClientPeerPayload) FromAddressBook(a *model.AddressBook) {
func (wcpp *WebClientPeerPayload) FromShareRecord(sr *model.ShareRecord) {
wcpp.ViewStyle = "shrink"
//24 hours ago
//24小时前
wcpp.Tm = time.Now().UnixNano()
wcpp.Tmppwd = sr.Password
wcpp.Info = WebClientPeerInfoPayload{
+1 -1
View File
@@ -50,7 +50,7 @@ func Init(g *gin.Engine) {
RustdeskCmdBind(adg)
DeviceGroupBind(adg)
//access static files
//访问静态文件
//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
}
+6 -10
View File
@@ -18,7 +18,7 @@ func ApiInit(g *gin.Engine) {
if global.Config.App.ShowSwagger == 1 {
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("api")))
}
// load HTML template
// 加载 HTML 模板
g.LoadHTMLGlob("resources/templates/*")
frg := g.Group("/api")
@@ -33,7 +33,7 @@ func ApiInit(g *gin.Engine) {
{
l := &api.Login{}
// if oidc is returned, login via oidc is possible
// 如果返回oidc则可以通过oidc登录
frg.GET("/login-options", l.LoginOptions)
frg.POST("/login", l.Login)
@@ -49,14 +49,10 @@ func ApiInit(g *gin.Engine) {
frg.GET("/oauth/callback", o.OauthCallback)
frg.GET("/oauth/login", o.OauthCallback)
frg.GET("/oauth/msg", o.Message)
frg.GET("/oidc/callback", o.OauthCallback)
frg.GET("/oidc/login", o.OauthCallback)
frg.GET("/oidc/msg", o.Message)
}
{
pe := &api.Peer{}
//submit system info
//提交系统信息
frg.POST("/sysinfo", pe.SysInfo)
frg.POST("/sysinfo_ver", pe.SysInfoVer)
}
@@ -93,14 +89,14 @@ func ApiInit(g *gin.Engine) {
{
ab := &api.Ab{}
//get address
//获取地址
frg.GET("/ab", ab.Ab)
//update address
//更新地址
frg.POST("/ab", ab.UpAb)
}
PersonalRoutes(frg)
//access static files
//访问静态文件
g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/public/upload"))
}
+2 -2
View File
@@ -10,7 +10,7 @@ type Handler interface {
Gc() error
}
// MaxTimeOut maximum timeout
// MaxTimeOut 最大超时时间
const (
TypeMem = "memory"
@@ -49,7 +49,7 @@ func EncodeValue(value interface{}) (string, error) {
}
func DecodeValue(value string, rtv interface{}) error {
// check whether rtv's type is string; if so, assign directly and return
//判断rtv的类型是否是string,如果是string,直接赋值并返回
/*switch rtv.(type) {
case *string:
*(rtv.(*string)) = value
+6 -6
View File
@@ -42,7 +42,7 @@ func TestFileCacheSet(t *testing.T) {
err := fc.Set("123", "ddd", 0)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
}
@@ -50,12 +50,12 @@ func TestFileCacheGet(t *testing.T) {
fc := New("file")
err := fc.Set("123", "45156", 300)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
res := ""
err = fc.Get("123", &res)
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
fmt.Println("res", res)
}
@@ -69,7 +69,7 @@ func TestRedisCacheSet(t *testing.T) {
err := rc.Set("123", "ddd", 0)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
}
@@ -81,12 +81,12 @@ func TestRedisCacheGet(t *testing.T) {
})
err := rc.Set("123", "451156", 300)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
res := ""
err = rc.Get("123", &res)
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
fmt.Println("res", res)
}
+4 -4
View File
@@ -32,12 +32,12 @@ func (c *FileCache) Get(key string, value interface{}) error {
return err
}
// get value; if the file does not exist or has expired, return empty and ignore errors
// 获取值,如果文件不存在或者过期,返回空,过滤掉错误
func (c *FileCache) getValue(key string) (string, error) {
f := c.fileName(key)
fileInfo, err := os.Stat(f)
if err != nil {
// file does not exist
//文件不存在
return "", nil
}
difT := time.Now().Sub(fileInfo.ModTime())
@@ -52,7 +52,7 @@ func (c *FileCache) getValue(key string) (string, error) {
return string(data), nil
}
// save value
// 保存值
func (c *FileCache) saveValue(key string, value string, exp int) error {
f := c.fileName(key)
lock := c.getLock(f)
@@ -91,7 +91,7 @@ func (c *FileCache) fileName(key string) string {
}
func (c *FileCache) Gc() error {
// check file expiration time and delete
//检查文件过期时间,并删除
return nil
}
+7 -7
View File
@@ -11,7 +11,7 @@ func TestFileSet(t *testing.T) {
err := fc.Set("123", "ddd", 0)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
}
@@ -21,7 +21,7 @@ func TestFileGet(t *testing.T) {
err := fc.Get("123", &res)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
fmt.Println("res", res)
}
@@ -32,7 +32,7 @@ func TestFileSetGet(t *testing.T) {
err = fc.Get("key1", &res)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
fmt.Println("res", res)
}
@@ -46,7 +46,7 @@ func TestFileGetJson(t *testing.T) {
err2 := fc.Get("123", res)
fmt.Println("res", res)
if err2 != nil {
t.Fatalf("read failed" + err2.Error())
t.Fatalf("读取失败" + err2.Error())
}
}
func TestFileSetGetJson(t *testing.T) {
@@ -59,7 +59,7 @@ func TestFileSetGetJson(t *testing.T) {
}
err := fc.Set("123", old, 300)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
//old_rr.AA = "aaa"
fmt.Println("old_rr", old)
@@ -68,10 +68,10 @@ func TestFileSetGetJson(t *testing.T) {
err2 := fc.Get("123", res)
fmt.Println("res", res)
if err2 != nil {
t.Fatalf("read failed" + err2.Error())
t.Fatalf("读取失败" + err2.Error())
}
if !reflect.DeepEqual(res, old) {
t.Fatalf("read error")
t.Fatalf("读取错误")
}
}
+9 -9
View File
@@ -11,8 +11,8 @@ import (
type MemoryCache struct {
data map[string]*CacheItem
ll *list.List // used to implement LRU
pq PriorityQueue // used to implement TTL
ll *list.List // 用于实现LRU
pq PriorityQueue // 用于实现TTL
quit chan struct{}
mu sync.Mutex
maxBytes int64
@@ -58,12 +58,12 @@ func (pq *PriorityQueue) Pop() interface{} {
}
func (m *MemoryCache) Get(key string, value interface{}) error {
// use reflection to set the stored value into the passed-in pointer variable
// 使用反射将存储的值设置到传入的指针变量中
val := reflect.ValueOf(value)
if val.Kind() != reflect.Ptr {
return errors.New("value must be a pointer")
}
// set to zero value
//设为空值
val.Elem().Set(reflect.Zero(val.Elem().Type()))
m.mu.Lock()
@@ -78,7 +78,7 @@ func (m *MemoryCache) Get(key string, value interface{}) error {
m.deleteItem(item)
return nil
}
// move to the tail of the queue
//移动到队列尾部
m.ll.MoveToBack(item.ListEle)
err := DecodeValue(item.Value, value)
@@ -97,11 +97,11 @@ func (m *MemoryCache) Set(key string, value interface{}, exp int) error {
if err != nil {
return err
}
// memory occupied by the key
//key 所占用的内存
keyBytes := int64(len(key))
// size of memory occupied by the value
//value所占用的内存空间大小
valueBytes := int64(len(v))
// check whether the maximum memory limit is exceeded
//判断是否超过最大内存限制
if m.maxBytes != 0 && m.maxBytes < keyBytes+valueBytes {
return errors.New("exceed maxBytes")
}
@@ -176,7 +176,7 @@ func (m *MemoryCache) startEviction() {
}()
}
// stopEviction stops the scheduled cleanup
// stopEviction 停止定时清理
func (m *MemoryCache) stopEviction() {
close(m.quit)
}
+14 -14
View File
@@ -11,7 +11,7 @@ func TestMemorySet(t *testing.T) {
err := mc.Set("123", "44567", 0)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
}
@@ -22,10 +22,10 @@ func TestMemoryGet(t *testing.T) {
err := mc.Get("123", &res)
fmt.Println("res", res)
if err != nil {
t.Fatalf("read failed " + err.Error())
t.Fatalf("读取失败 " + err.Error())
}
if res != "44567" {
t.Fatalf("read error")
t.Fatalf("读取错误")
}
}
@@ -37,30 +37,30 @@ func TestMemorySetExpGet(t *testing.T) {
mc.Set("2", "5", 5)
err := mc.Set("3", "3", 3)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
res := ""
err = mc.Get("3", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res 3", res)
time.Sleep(4 * time.Second)
//res = ""
err = mc.Get("3", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res 3", res)
err = mc.Get("2", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res 2", res)
err = mc.Get("1", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res 1", res)
@@ -69,29 +69,29 @@ func TestMemoryLru(t *testing.T) {
mc := NewMemoryCache(18)
mc.Set("1", "1111", 10)
mc.Set("2", "2222", 5)
// read once, so 2 will be moved to the end
//读取一次,2就会被放到最后
mc.Get("1", nil)
err := mc.Set("3", "three", 3)
err := mc.Set("3", "", 3)
if err != nil {
//t.Fatalf("write failed")
//t.Fatalf("写入失败")
}
res := ""
err = mc.Get("3", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res3", res)
res = ""
err = mc.Get("2", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res2", res)
res = ""
err = mc.Get("1", &res)
if err != nil {
t.Fatalf("read failed" + err.Error())
t.Fatalf("读取失败" + err.Error())
}
fmt.Println("res1", res)
+6 -6
View File
@@ -17,7 +17,7 @@ func TestRedisSet(t *testing.T) {
err := rc.Set("123", "ddd", 0)
if err != nil {
fmt.Println(err.Error())
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
}
@@ -29,12 +29,12 @@ func TestRedisGet(t *testing.T) {
})
err := rc.Set("123", "451156", 300)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
res := ""
err = rc.Get("123", &res)
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
fmt.Println("res", res)
}
@@ -54,16 +54,16 @@ func TestRedisGetJson(t *testing.T) {
}
err := rc.Set("1233", old, 300)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
res := &r{}
err2 := rc.Get("1233", res)
if err2 != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
if !reflect.DeepEqual(res, old) {
t.Fatalf("read error")
t.Fatalf("读取错误")
}
fmt.Println(res, res.Aa)
}
+5 -5
View File
@@ -6,7 +6,7 @@ import (
"sync"
)
// implements a simple cache used for testing
// 此处实现了一个简单的缓存,用于测试
// SimpleCache is a simple cache implementation
type SimpleCache struct {
data map[string]interface{}
@@ -19,21 +19,21 @@ func (s *SimpleCache) Get(key string, value interface{}) error {
s.mu.Lock()
defer s.mu.Unlock()
// use reflection to set the stored value into the passed-in pointer variable
// 使用反射将存储的值设置到传入的指针变量中
val := reflect.ValueOf(value)
if val.Kind() != reflect.Ptr {
return errors.New("value must be a pointer")
}
v, ok := s.data[key]
if !ok {
// set to zero value
//设为空值
val.Elem().Set(reflect.Zero(val.Elem().Type()))
return nil
}
vval := reflect.ValueOf(v)
if val.Elem().Type() != vval.Type() {
// set to zero value
//设为空值
val.Elem().Set(reflect.Zero(val.Elem().Type()))
return nil
}
@@ -45,7 +45,7 @@ func (s *SimpleCache) Get(key string, value interface{}) error {
func (s *SimpleCache) Set(key string, value interface{}, exp int) error {
s.mu.Lock()
defer s.mu.Unlock()
// check whether the passed-in value is a pointer; if so, dereference it
// 检查传入的值是否是指针,如果是则取其值
val := reflect.ValueOf(value)
if val.Kind() == reflect.Ptr {
val = val.Elem()
+11 -11
View File
@@ -9,11 +9,11 @@ func TestSimpleCache_Set(t *testing.T) {
s := NewSimpleCache()
err := s.Set("key", "value", 0)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
err = s.Set("key", 111, 0)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
}
@@ -24,7 +24,7 @@ func TestSimpleCache_Get(t *testing.T) {
err = s.Get("key", &value)
fmt.Println("value", value)
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
err = s.Set("key1", 11, 0)
@@ -32,7 +32,7 @@ func TestSimpleCache_Get(t *testing.T) {
err = s.Get("key1", &value1)
fmt.Println("value1", value1)
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
err = s.Set("key2", []byte{'a', 'b'}, 0)
@@ -40,7 +40,7 @@ func TestSimpleCache_Get(t *testing.T) {
err = s.Get("key2", &value2)
fmt.Println("value2", string(value2))
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
err = s.Set("key3", 33.33, 0)
@@ -48,7 +48,7 @@ func TestSimpleCache_Get(t *testing.T) {
err = s.Get("key3", &value3)
fmt.Println("value3", value3)
if err != nil {
t.Fatalf("read failed")
t.Fatalf("读取失败")
}
}
@@ -80,18 +80,18 @@ func TestSimpleCache_GetStruct(t *testing.T) {
}
err := s.Set("key", old, 300)
if err != nil {
t.Fatalf("write failed")
t.Fatalf("写入失败")
}
res := &r{}
err2 := s.Get("key", res)
fmt.Println("res", res)
if err2 != nil {
t.Fatalf("read failed" + err2.Error())
t.Fatalf("读取失败" + err2.Error())
}
// modify the original value to see whether it changes afterward
//修改原始值,看后面是否会变化
old.A = "aa"
old_rr.AA = "aaa"
fmt.Println("old", old)
@@ -99,10 +99,10 @@ func TestSimpleCache_GetStruct(t *testing.T) {
err3 := s.Get("key", res2)
fmt.Println("res2", res2, res2.R.AA, res2.R.BB)
if err3 != nil {
t.Fatalf("read failed" + err3.Error())
t.Fatalf("读取失败" + err3.Error())
}
//if reflect.DeepEqual(res, old) {
// t.Fatalf("read error")
// t.Fatalf("读取错误")
//}
}
+6 -6
View File
@@ -34,30 +34,30 @@ Hj4yO4j5LOWDMTgDcLsZTxbGiTzkNc/HghrNIevDAQdgjJQNl84zDjyyCA4r/MA7
bYJTtYj8q6J0EDbRdT9b6hMclyzjNXdx2loJxR0R8WUeL1lDEPq8
-----END RSA PRIVATE KEY-----`
// test token generation
// 测试token生成
func TestGenerateToken(t *testing.T) {
jwtService := NewJwt(pk, time.Second*1000)
token := jwtService.GenerateToken(1)
if token == "" {
t.Fatal("token generation failed")
t.Fatal("token生成失败")
}
fmt.Println(pk, token)
}
// test token parsing
// 测试token解析
func TestParseToken(t *testing.T) {
jwtService := NewJwt(pk, time.Second*1000)
token := jwtService.GenerateToken(999)
if token == "" {
t.Fatal("token generation failed")
t.Fatal("token生成失败")
}
uid, err := jwtService.ParseToken(token)
if err != nil {
t.Fatal("token parsing failed", err)
t.Fatal("token解析失败", err)
}
if uid != 999 {
t.Fatal("token parsing failed")
t.Fatal("token解析失败")
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ func New(c *Config) *log.Logger {
//FieldsOrder: []string{"name", "age"},
})
// log file
// 日志文件
f := c.Path
var write io.Writer
if f != "" {
+7 -7
View File
@@ -17,11 +17,11 @@ type MysqlConfig struct {
func NewMysql(mysqlConf *MysqlConfig, logwriter logger.Writer) *gorm.DB {
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: mysqlConf.Dsn, // DSN data source name
DefaultStringSize: 256, // default length for string type fields
//DisableDatetimePrecision: true, // disable datetime precision; not supported by databases before MySQL 5.6
//DontSupportRenameIndex: true, // rename indexes by dropping and recreating them; databases before MySQL 5.7 and MariaDB do not support renaming indexes
//DontSupportRenameColumn: true, // rename columns using `change`; databases before MySQL 8 and MariaDB do not support renaming columns
//SkipInitializeWithVersion: false, // auto-configure based on the current MySQL version
DefaultStringSize: 256, // string 类型字段的默认长度
//DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
//DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
//DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
//SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
Logger: logger.New(
@@ -42,10 +42,10 @@ func NewMysql(mysqlConf *MysqlConfig, logwriter logger.Writer) *gorm.DB {
if err2 != nil {
fmt.Println(err2)
}
// SetMaxIdleConns sets the maximum number of connections in the idle connection pool
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(mysqlConf.MaxIdleConns)
// SetMaxOpenConns sets the maximum number of open database connections.
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(mysqlConf.MaxOpenConns)
return db
+2 -2
View File
@@ -35,10 +35,10 @@ func NewPostgresql(conf *PostgresqlConfig, logwriter logger.Writer) *gorm.DB {
if err2 != nil {
fmt.Println(err2)
}
// SetMaxIdleConns sets the maximum number of connections in the idle connection pool
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(conf.MaxIdleConns)
// SetMaxOpenConns sets the maximum number of open database connections.
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(conf.MaxOpenConns)
return db
+2 -2
View File
@@ -34,10 +34,10 @@ func NewSqlite(sqliteConf *SqliteConfig, logwriter logger.Writer) *gorm.DB {
if err2 != nil {
fmt.Println(err2)
}
// SetMaxIdleConns sets the maximum number of connections in the idle connection pool
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(sqliteConf.MaxIdleConns)
// SetMaxOpenConns sets the maximum number of open database connections.
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(sqliteConf.MaxOpenConns)
return db
+5 -5
View File
@@ -240,11 +240,11 @@ func getMD5FromNewAuthString(r *http.Request) ([]byte, error) {
}
/* VerifySignature
* VerifySignature needs three pieces of data to perform signature verification: 1> obtain the public key PublicKey; 2> generate a new MD5 authentication string; 3> decode the authentication string carried by the Request;
* 1> obtain the public key PublicKey: get the URL from the "x-oss-pub-key-url" field of the RequestHeader, read the public key content the URL points to, decode and parse it, and use it as the input parameter of rsa.VerifyPKCS1v15.
* 2> generate a new MD5 authentication string: urldecode the path part of the url in the Request, append the query part of the url, then append the body, combine them and apply MD5 encoding to obtain the MD5 authentication byte string.
* 3> decode the authentication string carried by the Request: get the "authorization" field of the RequestHeader and Base64-decode it to use as the comparison authentication string for signature verification.
* rsa.VerifyPKCS1v15 performs the signature verification and returns the result.
* VerifySignature需要三个重要的数据信息来进行签名验证 1>获取公钥PublicKey; 2>生成新的MD5鉴权串; 3>解码Request携带的鉴权串;
* 1>获取公钥PublicKey : 从RequestHeader的"x-oss-pub-key-url"字段中获取 URL, 读取URL链接的包含的公钥内容 进行解码解析 将其作为rsa.VerifyPKCS1v15的入参
* 2>生成新的MD5鉴权串 : 把Request中的url中的path部分进行urldecode 加上url的query部分 再加上body 组合之后进行MD5编码 得到MD5鉴权字节串
* 3>解码Request携带的鉴权串 获取RequestHeader的"authorization"字段 对其进行Base64解码作为签名验证的鉴权对比串
* rsa.VerifyPKCS1v15进行签名验证返回验证结果
* */
func verifySignature(bytePublicKey []byte, byteMd5 []byte, authorization []byte) bool {
pubBlock, _ := pem.Decode(bytePublicKey)
+3 -3
View File
@@ -17,7 +17,7 @@ import "github.com/lejianwen/rustdesk-api/v2/model/custom_types"
// String loginName; //login username
// bool? sameServer;
// AddressBook some fields are only uploaded for Personal
// AddressBook 有些字段是Personal才会上传的
type AddressBook struct {
RowId uint `gorm:"primaryKey" json:"row_id"`
Id string `json:"id" gorm:"default:0;not null;index"`
@@ -59,8 +59,8 @@ type AddressBookCollectionRule struct {
IdModel
UserId uint `json:"user_id" gorm:"default:0;not null;"`
CollectionId uint `json:"collection_id" gorm:"default:0;not null;index" validate:"required"`
Rule int `json:"rule" gorm:"default:0;not null;" validate:"required,gte=1,lte=3"` // 0: none 1: read 2: read-write 3: full control
Type int `json:"type" gorm:"default:1;not null;" validate:"required,gte=1,lte=2"` // 1: personal 2: group
Rule int `json:"rule" gorm:"default:0;not null;" validate:"required,gte=1,lte=3"` // 0: 无 1: 读 2: 读写 3: 完全控制
Type int `json:"type" gorm:"default:1;not null;" validate:"required,gte=1,lte=2"` // 1: 个人 2: 群组
ToId uint `json:"to_id" gorm:"default:0;not null;" validate:"required,gt=0"`
TimeModel
}
+2 -2
View File
@@ -7,7 +7,7 @@ import (
"fmt"
)
// AutoJson data type
// AutoJson 数据类型
type AutoJson json.RawMessage
func (j *AutoJson) Scan(value interface{}) error {
@@ -33,7 +33,7 @@ func (j *AutoJson) Scan(value interface{}) error {
}
result := &json.RawMessage{}
err := json.Unmarshal(bytes, result)
// json parse error, return empty
//解析json错误 返回空
if err != nil {
*j = AutoJson(json.RawMessage{'[', ']'})
return nil
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"time"
)
// AutoTime custom time format
// AutoTime 自定义时间格式
type AutoTime time.Time
func (mt AutoTime) Value() (driver.Value, error) {
+2 -2
View File
@@ -1,8 +1,8 @@
package model
const (
GroupTypeDefault = 1 // default
GroupTypeShare = 2 // shared
GroupTypeDefault = 1 // 默认
GroupTypeShare = 2 // 共享
)
type Group struct {
+2 -2
View File
@@ -7,8 +7,8 @@ import (
type StatusCode int
const (
COMMON_STATUS_ENABLE StatusCode = 1 // common status: enabled
COMMON_STATUS_DISABLED StatusCode = 2 // common status: disabled
COMMON_STATUS_ENABLE StatusCode = 1 //通用状态 启用
COMMON_STATUS_DISABLED StatusCode = 2 //通用状态 禁用
)
type IdModel struct {
+2 -3
View File
@@ -41,7 +41,6 @@ type Oauth struct {
OauthType string `json:"oauth_type"`
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
//RedirectUrl string `json:"redirect_url"`
AutoRegister *bool `json:"auto_register"`
Scopes string `json:"scopes"`
Issuer string `json:"issuer"`
@@ -119,7 +118,7 @@ type OidcUser struct {
func (ou *OidcUser) ToOauthUser() *OauthUser {
var username string
// Use PreferredUsername; if not present, fall back to the Email prefix
// 使用 PreferredUsername,如果不存在,降级到 Email 前缀
if ou.PreferredUsername != "" {
username = ou.PreferredUsername
} else {
@@ -169,7 +168,7 @@ func (lu *LinuxdoUser) ToOauthUser() *OauthUser {
Name: lu.Name,
Username: strings.ToLower(lu.Username),
Email: lu.Email,
VerifiedEmail: true, // linux.do user emails are verified by default
VerifiedEmail: true, // linux.do 用户邮箱默认已验证
Picture: lu.Avatar,
}
}
-1
View File
@@ -15,7 +15,6 @@ type Peer struct {
LastOnlineTime int64 `json:"last_online_time" gorm:"default:0;not null;"`
LastOnlineIp string `json:"last_online_ip" gorm:"default:'';not null;"`
GroupId uint `json:"group_id" gorm:"default:0;not null;index"`
Alias string `json:"alias" gorm:"default:'';not null;index"`
TimeModel
}
+1 -1
View File
@@ -11,7 +11,7 @@ type ShareRecord struct {
TimeModel
}
// ShareRecordList share record list
// ShareRecordList 分享记录列表
type ShareRecordList struct {
ShareRecords []*ShareRecord `json:"list,omitempty"`
Pagination
+1 -1
View File
@@ -4,7 +4,7 @@ type Tag struct {
IdModel
Name string `json:"name" gorm:"default:'';not null;"`
UserId uint `json:"user_id" gorm:"default:0;not null;index"`
Color uint `json:"color" gorm:"default:0;not null;"` //color is a flutter color value, from 0x00000000 to 0xFFFFFFFF; the first two digits represent the alpha (transparency), the remaining 6 digits represent the color, can be converted to rgba
Color uint `json:"color" gorm:"default:0;not null;"` //color flutter的颜色值,从0x00000000 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba
CollectionId uint `json:"collection_id" gorm:"default:0;not null;index"`
Collection *AddressBookCollection `json:"collection,omitempty"`
TimeModel
+2 -2
View File
@@ -15,9 +15,9 @@ type User struct {
TimeModel
}
// BeforeSave hook ensures the email field has a sensible default value
// BeforeSave 钩子用于确保 email 字段有合理的默认值
//func (u *User) BeforeSave(tx *gorm.DB) (err error) {
// // If email is empty, set it to a default value
// // 如果 email 为空,设置为默认值
// if u.Email == "" {
// u.Email = fmt.Sprintf("%s@example.com", u.Username)
// }
+49 -56
View File
@@ -5,8 +5,8 @@ other = "測試2 {{.P0}}"
[ParamsError]
description = "Params validation failed."
one = "參數驗證失敗。"
other = "參數驗證失敗。"
one = "引數錯誤。"
other = "引數錯誤。"
[OperationFailed]
description = "OperationFailed."
@@ -20,18 +20,18 @@ other = "操作成功。"
[ItemExists]
description = "Item already exists."
one = "項目已存在。"
other = "項目已存在。"
one = "資料已存在。"
other = "資料已存在。"
[ItemNotFound]
description = "Item not found."
one = "找不到項目。"
other = "找不到項目。"
one = "資料不存在。"
other = "資料不存在。"
[NoAccess]
description = "No access."
one = "無權限存取。"
other = "無權限存取。"
one = "無許可權。"
other = "無許可權。"
[NeedLogin]
description = "Need login."
@@ -50,23 +50,24 @@ other = "系統錯誤。"
[ConfigNotFound]
description = "Config not found."
one = "找不到設定。"
other = "找不到設定。"
one = "配置不存在。"
other = "配置不存在。"
#授權過期
[OauthExpired]
description = "Oauth expired."
one = "OAuth 已過期,請重。"
other = "OAuth 已過期,請重。"
one = "授權過期,請重新授權。"
other = "授權過期,請重新授權。"
[OauthFailed]
description = "Oauth failed."
one = "OAuth 失敗。"
other = "OAuth 失敗。"
one = "授權失敗。"
other = "授權失敗。"
[OauthHasBindOtherUser]
description = "Oauth has bind other user."
one = "OAuth 已綁定其他使用者。"
other = "OAuth 已綁定其他使用者。"
one = "授權已繫結其他使用者。"
other = "授權已繫結其他使用者。"
[ParamIsEmpty]
description = "Param is empty."
@@ -75,64 +76,56 @@ other = "{{.P0}} 為空。"
[BindFail]
description = "Bind fail."
one = "綁定失敗。"
other = "綁定失敗。"
one = "繫結失敗。"
other = "繫結失敗。"
[BindSuccess]
description = "Bind success."
one = "綁定成功。"
other = "綁定成功。"
one = "繫結成功。"
other = "繫結成功。"
[OauthHasBeenSuccess]
description = "Oauth has been success."
one = "OAuth 已成功。"
other = "OAuth 已成功。"
one = "授權已成功。"
other = "授權已成功。"
[OauthSuccess]
description = "Oauth success."
one = "OAuth 成功。"
other = "OAuth 成功。"
one = "授權成功。"
other = "授權成功。"
[OauthRegisterSuccess]
description = "Oauth register success."
one = "OAuth 註冊成功。"
other = "OAuth 註冊成功。"
one = "授權註冊成功。"
other = "授權註冊成功。"
[OauthRegisterFailed]
description = "Oauth register failed."
one = "OAuth 註冊失敗。"
other = "OAuth 註冊失敗。"
one = "授權註冊失敗。"
other = "授權註冊失敗。"
[GetOauthTokenError]
description = "Get oauth token error."
one = "取得 OAuth 權杖錯誤。"
other = "取得 OAuth 權杖錯誤。"
one = "獲取授權token失敗。"
other = "獲取授權token失敗。"
[GetOauthUserInfoError]
description = "Get oauth user info error."
one = "取得 OAuth 使用者資訊錯誤。"
other = "取得 OAuth 使用者資訊錯誤。"
one = "獲取授權使用者資訊失敗。"
other = "獲取授權使用者資訊失敗。"
[DecodeOauthUserInfoError]
description = "Decode oauth user info error."
one = "解析 OAuth 使用者資訊錯誤。"
other = "解析 OAuth 使用者資訊錯誤。"
one = "解析授權使用者資訊失敗。"
other = "解析授權使用者資訊失敗。"
[OldPasswordError]
description = "Old password error."
one = "舊密碼錯誤。"
other = "舊密碼錯誤。"
[DefaultGroup]
description = "Default group."
one = "預設組"
other = "預設組"
one = "預設組"
other = "預設組"
[ShareGroup]
description = "Share group."
one = "共享組"
other = "共享組"
one = "共享組"
other = "共享組"
[RegisterClosed]
description = "Register closed."
one = "註冊已關閉。"
@@ -150,20 +143,20 @@ other = "驗證碼錯誤。"
[PwdLoginDisabled]
description = "Password login disabled."
one = "密碼登入已停用。"
other = "密碼登入已停用。"
one = "密碼登錄已禁用。"
other = "密碼登錄已禁用。"
[CannotShareToSelf]
description = "Cannot share to self."
one = "無法享給自己。"
other = "無法享給自己。"
one = "無法享給自己。"
other = "無法享給自己。"
[Banned]
description = "Banned."
one = "已被禁用。"
other = "已被禁用。"
one = "禁止使用。"
other = "禁止使用。"
[RegisterSuccessWaitAdminConfirm]
description = "Register success, wait admin confirm."
one = "註冊成功,等待管理員確認。"
other = "註冊成功,等待管理員確認。"
description = "Register success wait admin confirm."
one = "註冊成功,等待管理員確認。"
other = "註冊成功,等待管理員確認。"
+1 -1
View File
@@ -62,7 +62,7 @@
var title = 'OauthFailed'
var msg = '{{.message}}'
var btn = 'Close'
document.writeln('<script src="/api/oidc/msg?lang=' + lang + '&msg=' + msg + '&title=OauthFailed"><\/script>');
document.writeln('<script src="/api/oauth/msg?lang=' + lang + '&msg=' + msg + '&title=OauthFailed"><\/script>');
</script>
</head>
<body>
+1 -1
View File
@@ -61,7 +61,7 @@
var title = 'OauthSuccess'
var msg = '{{.message}}'
var btn = 'Close'
document.writeln('<script src="/api/oidc/msg?lang=' + lang + '&msg=' + msg + '&title=OauthSuccess"><\/script>');
document.writeln('<script src="/api/oauth/msg?lang=' + lang + '&msg=' + msg + '&title=OauthSuccess"><\/script>');
</script>
</head>
<body>

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