mirror of
https://github.com/lejianwen/rustdesk-api.git
synced 2026-02-16 03:00:55 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24f570b64f | ||
|
|
6322177b71 | ||
|
|
d2390d1cb3 | ||
|
|
6fe6f6b708 | ||
|
|
a656f4fec3 | ||
|
|
399c32da7d | ||
|
|
62167836dc | ||
|
|
caef3897a0 | ||
|
|
5ef6810e3f | ||
|
|
ae2079f583 | ||
|
|
aa65382a0f | ||
|
|
18c61a2bfc | ||
|
|
7cc1a8a58a | ||
|
|
cf9feac702 | ||
|
|
a963cd0209 |
172
README.md
172
README.md
@@ -30,33 +30,62 @@
|
|||||||
- Oauth 管理
|
- Oauth 管理
|
||||||
- 快速使用web client
|
- 快速使用web client
|
||||||
- i18n
|
- i18n
|
||||||
|
- 通过 web client 分享给游客
|
||||||
- Web Client
|
- Web Client
|
||||||
- 自动获取API server
|
- 自动获取API server
|
||||||
- 自动获取ID服务器和KEY
|
- 自动获取ID服务器和KEY
|
||||||
- 自动获取地址簿
|
- 自动获取地址簿
|
||||||
|
- 游客通过临时分享链接直接远程到设备
|
||||||
|
|
||||||
## 使用前准备
|
## 使用前准备
|
||||||
|
|
||||||
### [Rustdesk](https://github.com/rustdesk/rustdesk)
|
### [Rustdesk](https://github.com/rustdesk/rustdesk)
|
||||||
|
|
||||||
1. PC客户端使用的是 ***1.3.0***,经测试 ***1.2.6+*** 都可以
|
#### PC客户端使用的是 ***1.3.0***,经测试 ***1.2.6+*** 都可以
|
||||||
2. server端必须指定key,不能用自带的生成的key,否则可能链接不上或者超时
|
|
||||||
|
|
||||||
|
#### 关于PC端链接超时或者链接不上的问题以及解决方案
|
||||||
|
##### 链接不上是或者超时
|
||||||
|
因为server端相对于客户端落后版本,server不会响应客户端的`secure_tcp`请求,所以客户端超时。
|
||||||
|
相关代码代码位置在`https://github.com/rustdesk/rustdesk/blob/master/src/client.rs#L322`
|
||||||
|
```rust
|
||||||
|
if !key.is_empty() && !token.is_empty() {
|
||||||
|
// mainly for the security of token
|
||||||
|
allow_err!(secure_tcp(&mut socket, key).await);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
可看到当`key`和`token`都不为空时,会调用`secure_tcp`,但是server端不会响应,所以客户端超时
|
||||||
|
`secure_tcp` 代码位置在 `https://github.com/rustdesk/rustdesk/blob/master/src/common.rs#L1203`
|
||||||
|
|
||||||
|
##### 4种解决方案
|
||||||
|
1. server端指定key。
|
||||||
|
- 优点:简单
|
||||||
|
- 缺点:链接不是加密的
|
||||||
```bash
|
```bash
|
||||||
hbbs -r <relay-server-ip[:port]> -k <key>
|
hbbs -r <relay-server-ip[:port]> -k <key>
|
||||||
hbbr -k <key>
|
hbbr -k <key>
|
||||||
```
|
```
|
||||||
|
|
||||||
比如
|
比如
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hbbs -r <relay-server-ip[:port]> -k abc1234567
|
hbbs -r <relay-server-ip[:port]> -k abc1234567
|
||||||
hbbr -k abc1234567
|
hbbr -k abc1234567
|
||||||
```
|
```
|
||||||
|
2. server端使用系统生成的key,或者自定义的密钥对,但如果client已登录,链接时容易超时或者链接不上,可以退出登录后再链接就可以了,webclient可以不用退出登录
|
||||||
|
- 优点:链接加密
|
||||||
|
- 缺点:操作麻烦
|
||||||
|
3. server端使用系统生成的key,或者自定义的密钥对,fork官方客户端的代码将`secure_tcp`修改成直接返回,然后通过`Github Actions`编译,下载编译后的客户端。
|
||||||
|
参考[官方文档](https://rustdesk.com/docs/en/dev/build/all/)
|
||||||
|
- 优点:链接加密,可以自定义客户端一些功能,编译后直接可用
|
||||||
|
- 缺点:需要自己fork代码,编译,有点难度
|
||||||
|
4. 使用[我fork的代码](https://github.com/lejianwen/rustdesk),已经修改了`secure_tcp`,可以直接下载使用,[下载地址](https://github.com/lejianwen/rustdesk/releases)
|
||||||
|
- 优点:代码改动可查看,`Github Actions`编译,链接加密,直接下载使用
|
||||||
|
- 缺点:可能跟不上官方版本更新
|
||||||
|
|
||||||
|
***对链接加密要求不高的可以使用`1`,对链接加密要求高的可以使用`3`或`4`***
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
### API 服务: 基本实现了PC端基础的接口。支持Personal版本接口,可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
|
### API 服务
|
||||||
|
基本实现了PC端基础的接口。支持Personal版本接口,可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
|
||||||
|
|
||||||
#### 登录
|
#### 登录
|
||||||
|
|
||||||
@@ -69,26 +98,27 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 群组,群组分为`共享组`和`普通组`,共享组中所有人都能看到小组成员的设备,普通组只有管理员能看到所有小组成员的设备
|
#### 群组
|
||||||
|
群组分为`共享组`和`普通组`,共享组中所有人都能看到小组成员的设备,普通组只有管理员能看到所有小组成员的设备
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Web Admin:
|
### Web Admin:
|
||||||
|
|
||||||
***使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
|
* 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
|
||||||
|
|
||||||
***后台访问地址是`http://<your server>[:port]/_admin/`初次安装管理员为用户名密码为`admin` `admin`,请即时更改密码***
|
* 后台访问地址是`http://<your server>[:port]/_admin/`初次安装管理员为用户名密码为`admin` `admin`,请即时更改密码
|
||||||
|
|
||||||
1. 管理员界面
|
1. 管理员界面
|
||||||

|

|
||||||
2. 普通用户界面
|
2. 普通用户界面
|
||||||

|

|
||||||
右上角也可以更改密码
|
右上角可以更改密码,也可以切换语言
|
||||||

|

|
||||||
|
|
||||||
3. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
|
3. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
|
||||||

|

|
||||||
4. 可以直接打开webclient,方便使用
|
4. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
|
||||||

|

|
||||||
5. Oauth,暂时只支持了`Github`和`Google`, 需要创建一个`OAuth App`,然后配置到后台
|
5. Oauth,暂时只支持了`Github`和`Google`, 需要创建一个`OAuth App`,然后配置到后台
|
||||||

|

|
||||||
@@ -121,6 +151,8 @@
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
lang: "en"
|
lang: "en"
|
||||||
|
app:
|
||||||
|
web-client: 1 # 1:启用 0:禁用
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release"
|
mode: "release"
|
||||||
@@ -141,17 +173,23 @@ rustdesk:
|
|||||||
api-server: "http://192.168.1.66:21114"
|
api-server: "http://192.168.1.66:21114"
|
||||||
key: "123456789"
|
key: "123456789"
|
||||||
personal: 1
|
personal: 1
|
||||||
|
logger:
|
||||||
|
path: "./runtime/log.txt"
|
||||||
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
|
report-caller: true
|
||||||
```
|
```
|
||||||
|
|
||||||
* 环境变量,变量名前缀是RUSTDESK_API,环境变量如果存在将覆盖配置文件中的配置
|
### 环境变量
|
||||||
|
变量名前缀是`RUSTDESK_API`,环境变量如果存在将覆盖配置文件中的配置
|
||||||
|
|
||||||
| 变量名 | 说明 | 示例 |
|
| 变量名 | 说明 | 示例 |
|
||||||
|-------------------------------------|--------------------------------------|-----------------------------|
|
|------------------------------------|--------------------------------------|-----------------------------|
|
||||||
| TZ | 时区 | Asia/Shanghai |
|
| TZ | 时区 | Asia/Shanghai |
|
||||||
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
||||||
|
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
|
||||||
| -----GIN配置----- | ---------- | ---------- |
|
| -----GIN配置----- | ---------- | ---------- |
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
||||||
| -----------GORM配置------------------ | ------------------------------------ | --------------------------- |
|
| -----------GORM配置---------------- | ------------------------------------ | --------------------------- |
|
||||||
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
|
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
|
||||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
|
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
|
||||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
|
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
|
||||||
@@ -167,7 +205,7 @@ rustdesk:
|
|||||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
|
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
|
||||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
|
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
|
||||||
|
|
||||||
### 安装步骤
|
### 运行
|
||||||
|
|
||||||
#### docker运行
|
#### docker运行
|
||||||
|
|
||||||
@@ -177,18 +215,17 @@ rustdesk:
|
|||||||
docker run -d --name rustdesk-api -p 21114:21114 \
|
docker run -d --name rustdesk-api -p 21114:21114 \
|
||||||
-v /data/rustdesk/api:/app/data \
|
-v /data/rustdesk/api:/app/data \
|
||||||
-e TZ=Asia/Shanghai \
|
-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_ID_SERVER=192.168.1.66:21116 \
|
||||||
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
-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_API_SERVER=http://192.168.1.66:21114 \
|
||||||
-e RUSTDESK_API_RUSTDESK_KEY=123456789 \
|
-e RUSTDESK_API_RUSTDESK_KEY=<key> \
|
||||||
lejianwen/rustdesk-api
|
lejianwen/rustdesk-api
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 使用`docker compose`
|
2. 使用`docker compose`
|
||||||
|
|
||||||
- 简单示例
|
- 简单示例
|
||||||
|
```yaml
|
||||||
```docker-compose
|
|
||||||
services:
|
services:
|
||||||
rustdesk-api:
|
rustdesk-api:
|
||||||
container_name: rustdesk-api
|
container_name: rustdesk-api
|
||||||
@@ -197,7 +234,7 @@ lejianwen/rustdesk-api
|
|||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
ports:
|
ports:
|
||||||
- 21114:21114
|
- 21114:21114
|
||||||
image: lejianwen/rustdesk-api
|
image: lejianwen/rustdesk-api
|
||||||
@@ -208,9 +245,9 @@ lejianwen/rustdesk-api
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
```
|
```
|
||||||
|
|
||||||
- 根据rustdesk提供的示例加上自己的rustdesk-api
|
- 根据rustdesk官方提供的示例,加上自己的rustdesk-api
|
||||||
|
- 如果是使用的系统生成的KEY,去掉`-k <key>`参数,在启动后运行`docker-compose logs hbbs`或者`cat ./data/id_ed25519.pub`查看KEY,然后再修改`RUSTDESK_API_RUSTDESK_KEY=<key>`再执行`docker-compose up -d`
|
||||||
```docker-compose
|
```yaml
|
||||||
networks:
|
networks:
|
||||||
rustdesk-net:
|
rustdesk-net:
|
||||||
external: false
|
external: false
|
||||||
@@ -222,11 +259,10 @@ lejianwen/rustdesk-api
|
|||||||
- 21116:21116 # 自定义 hbbs 映射端口
|
- 21116:21116 # 自定义 hbbs 映射端口
|
||||||
- 21116:21116/udp # 自定义 hbbs 映射端口
|
- 21116:21116/udp # 自定义 hbbs 映射端口
|
||||||
- 21118:21118 # web client
|
- 21118:21118 # web client
|
||||||
- 21119:21119 # web client
|
|
||||||
image: rustdesk/rustdesk-server
|
image: rustdesk/rustdesk-server
|
||||||
command: hbbs -r <relay-server-ip[:port]> -k 123456789 # 填入个人域名或 IP + hbbr 暴露端口
|
command: hbbs -r <relay-server-ip[:port]> -k <key> # 填入个人域名或 IP + hbbr 暴露端口
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/hbbs:/root # 自定义挂载目录
|
- ./data:/root # 自定义挂载目录
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -240,11 +276,11 @@ lejianwen/rustdesk-api
|
|||||||
container_name: hbbr
|
container_name: hbbr
|
||||||
ports:
|
ports:
|
||||||
- 21117:21117 # 自定义 hbbr 映射端口
|
- 21117:21117 # 自定义 hbbr 映射端口
|
||||||
|
- 21119:21119 # web client
|
||||||
image: rustdesk/rustdesk-server
|
image: rustdesk/rustdesk-server
|
||||||
command: hbbr -k 123456789
|
command: hbbr -k <key>
|
||||||
#command: hbbr
|
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/hbbr:/root # 自定义挂载目录
|
- ./data:/root
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -259,7 +295,7 @@ lejianwen/rustdesk-api
|
|||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
ports:
|
ports:
|
||||||
- 21114:21114
|
- 21114:21114
|
||||||
image: lejianwen/rustdesk-api
|
image: lejianwen/rustdesk-api
|
||||||
@@ -268,14 +304,11 @@ lejianwen/rustdesk-api
|
|||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- 如果使用的是S6的镜像,会需要修改启动脚本,覆盖镜像中的`/etc/s6-overlay/s6-rc.d/hbbr/run`
|
- S6的镜像
|
||||||
和`/etc/s6-overlay/s6-rc.d/hbbr/run`
|
- 如果使用***自定义KEY***,会需要修改启动脚本,覆盖镜像中的`/etc/s6-overlay/s6-rc.d/hbbr/run`和`/etc/s6-overlay/s6-rc.d/hbbr/run`
|
||||||
|
1. 创建`hbbr/run`,自定义KEY才需要
|
||||||
1. 创建`hbbr/run`
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#!/command/with-contenv sh
|
#!/command/with-contenv sh
|
||||||
cd /data
|
cd /data
|
||||||
@@ -283,8 +316,7 @@ lejianwen/rustdesk-api
|
|||||||
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
||||||
/usr/bin/hbbr $PARAMS
|
/usr/bin/hbbr $PARAMS
|
||||||
```
|
```
|
||||||
|
2. 创建`hbbs/run`,自定义KEY才需要
|
||||||
2. 创建`hbbs/run`
|
|
||||||
```bash
|
```bash
|
||||||
#!/command/with-contenv sh
|
#!/command/with-contenv sh
|
||||||
sleep 2
|
sleep 2
|
||||||
@@ -294,8 +326,7 @@ lejianwen/rustdesk-api
|
|||||||
/usr/bin/hbbs -r $RELAY $PARAMS
|
/usr/bin/hbbs -r $RELAY $PARAMS
|
||||||
```
|
```
|
||||||
3. 修改`docker-compose.yml`中的`s6`部分
|
3. 修改`docker-compose.yml`中的`s6`部分
|
||||||
|
```yaml
|
||||||
```
|
|
||||||
networks:
|
networks:
|
||||||
rustdesk-net:
|
rustdesk-net:
|
||||||
external: false
|
external: false
|
||||||
@@ -313,7 +344,7 @@ lejianwen/rustdesk-api
|
|||||||
environment:
|
environment:
|
||||||
- RELAY=192.168.1.66:21117
|
- RELAY=192.168.1.66:21117
|
||||||
- ENCRYPTED_ONLY=1
|
- ENCRYPTED_ONLY=1
|
||||||
- KEY=abc123456789
|
- KEY=<key> #自定义KEY
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
||||||
@@ -329,17 +360,55 @@ lejianwen/rustdesk-api
|
|||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=abc123456789
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
|
volumes:
|
||||||
|
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||||
|
networks:
|
||||||
|
- rustdesk-net
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
- 如果使用***系统生成的KEY***或者***自定义KEY_PUB,KEY_PRIV***,不需要修改启动脚本,但要在生成KEY后获取到KEY再`docker-compose up -d`
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
rustdesk-net:
|
||||||
|
external: false
|
||||||
|
services:
|
||||||
|
rustdesk-server:
|
||||||
|
container_name: rustdesk-server
|
||||||
|
ports:
|
||||||
|
- 21115:21115
|
||||||
|
- 21116:21116
|
||||||
|
- 21116:21116/udp
|
||||||
|
- 21117:21117
|
||||||
|
- 21118:21118
|
||||||
|
- 21119:21119
|
||||||
|
image: rustdesk/rustdesk-server-s6:latest
|
||||||
|
environment:
|
||||||
|
- RELAY=192.168.1.66:21117
|
||||||
|
- ENCRYPTED_ONLY=1
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
restart: unless-stopped
|
||||||
|
rustdesk-api:
|
||||||
|
container_name: rustdesk-api
|
||||||
|
ports:
|
||||||
|
- 21114:21114
|
||||||
|
image: lejianwen/rustdesk-api
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
|
- RUSTDESK_API_RUSTDESK_KEY=<key> #系统生成的KEY
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/api:/app/data #将数据库挂载
|
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 下载release直接运行
|
#### 下载release直接运行
|
||||||
|
|
||||||
下载地址[release](https://github.com/lejianwen/rustdesk-api/releases)
|
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
|
||||||
|
|
||||||
#### 源码安装
|
#### 源码安装
|
||||||
|
|
||||||
@@ -379,7 +448,22 @@ lejianwen/rustdesk-api
|
|||||||
|
|
||||||
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
|
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
|
||||||
|
|
||||||
|
#### nginx反代
|
||||||
|
在`nginx`中配置反代
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
listen <your port>;
|
||||||
|
server_name <your server>;
|
||||||
|
location / {
|
||||||
|
proxy_pass http://<api-server[:port]>;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
## 其他
|
## 其他
|
||||||
|
|
||||||
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
||||||
- [webclient](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
- [webclient来源](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
||||||
185
README_EN.md
185
README_EN.md
@@ -29,34 +29,64 @@ desktop software that provides self-hosted solutions.
|
|||||||
- OAuth Management
|
- OAuth Management
|
||||||
- Quick access to web client
|
- Quick access to web client
|
||||||
- i18n
|
- i18n
|
||||||
|
- Share to guest by web client
|
||||||
- Web Client
|
- Web Client
|
||||||
- Automatically obtain API server
|
- Automatically obtain API server
|
||||||
- Automatically obtain ID server and KEY
|
- Automatically obtain ID server and KEY
|
||||||
- Automatically obtain address book
|
- Automatically obtain address book
|
||||||
|
- Visitors are remotely to the device via a temporary sharing link
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
### [Rustdesk](https://github.com/rustdesk/rustdesk)
|
### [Rustdesk](https://github.com/rustdesk/rustdesk)
|
||||||
|
|
||||||
1. The PC client version used is ***1.3.0***, and versions ***1.2.6+*** have been tested to work.
|
|
||||||
2. The server must specify a key, and not use the auto-generated key, otherwise there may be connection failures or
|
|
||||||
timeouts.
|
|
||||||
|
|
||||||
|
#### The PC client uses version ***1.3.0***, and versions ***1.2.6+*** have been tested to work.
|
||||||
|
|
||||||
|
#### Solutions for PC client connection timeout or connection issues
|
||||||
|
##### Connection issues or timeouts
|
||||||
|
Because the server version lags behind the client version, the server does not respond to the client's `secure_tcp` request, causing the client to timeout.
|
||||||
|
Relevant code can be found at `https://github.com/rustdesk/rustdesk/blob/master/src/client.rs#L322`
|
||||||
|
```rust
|
||||||
|
if !key.is_empty() && !token.is_empty() {
|
||||||
|
// mainly for the security of token
|
||||||
|
allow_err!(secure_tcp(&mut socket, key).await);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As seen, when both `key` and `token` are not empty, `secure_tcp` is called, but the server does not respond, causing the client to timeout.
|
||||||
|
The `secure_tcp` code is located at `https://github.com/rustdesk/rustdesk/blob/master/src/common.rs#L1203`
|
||||||
|
|
||||||
|
##### Four Solutions
|
||||||
|
1. Specify the key on the server.
|
||||||
|
- Advantage: Simple
|
||||||
|
- Disadvantage: The connection is not encrypted
|
||||||
```bash
|
```bash
|
||||||
hbbs -r <relay-server-ip[:port]> -k <key>
|
hbbs -r <relay-server-ip[:port]> -k <key>
|
||||||
hbbr -k <key>
|
hbbr -k <key>
|
||||||
```
|
```
|
||||||
|
For example
|
||||||
Example:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hbbs -r <relay-server-ip[:port]> -k abc1234567
|
hbbs -r <relay-server-ip[:port]> -k abc1234567
|
||||||
hbbr -k abc1234567
|
hbbr -k abc1234567
|
||||||
```
|
```
|
||||||
|
2. Use a system-generated key or a custom key pair on the server. If the client is already logged in, it may timeout or fail to connect. Logging out and reconnecting usually resolves the issue, and the web client does not need to log out.
|
||||||
|
- Advantage: Encrypted connection
|
||||||
|
- Disadvantage: Complicated operation
|
||||||
|
3. Use a system-generated key or a custom key pair on the server, fork the official client code to modify `secure_tcp` to return directly, then compile using `Github Actions` and download the compiled client.
|
||||||
|
Refer to [official documentation](https://rustdesk.com/docs/en/dev/build/all/)
|
||||||
|
- Advantage: Encrypted connection, customizable client features, ready to use after compilation
|
||||||
|
- Disadvantage: Requires forking code and compiling, which can be challenging
|
||||||
|
4. Use [my forked code](https://github.com/lejianwen/rustdesk), which has already modified `secure_tcp`. You can download and use it directly from [here](https://github.com/lejianwen/rustdesk/releases)
|
||||||
|
- Advantage: Code changes are viewable, compiled with `Github Actions`, encrypted connection, ready to use
|
||||||
|
- Disadvantage: May not keep up with official version updates
|
||||||
|
|
||||||
|
***If encryption is not a high priority, use `1`. If encryption is important, use `3` or `4`.***
|
||||||
|
|
||||||
## Overview
|
## 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 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.
|
||||||
|
|
||||||
#### Login
|
#### Login
|
||||||
|
|
||||||
@@ -70,17 +100,18 @@ desktop software that provides self-hosted solutions.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Groups: Groups are divided into `shared groups` and `regular groups`. In shared groups, everyone can see the peers of all group members, while in regular groups, only administrators can see all members' peers.
|
#### Groups
|
||||||
|
Groups are divided into `shared groups` and `regular groups`. In shared groups, everyone can see the peers of all group members, while in regular groups, only administrators can see all members' peers.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Web Admin
|
### Web Admin
|
||||||
|
|
||||||
***The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and
|
* 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)***
|
displaying data.Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
|
||||||
|
|
||||||
***Admin panel URL: `http://<your server[:port]>/_admin/`. The default username and password for the initial
|
* Admin panel URL: `http://<your server[:port]>/_admin/`. The default username and password for the initial
|
||||||
installation are `admin` `admin`, please change the password immediately.***
|
installation are `admin` `admin`, please change the password immediately.
|
||||||
|
|
||||||
1. Admin interface:
|
1. Admin interface:
|
||||||

|

|
||||||
@@ -90,7 +121,7 @@ installation are `admin` `admin`, please change the password immediately.***
|
|||||||

|

|
||||||
3. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
|
3. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
|
||||||

|

|
||||||
4. You can open the web client directly for convenience:
|
4. You can directly open the web client for convenient use; it can also be shared with guests, allowing them to remotely access the device via the web client.
|
||||||

|

|
||||||
5. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in
|
5. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in
|
||||||
the admin
|
the admin
|
||||||
@@ -126,6 +157,8 @@ installation are `admin` `admin`, please change the password immediately.***
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
lang: "en"
|
lang: "en"
|
||||||
|
app:
|
||||||
|
web-client: 1 # web client route 1:open 0:close
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release"
|
mode: "release"
|
||||||
@@ -146,29 +179,33 @@ rustdesk:
|
|||||||
api-server: "http://192.168.1.66:21114"
|
api-server: "http://192.168.1.66:21114"
|
||||||
key: "123456789"
|
key: "123456789"
|
||||||
personal: 1
|
personal: 1
|
||||||
|
logger:
|
||||||
|
path: "./runtime/log.txt"
|
||||||
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
|
report-caller: true
|
||||||
```
|
```
|
||||||
|
|
||||||
* Environment variables, with the prefix `RUSTDESK_API_RUSTDESK_PERSONAL`, will override the settings in the
|
### Environment Variables
|
||||||
configuration file if
|
The prefix for variable names is `RUSTDESK_API`. If environment variables exist, they will override the configurations in the configuration file.
|
||||||
present.
|
|
||||||
|
|
||||||
| Variable Name | Description | Example |
|
| Variable Name | Description | Example |
|
||||||
|------------------------------------|-----------------------------------------------------------|--------------------------------|
|
|------------------------------------|-----------------------------------------------------------|-------------------------------|
|
||||||
| TZ | timezone | Asia/Shanghai |
|
| TZ | timezone | Asia/Shanghai |
|
||||||
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
||||||
| ----- GIN Configuration ----- | --------------------------------------- | ------------------------------ |
|
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, deault 1 | 1 |
|
||||||
|
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
||||||
| ----- GORM Configuration ----- | --------------------------------------- | ------------------------------ |
|
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
| 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_IDLE_CONNS | Maximum idle connections | 10 |
|
||||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
||||||
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
||||||
| ----- MYSQL Configuration ----- | --------------------------------------- | ------------------------------ |
|
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
||||||
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
||||||
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
||||||
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
||||||
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ------------------------------ |
|
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
| 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_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_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
||||||
@@ -188,23 +225,22 @@ docker run -d --name rustdesk-api -p 21114:21114 \
|
|||||||
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
-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_RELAY_SERVER=192.168.1.66:21117 \
|
||||||
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
||||||
-e RUSTDESK_API_RUSTDESK_KEY=123456789 \
|
-e RUSTDESK_API_RUSTDESK_KEY=abc123456 \
|
||||||
lejianwen/rustdesk-api
|
lejianwen/rustdesk-api
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Using `docker-compose`
|
2. Using `docker-compose`
|
||||||
|
|
||||||
- Simple example:
|
- Simple example:
|
||||||
|
```yaml
|
||||||
```docker-compose
|
|
||||||
services:
|
services:
|
||||||
rustdesk-api:
|
rustdesk-api:
|
||||||
container_name: rustdesk-api
|
container_name: rustdesk-api
|
||||||
environment:
|
environment:
|
||||||
|
- RUSTDESK_API_LANG=en
|
||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
ports:
|
ports:
|
||||||
- 21114:21114
|
- 21114:21114
|
||||||
image: lejianwen/rustdesk-api
|
image: lejianwen/rustdesk-api
|
||||||
@@ -216,8 +252,8 @@ lejianwen/rustdesk-api
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Example with RustDesk's official Docker Compose file, adding your `rustdesk-api` service:
|
- Example with RustDesk's official Docker Compose file, adding your `rustdesk-api` service:
|
||||||
|
- If you are using a system-generated KEY, remove the `-k <key>` parameter. However, after the first startup, run `docker-compose logs hbbs` or `cat ./data/id_ed25519.pub` to view the KEY, then modify `RUSTDESK_API_RUSTDESK_KEY=<key>` and execute `docker-compose up -d` again.
|
||||||
```docker-compose
|
```yaml
|
||||||
networks:
|
networks:
|
||||||
rustdesk-net:
|
rustdesk-net:
|
||||||
external: false
|
external: false
|
||||||
@@ -229,11 +265,10 @@ lejianwen/rustdesk-api
|
|||||||
- 21116:21116 # 自定义 hbbs 映射端口
|
- 21116:21116 # 自定义 hbbs 映射端口
|
||||||
- 21116:21116/udp # 自定义 hbbs 映射端口
|
- 21116:21116/udp # 自定义 hbbs 映射端口
|
||||||
- 21118:21118 # web client
|
- 21118:21118 # web client
|
||||||
- 21119:21119 # web client
|
|
||||||
image: rustdesk/rustdesk-server
|
image: rustdesk/rustdesk-server
|
||||||
command: hbbs -r <relay-server-ip[:port]> -k 123456789 # 填入个人域名或 IP + hbbr 暴露端口
|
command: hbbs -r <relay-server-ip[:port]> -k <key> # 填入个人域名或 IP + hbbr 暴露端口
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/hbbs:/root # 自定义挂载目录
|
- ./data:/root # 自定义挂载目录
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -247,11 +282,11 @@ lejianwen/rustdesk-api
|
|||||||
container_name: hbbr
|
container_name: hbbr
|
||||||
ports:
|
ports:
|
||||||
- 21117:21117 # 自定义 hbbr 映射端口
|
- 21117:21117 # 自定义 hbbr 映射端口
|
||||||
|
- 21119:21119 # web client
|
||||||
image: rustdesk/rustdesk-server
|
image: rustdesk/rustdesk-server
|
||||||
command: hbbr -k 123456789
|
command: hbbr -k <key>
|
||||||
#command: hbbr
|
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/hbbr:/root # 自定义挂载目录
|
- ./data:/root
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -262,10 +297,11 @@ lejianwen/rustdesk-api
|
|||||||
rustdesk-api:
|
rustdesk-api:
|
||||||
container_name: rustdesk-api
|
container_name: rustdesk-api
|
||||||
environment:
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
ports:
|
ports:
|
||||||
- 21114:21114
|
- 21114:21114
|
||||||
image: lejianwen/rustdesk-api
|
image: lejianwen/rustdesk-api
|
||||||
@@ -274,13 +310,11 @@ lejianwen/rustdesk-api
|
|||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
```
|
```
|
||||||
- If you are using an S6 image, you need to modify the startup script `/etc/s6-overlay/s6-rc.d/hbbr/run`
|
|
||||||
and `/etc/s6-overlay/s6-rc.d/hbbr/run`
|
|
||||||
|
|
||||||
1. create `hbbr/run`
|
|
||||||
|
|
||||||
|
- S6 image
|
||||||
|
- - If using ***custom KEY***, you will need to modify the startup script to override the `/etc/s6-overlay/s6-rc.d/hbbr/run` and `/etc/s6-overlay/s6-rc.d/hbbr/run` in the image.
|
||||||
|
1. Create `hbbr/run`, only needed for custom KEY
|
||||||
```bash
|
```bash
|
||||||
#!/command/with-contenv sh
|
#!/command/with-contenv sh
|
||||||
cd /data
|
cd /data
|
||||||
@@ -288,8 +322,7 @@ lejianwen/rustdesk-api
|
|||||||
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
||||||
/usr/bin/hbbr $PARAMS
|
/usr/bin/hbbr $PARAMS
|
||||||
```
|
```
|
||||||
|
2. Create `hbbs/run`, only needed for custom KEY
|
||||||
2. create `hbbs/run`
|
|
||||||
```bash
|
```bash
|
||||||
#!/command/with-contenv sh
|
#!/command/with-contenv sh
|
||||||
sleep 2
|
sleep 2
|
||||||
@@ -298,8 +331,8 @@ lejianwen/rustdesk-api
|
|||||||
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
||||||
/usr/bin/hbbs -r $RELAY $PARAMS
|
/usr/bin/hbbs -r $RELAY $PARAMS
|
||||||
```
|
```
|
||||||
3. edit `docker-compose.yml`
|
3. Modify the `s6` section in `docker-compose.yml`
|
||||||
```
|
```yaml
|
||||||
networks:
|
networks:
|
||||||
rustdesk-net:
|
rustdesk-net:
|
||||||
external: false
|
external: false
|
||||||
@@ -317,7 +350,7 @@ lejianwen/rustdesk-api
|
|||||||
environment:
|
environment:
|
||||||
- RELAY=192.168.1.66:21117
|
- RELAY=192.168.1.66:21117
|
||||||
- ENCRYPTED_ONLY=1
|
- ENCRYPTED_ONLY=1
|
||||||
- KEY=abc123456789
|
- KEY=<key> #KEY
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
||||||
@@ -333,9 +366,48 @@ lejianwen/rustdesk-api
|
|||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=abc123456789
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/api:/app/data #将数据库挂载
|
- /data/rustdesk/api:/app/data
|
||||||
|
networks:
|
||||||
|
- rustdesk-net
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
- If using ***system-generated KEY*** or ***custom KEY_PUB, KEY_PRIV***, you do not need to modify the startup script, but you need to obtain the KEY after it is generated and then run `docker-compose up -d`
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
rustdesk-net:
|
||||||
|
external: false
|
||||||
|
services:
|
||||||
|
rustdesk-server:
|
||||||
|
container_name: rustdesk-server
|
||||||
|
ports:
|
||||||
|
- 21115:21115
|
||||||
|
- 21116:21116
|
||||||
|
- 21116:21116/udp
|
||||||
|
- 21117:21117
|
||||||
|
- 21118:21118
|
||||||
|
- 21119:21119
|
||||||
|
image: rustdesk/rustdesk-server-s6:latest
|
||||||
|
environment:
|
||||||
|
- RELAY=192.168.1.66:21117
|
||||||
|
- ENCRYPTED_ONLY=1
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
restart: unless-stopped
|
||||||
|
rustdesk-api:
|
||||||
|
container_name: rustdesk-api
|
||||||
|
ports:
|
||||||
|
- 21114:21114
|
||||||
|
image: lejianwen/rustdesk-api
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
|
volumes:
|
||||||
|
- /data/rustdesk/api:/app/data
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -388,7 +460,22 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
|
|||||||
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
|
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
|
||||||
change the password promptly.
|
change the password promptly.
|
||||||
|
|
||||||
## Miscellaneous
|
#### nginx reverse proxy
|
||||||
|
Configure reverse proxy in `nginx`
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
listen <your port>;
|
||||||
|
server_name <your server>;
|
||||||
|
location / {
|
||||||
|
proxy_pass http://<api-server[:port]>;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Others
|
||||||
|
|
||||||
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
||||||
- [webclient](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
- [Web client source](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
lang: "zh-CN"
|
lang: "zh-CN"
|
||||||
|
app:
|
||||||
|
web-client: 1 # 1:启用 0:禁用
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release" #release,debug,test
|
mode: "release" #release,debug,test
|
||||||
@@ -16,7 +18,7 @@ mysql:
|
|||||||
rustdesk:
|
rustdesk:
|
||||||
id-server: "192.168.1.66:21116"
|
id-server: "192.168.1.66:21116"
|
||||||
relay-server: "192.168.1.66:21117"
|
relay-server: "192.168.1.66:21117"
|
||||||
api-server: "http://192.168.1.66:21114"
|
api-server: "http://127.0.0.1:21114"
|
||||||
key: "123456789"
|
key: "123456789"
|
||||||
personal: 1
|
personal: 1
|
||||||
logger:
|
logger:
|
||||||
|
|||||||
@@ -14,8 +14,13 @@ const (
|
|||||||
DefaultConfig = "conf/config.yaml"
|
DefaultConfig = "conf/config.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
WebClient int `mapstructure:"web-client"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Lang string `mapstructure:"lang"`
|
Lang string `mapstructure:"lang"`
|
||||||
|
App App
|
||||||
Gorm Gorm
|
Gorm Gorm
|
||||||
Mysql Mysql
|
Mysql Mysql
|
||||||
Gin Gin
|
Gin Gin
|
||||||
|
|||||||
@@ -244,6 +244,51 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/address_book/share": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "地址簿分享",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"地址簿"
|
||||||
|
],
|
||||||
|
"summary": "地址簿分享",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "地址簿信息",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/admin.ShareByWebClientForm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/address_book/update": {
|
"/admin/address_book/update": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -301,6 +346,40 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/app-config": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "APP服务配置",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"ADMIN"
|
||||||
|
],
|
||||||
|
"summary": "APP服务配置",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/file/oss_token": {
|
"/admin/file/oss_token": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1371,6 +1450,18 @@ const docTemplateadmin = `{
|
|||||||
"description": "时间",
|
"description": "时间",
|
||||||
"name": "time_ago",
|
"name": "time_ago",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID",
|
||||||
|
"name": "id",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "主机名",
|
||||||
|
"name": "hostname",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -1475,7 +1566,7 @@ const docTemplateadmin = `{
|
|||||||
"tags": [
|
"tags": [
|
||||||
"ADMIN"
|
"ADMIN"
|
||||||
],
|
],
|
||||||
"summary": "服务配置",
|
"summary": "RUSTDESK服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -2456,6 +2547,33 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"admin.ShareByWebClientForm": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"password",
|
||||||
|
"password_type"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"expire": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password_type": {
|
||||||
|
"description": "只能是once,fixed",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"once",
|
||||||
|
"fixed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"admin.TagForm": {
|
"admin.TagForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|||||||
@@ -237,6 +237,51 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/address_book/share": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "地址簿分享",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"地址簿"
|
||||||
|
],
|
||||||
|
"summary": "地址簿分享",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "地址簿信息",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/admin.ShareByWebClientForm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/address_book/update": {
|
"/admin/address_book/update": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -294,6 +339,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/app-config": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "APP服务配置",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"ADMIN"
|
||||||
|
],
|
||||||
|
"summary": "APP服务配置",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/file/oss_token": {
|
"/admin/file/oss_token": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1364,6 +1443,18 @@
|
|||||||
"description": "时间",
|
"description": "时间",
|
||||||
"name": "time_ago",
|
"name": "time_ago",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID",
|
||||||
|
"name": "id",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "主机名",
|
||||||
|
"name": "hostname",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -1468,7 +1559,7 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"ADMIN"
|
"ADMIN"
|
||||||
],
|
],
|
||||||
"summary": "服务配置",
|
"summary": "RUSTDESK服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -2449,6 +2540,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"admin.ShareByWebClientForm": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"password",
|
||||||
|
"password_type"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"expire": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password_type": {
|
||||||
|
"description": "只能是once,fixed",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"once",
|
||||||
|
"fixed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"admin.TagForm": {
|
"admin.TagForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
|||||||
@@ -141,6 +141,25 @@ definitions:
|
|||||||
version:
|
version:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
admin.ShareByWebClientForm:
|
||||||
|
properties:
|
||||||
|
expire:
|
||||||
|
type: integer
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
password_type:
|
||||||
|
description: 只能是once,fixed
|
||||||
|
enum:
|
||||||
|
- once
|
||||||
|
- fixed
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- password
|
||||||
|
- password_type
|
||||||
|
type: object
|
||||||
admin.TagForm:
|
admin.TagForm:
|
||||||
properties:
|
properties:
|
||||||
color:
|
color:
|
||||||
@@ -618,6 +637,34 @@ paths:
|
|||||||
summary: 地址簿列表
|
summary: 地址簿列表
|
||||||
tags:
|
tags:
|
||||||
- 地址簿
|
- 地址簿
|
||||||
|
/admin/address_book/share:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 地址簿分享
|
||||||
|
parameters:
|
||||||
|
- description: 地址簿信息
|
||||||
|
in: body
|
||||||
|
name: body
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/admin.ShareByWebClientForm'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
security:
|
||||||
|
- token: []
|
||||||
|
summary: 地址簿分享
|
||||||
|
tags:
|
||||||
|
- 地址簿
|
||||||
/admin/address_book/update:
|
/admin/address_book/update:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -651,6 +698,27 @@ paths:
|
|||||||
summary: 地址簿编辑
|
summary: 地址簿编辑
|
||||||
tags:
|
tags:
|
||||||
- 地址簿
|
- 地址簿
|
||||||
|
/admin/app-config:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: APP服务配置
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
security:
|
||||||
|
- token: []
|
||||||
|
summary: APP服务配置
|
||||||
|
tags:
|
||||||
|
- ADMIN
|
||||||
/admin/file/oss_token:
|
/admin/file/oss_token:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -1283,6 +1351,14 @@ paths:
|
|||||||
in: query
|
in: query
|
||||||
name: time_ago
|
name: time_ago
|
||||||
type: integer
|
type: integer
|
||||||
|
- description: ID
|
||||||
|
in: query
|
||||||
|
name: id
|
||||||
|
type: string
|
||||||
|
- description: 主机名
|
||||||
|
in: query
|
||||||
|
name: hostname
|
||||||
|
type: string
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -1355,7 +1431,7 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- token: []
|
- token: []
|
||||||
summary: 服务配置
|
summary: RUSTDESK服务配置
|
||||||
tags:
|
tags:
|
||||||
- ADMIN
|
- ADMIN
|
||||||
/admin/tag/create:
|
/admin/tag/create:
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 46 KiB |
@@ -945,13 +945,37 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/shared-peer": {
|
||||||
|
"post": {
|
||||||
|
"description": "分享的peer",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"WEBCLIENT"
|
||||||
|
],
|
||||||
|
"summary": "分享的peer",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/sysinfo": {
|
"/sysinfo": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "提交系统信息",
|
"description": "提交系统信息",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
|
|||||||
@@ -938,13 +938,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/shared-peer": {
|
||||||
|
"post": {
|
||||||
|
"description": "分享的peer",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"WEBCLIENT"
|
||||||
|
],
|
||||||
|
"summary": "分享的peer",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/sysinfo": {
|
"/sysinfo": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "提交系统信息",
|
"description": "提交系统信息",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
|
|||||||
@@ -727,6 +727,25 @@ paths:
|
|||||||
summary: 服务配置
|
summary: 服务配置
|
||||||
tags:
|
tags:
|
||||||
- WEBCLIENT
|
- WEBCLIENT
|
||||||
|
/shared-peer:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 分享的peer
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
summary: 分享的peer
|
||||||
|
tags:
|
||||||
|
- WEBCLIENT
|
||||||
/sysinfo:
|
/sysinfo:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -750,8 +769,6 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
summary: 提交系统信息
|
summary: 提交系统信息
|
||||||
tags:
|
tags:
|
||||||
- 地址
|
- 地址
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 50 KiB |
@@ -7,6 +7,7 @@ import (
|
|||||||
adResp "Gwen/http/response/admin"
|
adResp "Gwen/http/response/admin"
|
||||||
"Gwen/model"
|
"Gwen/model"
|
||||||
"Gwen/service"
|
"Gwen/service"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,18 +29,21 @@ func (ct *Login) Login(c *gin.Context) {
|
|||||||
f := &admin.Login{}
|
f := &admin.Login{}
|
||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), c.ClientIP()))
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errList := global.Validator.ValidStruct(c, f)
|
errList := global.Validator.ValidStruct(c, f)
|
||||||
if len(errList) > 0 {
|
if len(errList) > 0 {
|
||||||
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), c.ClientIP()))
|
||||||
response.Fail(c, 101, errList[0])
|
response.Fail(c, 101, errList[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
||||||
|
|
||||||
if u.Id == 0 {
|
if u.Id == 0 {
|
||||||
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), c.ClientIP()))
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ func (ct *Peer) Create(c *gin.Context) {
|
|||||||
// @Param page query int false "页码"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "页大小"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param time_ago query int false "时间"
|
// @Param time_ago query int false "时间"
|
||||||
|
// @Param id query string false "ID"
|
||||||
|
// @Param hostname query string false "主机名"
|
||||||
// @Success 200 {object} response.Response{data=model.PeerList}
|
// @Success 200 {object} response.Response{data=model.PeerList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/peer/list [get]
|
// @Router /admin/peer/list [get]
|
||||||
@@ -96,6 +98,12 @@ func (ct *Peer) List(c *gin.Context) {
|
|||||||
lt := time.Now().Unix() + int64(query.TimeAgo)
|
lt := time.Now().Unix() + int64(query.TimeAgo)
|
||||||
tx.Where("last_online_time > ?", lt)
|
tx.Where("last_online_time > ?", lt)
|
||||||
}
|
}
|
||||||
|
if query.Id != "" {
|
||||||
|
tx.Where("id like ?", "%"+query.Id+"%")
|
||||||
|
}
|
||||||
|
if query.Hostname != "" {
|
||||||
|
tx.Where("hostname like ?", "%"+query.Hostname+"%")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
type Rustdesk struct {
|
type Rustdesk struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig 服务配置
|
// ServerConfig RUSTDESK服务配置
|
||||||
// @Tags ADMIN
|
// @Tags ADMIN
|
||||||
// @Summary 服务配置
|
// @Summary RUSTDESK服务配置
|
||||||
// @Description 服务配置,给webclient提供api-server
|
// @Description 服务配置,给webclient提供api-server
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
@@ -28,3 +28,19 @@ func (r *Rustdesk) ServerConfig(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
response.Success(c, cf)
|
response.Success(c, cf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppConfig APP服务配置
|
||||||
|
// @Tags ADMIN
|
||||||
|
// @Summary APP服务配置
|
||||||
|
// @Description APP服务配置
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 500 {object} response.Response
|
||||||
|
// @Router /admin/app-config [get]
|
||||||
|
// @Security token
|
||||||
|
func (r *Rustdesk) AppConfig(c *gin.Context) {
|
||||||
|
response.Success(c, &gin.H{
|
||||||
|
"web_client": global.Config.App.WebClient,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"Gwen/model"
|
"Gwen/model"
|
||||||
"Gwen/service"
|
"Gwen/service"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -394,7 +393,7 @@ func (a *Ab) PTags(c *gin.Context) {
|
|||||||
// @Router /ab/peer/add/{guid} [post]
|
// @Router /ab/peer/add/{guid} [post]
|
||||||
// @Security BearerAuth
|
// @Security BearerAuth
|
||||||
func (a *Ab) PeerAdd(c *gin.Context) {
|
func (a *Ab) PeerAdd(c *gin.Context) {
|
||||||
// forceAlwaysRelay永远是字符串"false",真是坑
|
// forceAlwaysRelay永远是字符串"false"
|
||||||
//f := &gin.H{}
|
//f := &gin.H{}
|
||||||
f := &requstform.PersonalAddressBookForm{}
|
f := &requstform.PersonalAddressBookForm{}
|
||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
@@ -402,10 +401,20 @@ func (a *Ab) PeerAdd(c *gin.Context) {
|
|||||||
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(f)
|
//fmt.Println(f)
|
||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
f.UserId = u.Id
|
f.UserId = u.Id
|
||||||
ab := f.ToAddressBook()
|
ab := f.ToAddressBook()
|
||||||
|
|
||||||
|
if ab.Platform == "" || ab.Username == "" || ab.Hostname == "" {
|
||||||
|
peer := service.AllService.PeerService.FindById(ab.Id)
|
||||||
|
if peer.RowId != 0 {
|
||||||
|
ab.Platform = service.AllService.AddressBookService.PlatformFromOs(peer.Os)
|
||||||
|
ab.Username = peer.Username
|
||||||
|
ab.Hostname = peer.Hostname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = service.AllService.AddressBookService.AddAddressBook(ab)
|
err = service.AllService.AddressBookService.AddAddressBook(ab)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"Gwen/model"
|
"Gwen/model"
|
||||||
"Gwen/service"
|
"Gwen/service"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
@@ -30,12 +31,14 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
//fmt.Println(f)
|
//fmt.Println(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), c.ClientIP()))
|
||||||
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errList := global.Validator.ValidStruct(c, f)
|
errList := global.Validator.ValidStruct(c, f)
|
||||||
if len(errList) > 0 {
|
if len(errList) > 0 {
|
||||||
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), c.ClientIP()))
|
||||||
response.Error(c, errList[0])
|
response.Error(c, errList[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -43,6 +46,7 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
||||||
|
|
||||||
if u.Id == 0 {
|
if u.Id == 0 {
|
||||||
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), c.ClientIP()))
|
||||||
response.Error(c, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
response.Error(c, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ type Peer struct {
|
|||||||
// @Success 200 {string} string "SYSINFO_UPDATED,ID_NOT_FOUND"
|
// @Success 200 {string} string "SYSINFO_UPDATED,ID_NOT_FOUND"
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /sysinfo [post]
|
// @Router /sysinfo [post]
|
||||||
// @Security BearerAuth
|
|
||||||
func (p *Peer) SysInfo(c *gin.Context) {
|
func (p *Peer) SysInfo(c *gin.Context) {
|
||||||
f := &requstform.PeerForm{}
|
f := &requstform.PeerForm{}
|
||||||
err := c.ShouldBindBodyWith(f, binding.JSON)
|
err := c.ShouldBindBodyWith(f, binding.JSON)
|
||||||
@@ -30,17 +29,28 @@ func (p *Peer) SysInfo(c *gin.Context) {
|
|||||||
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fpe := f.ToPeer()
|
||||||
pe := service.AllService.PeerService.FindById(f.Id)
|
pe := service.AllService.PeerService.FindById(f.Id)
|
||||||
if pe == nil || pe.RowId == 0 {
|
if pe.RowId == 0 {
|
||||||
pe = f.ToPeer()
|
pe = f.ToPeer()
|
||||||
|
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid)
|
||||||
err = service.AllService.PeerService.Create(pe)
|
err = service.AllService.PeerService.Create(pe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if pe.UserId == 0 {
|
||||||
|
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid)
|
||||||
|
}
|
||||||
|
fpe.RowId = pe.RowId
|
||||||
|
fpe.UserId = pe.UserId
|
||||||
|
err = service.AllService.PeerService.Update(fpe)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//SYSINFO_UPDATED 上传成功
|
//SYSINFO_UPDATED 上传成功
|
||||||
//ID_NOT_FOUND 下次心跳会上传
|
//ID_NOT_FOUND 下次心跳会上传
|
||||||
//直接响应文本
|
//直接响应文本
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
func RustAuth() gin.HandlerFunc {
|
func RustAuth() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
//fmt.Println(c.Request.Header)
|
//fmt.Println(c.Request.URL, c.Request.Header)
|
||||||
//获取HTTP_AUTHORIZATION
|
//获取HTTP_AUTHORIZATION
|
||||||
token := c.GetHeader("Authorization")
|
token := c.GetHeader("Authorization")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
|
|||||||
@@ -36,4 +36,6 @@ func (f *PeerForm) ToPeer() *model.Peer {
|
|||||||
type PeerQuery struct {
|
type PeerQuery struct {
|
||||||
PageQuery
|
PageQuery
|
||||||
TimeAgo int `json:"time_ago" form:"time_ago"`
|
TimeAgo int `json:"time_ago" form:"time_ago"`
|
||||||
|
Id string `json:"id" form:"id"`
|
||||||
|
Hostname string `json:"hostname" form:"hostname"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ func Init(g *gin.Engine) {
|
|||||||
|
|
||||||
rs := &admin.Rustdesk{}
|
rs := &admin.Rustdesk{}
|
||||||
adg.GET("/server-config", rs.ServerConfig)
|
adg.GET("/server-config", rs.ServerConfig)
|
||||||
|
adg.GET("/app-config", rs.AppConfig)
|
||||||
|
|
||||||
//访问静态文件
|
//访问静态文件
|
||||||
//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
|
//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
|
||||||
|
|||||||
@@ -47,17 +47,11 @@ func ApiInit(g *gin.Engine) {
|
|||||||
frg.POST("/sysinfo", pe.SysInfo)
|
frg.POST("/sysinfo", pe.SysInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if global.Config.App.WebClient == 1 {
|
||||||
w := &api.WebClient{}
|
WebClientRoutes(frg)
|
||||||
frg.POST("/shared-peer", w.SharedPeer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frg.Use(middleware.RustAuth())
|
frg.Use(middleware.RustAuth())
|
||||||
{
|
|
||||||
w := &api.WebClient{}
|
|
||||||
frg.POST("/server-config", w.ServerConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
u := &api.User{}
|
u := &api.User{}
|
||||||
frg.GET("/user/info", u.Info)
|
frg.GET("/user/info", u.Info)
|
||||||
@@ -115,3 +109,14 @@ func PersonalRoutes(frg *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WebClientRoutes(frg *gin.RouterGroup) {
|
||||||
|
w := &api.WebClient{}
|
||||||
|
{
|
||||||
|
frg.POST("/shared-peer", w.SharedPeer)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
frg.POST("/server-config", middleware.RustAuth(), w.ServerConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ import (
|
|||||||
func WebInit(g *gin.Engine) {
|
func WebInit(g *gin.Engine) {
|
||||||
i := &web.Index{}
|
i := &web.Index{}
|
||||||
g.GET("/", i.Index)
|
g.GET("/", i.Index)
|
||||||
|
|
||||||
|
if global.Config.App.WebClient == 1 {
|
||||||
g.GET("/webclient-config/index.js", i.ConfigJs)
|
g.GET("/webclient-config/index.js", i.ConfigJs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if global.Config.App.WebClient == 1 {
|
||||||
g.StaticFS("/webclient", http.Dir(global.Config.Gin.ResourcesPath+"/web"))
|
g.StaticFS("/webclient", http.Dir(global.Config.Gin.ResourcesPath+"/web"))
|
||||||
|
}
|
||||||
g.StaticFS("/_admin", http.Dir(global.Config.Gin.ResourcesPath+"/admin"))
|
g.StaticFS("/_admin", http.Dir(global.Config.Gin.ResourcesPath+"/admin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ type SqliteConfig struct {
|
|||||||
|
|
||||||
func NewSqlite(sqliteConf *SqliteConfig) *gorm.DB {
|
func NewSqlite(sqliteConf *SqliteConfig) *gorm.DB {
|
||||||
db, err := gorm.Open(sqlite.Open("./data/rustdeskapi.db"), &gorm.Config{
|
db, err := gorm.Open(sqlite.Open("./data/rustdeskapi.db"), &gorm.Config{
|
||||||
|
DisableForeignKeyConstraintWhenMigrating: true,
|
||||||
Logger: logger.New(
|
Logger: logger.New(
|
||||||
global.Logger, // io writer
|
global.Logger, // io writer
|
||||||
logger.Config{
|
logger.Config{
|
||||||
|
|||||||
4
resources/web/js/dist/index.js
vendored
4
resources/web/js/dist/index.js
vendored
File diff suppressed because one or more lines are too long
29
resources/web/js/src/globals.js
vendored
29
resources/web/js/src/globals.js
vendored
@@ -1,11 +1,14 @@
|
|||||||
import Connection from "./connection";
|
import Connection from "./connection";
|
||||||
import _sodium from "libsodium-wrappers";
|
import _sodium from "libsodium-wrappers";
|
||||||
import { CursorData } from "./message";
|
|
||||||
import {loadVp9} from "./codec";
|
import {loadVp9} from "./codec";
|
||||||
import {checkIfRetry, version} from "./gen_js_from_hbb";
|
import {checkIfRetry, version} from "./gen_js_from_hbb";
|
||||||
import {initZstd, translate} from "./common";
|
import {initZstd, translate} from "./common";
|
||||||
import PCMPlayer from "pcm-player";
|
import PCMPlayer from "pcm-player";
|
||||||
|
import {getServerConf} from "./ljw";
|
||||||
|
|
||||||
|
window.myconsole = (...args) => {
|
||||||
|
console.log(args);
|
||||||
|
}
|
||||||
window.curConn = undefined;
|
window.curConn = undefined;
|
||||||
window.isMobile = () => {
|
window.isMobile = () => {
|
||||||
return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|
return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|
||||||
@@ -126,6 +129,7 @@ export function newConn() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sodium;
|
let sodium;
|
||||||
|
|
||||||
export async function verify(signed, pk) {
|
export async function verify(signed, pk) {
|
||||||
if (!sodium) {
|
if (!sodium) {
|
||||||
await _sodium.ready;
|
await _sodium.ready;
|
||||||
@@ -178,6 +182,7 @@ export function decrypt(signed, nonce, key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.setByName = (name, value) => {
|
window.setByName = (name, value) => {
|
||||||
|
myconsole('setByName', name, value);
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'remote_id':
|
case 'remote_id':
|
||||||
localStorage.setItem('remote-id', value);
|
localStorage.setItem('remote-id', value);
|
||||||
@@ -256,6 +261,9 @@ window.setByName = (name, value) => {
|
|||||||
case 'option':
|
case 'option':
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
localStorage.setItem(value.name, value.value);
|
localStorage.setItem(value.name, value.value);
|
||||||
|
if (value.name === 'access_token' && value.value) {
|
||||||
|
getServerConf(value.value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'peer_option':
|
case 'peer_option':
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
@@ -271,6 +279,7 @@ window.setByName = (name, value) => {
|
|||||||
|
|
||||||
window.getByName = (name, arg) => {
|
window.getByName = (name, arg) => {
|
||||||
let v = _getByName(name, arg);
|
let v = _getByName(name, arg);
|
||||||
|
myconsole('getByName', name, arg, v);
|
||||||
if (typeof v == 'string' || v instanceof String) return v;
|
if (typeof v == 'string' || v instanceof String) return v;
|
||||||
if (v == undefined || v == null) return '';
|
if (v == undefined || v == null) return '';
|
||||||
return JSON.stringify(v);
|
return JSON.stringify(v);
|
||||||
@@ -299,7 +308,11 @@ function _getByName(name, arg) {
|
|||||||
case 'toggle_option':
|
case 'toggle_option':
|
||||||
return curConn.getOption(arg) || false;
|
return curConn.getOption(arg) || false;
|
||||||
case 'option':
|
case 'option':
|
||||||
return localStorage.getItem(arg);
|
const v = localStorage.getItem(arg);
|
||||||
|
if (arg === 'access_token' && v) {
|
||||||
|
getServerConf(v);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
case 'image_quality':
|
case 'image_quality':
|
||||||
return curConn.getImageQuality();
|
return curConn.getImageQuality();
|
||||||
case 'translate':
|
case 'translate':
|
||||||
@@ -336,7 +349,8 @@ window.init = async () => {
|
|||||||
opusWorker.onmessage = (e) => {
|
opusWorker.onmessage = (e) => {
|
||||||
pcmPlayer.feed(e.data);
|
pcmPlayer.feed(e.data);
|
||||||
}
|
}
|
||||||
loadVp9(() => { });
|
loadVp9(() => {
|
||||||
|
});
|
||||||
await initZstd();
|
await initZstd();
|
||||||
console.log('init done');
|
console.log('init done');
|
||||||
}
|
}
|
||||||
@@ -362,8 +376,7 @@ export function copyToClipboard(text) {
|
|||||||
// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
|
// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
|
||||||
return window.clipboardData.setData("Text", text);
|
return window.clipboardData.setData("Text", text);
|
||||||
|
|
||||||
}
|
} else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
|
||||||
else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
|
|
||||||
var textarea = document.createElement("textarea");
|
var textarea = document.createElement("textarea");
|
||||||
textarea.textContent = text;
|
textarea.textContent = text;
|
||||||
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in Microsoft Edge.
|
textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in Microsoft Edge.
|
||||||
@@ -371,12 +384,10 @@ export function copyToClipboard(text) {
|
|||||||
textarea.select();
|
textarea.select();
|
||||||
try {
|
try {
|
||||||
return document.execCommand("copy"); // Security exception may be thrown by some browsers.
|
return document.execCommand("copy"); // Security exception may be thrown by some browsers.
|
||||||
}
|
} catch (ex) {
|
||||||
catch (ex) {
|
|
||||||
console.warn("Copy to clipboard failed.", ex);
|
console.warn("Copy to clipboard failed.", ex);
|
||||||
// return prompt("Copy to clipboard: Ctrl+C, Enter", text);
|
// return prompt("Copy to clipboard: Ctrl+C, Enter", text);
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
document.body.removeChild(textarea);
|
document.body.removeChild(textarea);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
resources/web/js/src/ljw.js
vendored
21
resources/web/js/src/ljw.js
vendored
@@ -49,11 +49,13 @@ if (share_token) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fetching = false
|
||||||
const autoWriteServer = () => {
|
export function getServerConf(token){
|
||||||
return setTimeout(() => {
|
console.log('getServerConf', token)
|
||||||
const token = localStorage.getItem('access_token')
|
if(fetching){
|
||||||
if (token && apiserver) {
|
return
|
||||||
|
}
|
||||||
|
fetching = true
|
||||||
fetch(apiserver + "/api/server-config", {
|
fetch(apiserver + "/api/server-config", {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -62,12 +64,12 @@ const autoWriteServer = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
).then(res => res.json()).then(res => {
|
).then(res => res.json()).then(res => {
|
||||||
|
fetching = false
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
if (!localStorage.getItem('custom-rendezvous-server') || !localStorage.getItem('key')) {
|
if (!localStorage.getItem('custom-rendezvous-server') || !localStorage.getItem('key')) {
|
||||||
localStorage.setItem('custom-rendezvous-server', res.data.id_server)
|
localStorage.setItem('custom-rendezvous-server', res.data.id_server)
|
||||||
localStorage.setItem('key', res.data.key)
|
localStorage.setItem('key', res.data.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.data.peers) {
|
if (res.data.peers) {
|
||||||
const oldPeers = JSON.parse(localStorage.getItem('peers')) || {}
|
const oldPeers = JSON.parse(localStorage.getItem('peers')) || {}
|
||||||
let needUpdate = false
|
let needUpdate = false
|
||||||
@@ -91,10 +93,7 @@ const autoWriteServer = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}).catch(_ => {
|
||||||
|
fetching = false
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
autoWriteServer()
|
|
||||||
}
|
}
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
autoWriteServer()
|
|
||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"Gwen/model"
|
"Gwen/model"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressBookService struct {
|
type AddressBookService struct {
|
||||||
@@ -69,6 +70,14 @@ func (s *AddressBookService) UpdateAddressBook(abs []*model.AddressBook, userId
|
|||||||
ab.UserId = userId
|
ab.UserId = userId
|
||||||
if !ok {
|
if !ok {
|
||||||
//添加
|
//添加
|
||||||
|
if ab.Platform == "" || ab.Username == "" || ab.Hostname == "" {
|
||||||
|
peer := AllService.PeerService.FindById(ab.Id)
|
||||||
|
if peer.RowId != 0 {
|
||||||
|
ab.Platform = AllService.AddressBookService.PlatformFromOs(peer.Os)
|
||||||
|
ab.Username = peer.Username
|
||||||
|
ab.Hostname = peer.Hostname
|
||||||
|
}
|
||||||
|
}
|
||||||
tx.Create(ab)
|
tx.Create(ab)
|
||||||
} else {
|
} else {
|
||||||
//更新
|
//更新
|
||||||
@@ -127,3 +136,20 @@ func (t *AddressBookService) SharedPeer(shareToken string) *model.ShareRecord {
|
|||||||
global.DB.Where("share_token = ?", shareToken).First(m)
|
global.DB.Where("share_token = ?", shareToken).First(m)
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlatformFromOs
|
||||||
|
func (t *AddressBookService) PlatformFromOs(os string) string {
|
||||||
|
if strings.Contains(os, "Android") || strings.Contains(os, "android") {
|
||||||
|
return "Android"
|
||||||
|
}
|
||||||
|
if strings.Contains(os, "Windows") || strings.Contains(os, "windows") {
|
||||||
|
return "Windows"
|
||||||
|
}
|
||||||
|
if strings.Contains(os, "Linux") || strings.Contains(os, "linux") {
|
||||||
|
return "Linux"
|
||||||
|
}
|
||||||
|
if strings.Contains(os, "mac") || strings.Contains(os, "Mac") {
|
||||||
|
return "Mac OS"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -262,3 +262,10 @@ func (us *UserService) UserThirdInfo(userId uint, op string) *model.UserThird {
|
|||||||
global.DB.Where("user_id = ? and third_type = ?", userId, op).First(ut)
|
global.DB.Where("user_id = ? and third_type = ?", userId, op).First(ut)
|
||||||
return ut
|
return ut
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindLatestUserIdFromLoginLogByUuid 根据uuid查找最后登录的用户id
|
||||||
|
func (us *UserService) FindLatestUserIdFromLoginLogByUuid(uuid string) uint {
|
||||||
|
llog := &model.LoginLog{}
|
||||||
|
global.DB.Where("uuid = ?", uuid).Order("id desc").First(llog)
|
||||||
|
return llog.UserId
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user