Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcce10c695 | ||
|
|
30eb14702f | ||
|
|
3679fcc874 | ||
|
|
d085b4e3c2 | ||
|
|
dc8fcdf214 | ||
|
|
8bab23b65b | ||
|
|
f64022e411 | ||
|
|
2d37302cf9 | ||
|
|
1a1856257d | ||
|
|
24f570b64f | ||
|
|
6322177b71 | ||
|
|
d2390d1cb3 | ||
|
|
6fe6f6b708 | ||
|
|
a656f4fec3 | ||
|
|
399c32da7d | ||
|
|
62167836dc | ||
|
|
caef3897a0 | ||
|
|
5ef6810e3f | ||
|
|
ae2079f583 | ||
|
|
aa65382a0f | ||
|
|
18c61a2bfc | ||
|
|
7cc1a8a58a | ||
|
|
cf9feac702 | ||
|
|
a963cd0209 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -39,7 +39,7 @@ env:
|
|||||||
DOCKERHUB_IMAGE_NAMESPACE: ${{ github.event.inputs.DOCKERHUB_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 }}
|
GHCR_IMAGE_NAMESPACE: ${{ github.event.inputs.GHCR_IMAGE_NAMESPACE || github.actor }}
|
||||||
SKIP_DOCKER_HUB: ${{ github.event.inputs.SKIP_DOCKER_HUB || 'false' }}
|
SKIP_DOCKER_HUB: ${{ github.event.inputs.SKIP_DOCKER_HUB || 'false' }}
|
||||||
SKIP_GHCR: ${{ github.event.inputs.SKIP_GHCR }}
|
SKIP_GHCR: ${{ github.event.inputs.SKIP_GHCR || 'false' }}
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
453
README.md
453
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,否则可能链接不上或者超时
|
|
||||||
|
|
||||||
```bash
|
#### 关于PC端链接超时或者链接不上的问题以及解决方案
|
||||||
hbbs -r <relay-server-ip[:port]> -k <key>
|
##### 链接不上是或者超时
|
||||||
hbbr -k <key>
|
因为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
|
||||||
```bash
|
allow_err!(secure_tcp(&mut socket, key).await);
|
||||||
hbbs -r <relay-server-ip[:port]> -k abc1234567
|
}
|
||||||
hbbr -k abc1234567
|
```
|
||||||
```
|
可看到当`key`和`token`都不为空时,会调用`secure_tcp`,但是server端不会响应,所以客户端超时
|
||||||
|
`secure_tcp` 代码位置在 `https://github.com/rustdesk/rustdesk/blob/master/src/common.rs#L1203`
|
||||||
|
|
||||||
|
##### 4种解决方案
|
||||||
|
1. server端指定key。
|
||||||
|
- 优点:简单
|
||||||
|
- 缺点:链接不是加密的
|
||||||
|
```bash
|
||||||
|
hbbs -r <relay-server-ip[:port]> -k <key>
|
||||||
|
hbbr -k <key>
|
||||||
|
```
|
||||||
|
比如
|
||||||
|
```bash
|
||||||
|
hbbs -r <relay-server-ip[:port]> -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,54 +173,66 @@ 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
|
||||||
|
proxy:
|
||||||
|
enable: false
|
||||||
|
host: ""
|
||||||
```
|
```
|
||||||
|
|
||||||
* 环境变量,变量名前缀是RUSTDESK_API,环境变量如果存在将覆盖配置文件中的配置
|
### 环境变量
|
||||||
|
变量名前缀是`RUSTDESK_API`,环境变量如果存在将覆盖配置文件中的配置
|
||||||
|
|
||||||
| 变量名 | 说明 | 示例 |
|
| 变量名 | 说明 | 示例 |
|
||||||
|-------------------------------------|--------------------------------------|-----------------------------|
|
|------------------------------------|--------------------------------------|-----------------------------|
|
||||||
| TZ | 时区 | Asia/Shanghai |
|
| TZ | 时区 | Asia/Shanghai |
|
||||||
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
||||||
| -----GIN配置----- | ---------- | ---------- |
|
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
| -----GIN配置----- | ---------- | ---------- |
|
||||||
| -----------GORM配置------------------ | ------------------------------------ | --------------------------- |
|
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
||||||
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
|
| -----------GORM配置---------------- | ------------------------------------ | --------------------------- |
|
||||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
|
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
|
||||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
|
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
|
||||||
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API, 1:启用,0:不启用; 默认启用 | 1 |
|
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
|
||||||
| -----MYSQL配置----- | ---------- | ---------- |
|
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API, 1:启用,0:不启用; 默认启用 | 1 |
|
||||||
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
|
| -----MYSQL配置----- | ---------- | ---------- |
|
||||||
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
|
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
|
||||||
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
|
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
|
||||||
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
|
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
|
||||||
| -----RUSTDESK配置----- | --------------- | ---------- |
|
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
|
||||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
|
| -----RUSTDESK配置----- | --------------- | ---------- |
|
||||||
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
|
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
|
||||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
|
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
|
||||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
|
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
|
||||||
|
| ----PROXY配置----- | --------------- | ---------- |
|
||||||
|
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
|
||||||
|
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
|
||||||
|
|
||||||
### 安装步骤
|
|
||||||
|
### 运行
|
||||||
|
|
||||||
#### docker运行
|
#### docker运行
|
||||||
|
|
||||||
1. 直接docker运行,配置可以通过挂载配置文件`/app/conf/config.yaml`来修改,或者通过环境变量覆盖配置文件中的配置
|
1. 直接docker运行,配置可以通过挂载配置文件`/app/conf/config.yaml`来修改,或者通过环境变量覆盖配置文件中的配置
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
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_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
-e RUSTDESK_API_LANG=zh-CN \
|
||||||
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
||||||
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
||||||
-e RUSTDESK_API_RUSTDESK_KEY=123456789 \
|
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
||||||
lejianwen/rustdesk-api
|
-e RUSTDESK_API_RUSTDESK_KEY=<key> \
|
||||||
```
|
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 +241,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,74 +252,70 @@ 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
|
||||||
services:
|
services:
|
||||||
hbbs:
|
hbbs:
|
||||||
container_name: hbbs
|
container_name: hbbs
|
||||||
ports:
|
ports:
|
||||||
- 21115:21115
|
- 21115:21115
|
||||||
- 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 <key> # 填入个人域名或 IP + hbbr 暴露端口
|
||||||
command: hbbs -r <relay-server-ip[:port]> -k 123456789 # 填入个人域名或 IP + hbbr 暴露端口
|
volumes:
|
||||||
volumes:
|
- ./data:/root # 自定义挂载目录
|
||||||
- /data/rustdesk/hbbs:/root # 自定义挂载目录
|
networks:
|
||||||
networks:
|
- rustdesk-net
|
||||||
- rustdesk-net
|
depends_on:
|
||||||
depends_on:
|
- hbbr
|
||||||
- hbbr
|
restart: unless-stopped
|
||||||
restart: unless-stopped
|
deploy:
|
||||||
deploy:
|
resources:
|
||||||
resources:
|
limits:
|
||||||
limits:
|
memory: 64M
|
||||||
memory: 64M
|
hbbr:
|
||||||
hbbr:
|
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:/root
|
||||||
- /data/rustdesk/hbbr:/root # 自定义挂载目录
|
networks:
|
||||||
networks:
|
- rustdesk-net
|
||||||
- rustdesk-net
|
restart: unless-stopped
|
||||||
restart: unless-stopped
|
deploy:
|
||||||
deploy:
|
resources:
|
||||||
resources:
|
limits:
|
||||||
limits:
|
memory: 64M
|
||||||
memory: 64M
|
rustdesk-api:
|
||||||
rustdesk-api:
|
container_name: rustdesk-api
|
||||||
container_name: rustdesk-api
|
environment:
|
||||||
environment:
|
- TZ=Asia/Shanghai
|
||||||
- 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=<key>
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
ports:
|
||||||
ports:
|
- 21114:21114
|
||||||
- 21114:21114
|
image: lejianwen/rustdesk-api
|
||||||
image: lejianwen/rustdesk-api
|
volumes:
|
||||||
volumes:
|
- /data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
||||||
- /data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
networks:
|
||||||
networks:
|
- rustdesk-net
|
||||||
- rustdesk-net
|
restart: unless-stopped
|
||||||
restart: unless-stopped
|
```
|
||||||
|
|
||||||
```
|
- S6的镜像
|
||||||
|
- 如果使用***自定义KEY***,会需要修改启动脚本,覆盖镜像中的`/etc/s6-overlay/s6-rc.d/hbbr/run`和`/etc/s6-overlay/s6-rc.d/hbbr/run`
|
||||||
- 如果使用的是S6的镜像,会需要修改启动脚本,覆盖镜像中的`/etc/s6-overlay/s6-rc.d/hbbr/run`
|
1. 创建`hbbr/run`,自定义KEY才需要
|
||||||
和`/etc/s6-overlay/s6-rc.d/hbbr/run`
|
|
||||||
|
|
||||||
1. 创建`hbbr/run`
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#!/command/with-contenv sh
|
#!/command/with-contenv sh
|
||||||
cd /data
|
cd /data
|
||||||
@@ -283,63 +323,99 @@ 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
|
cd /data
|
||||||
cd /data
|
PARAMS=
|
||||||
PARAMS=
|
[ "${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. 修改`docker-compose.yml`中的`s6`部分
|
||||||
3. 修改`docker-compose.yml`中的`s6`部分
|
```yaml
|
||||||
|
networks:
|
||||||
```
|
rustdesk-net:
|
||||||
networks:
|
external: false
|
||||||
rustdesk-net:
|
services:
|
||||||
external: false
|
rustdesk-server:
|
||||||
services:
|
container_name: rustdesk-server
|
||||||
rustdesk-server:
|
ports:
|
||||||
container_name: rustdesk-server
|
- 21115:21115
|
||||||
ports:
|
- 21116:21116
|
||||||
- 21115:21115
|
- 21116:21116/udp
|
||||||
- 21116:21116
|
- 21117:21117
|
||||||
- 21116:21116/udp
|
- 21118:21118
|
||||||
- 21117:21117
|
- 21119:21119
|
||||||
- 21118:21118
|
image: rustdesk/rustdesk-server-s6:latest
|
||||||
- 21119:21119
|
environment:
|
||||||
image: rustdesk/rustdesk-server-s6:latest
|
- RELAY=192.168.1.66:21117
|
||||||
environment:
|
- ENCRYPTED_ONLY=1
|
||||||
- RELAY=192.168.1.66:21117
|
- KEY=<key> #自定义KEY
|
||||||
- ENCRYPTED_ONLY=1
|
volumes:
|
||||||
- KEY=abc123456789
|
- ./data:/data
|
||||||
volumes:
|
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
||||||
- ./data:/data
|
- ./hbbs/run:/etc/s6-overlay/s6-rc.d/hbbs/run
|
||||||
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
restart: unless-stopped
|
||||||
- ./hbbs/run:/etc/s6-overlay/s6-rc.d/hbbs/run
|
rustdesk-api:
|
||||||
restart: unless-stopped
|
container_name: rustdesk-api
|
||||||
rustdesk-api:
|
ports:
|
||||||
container_name: rustdesk-api
|
- 21114:21114
|
||||||
ports:
|
image: lejianwen/rustdesk-api
|
||||||
- 21114:21114
|
environment:
|
||||||
image: lejianwen/rustdesk-api
|
- TZ=Asia/Shanghai
|
||||||
environment:
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
- TZ=Asia/Shanghai
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
- RUSTDESK_API_RUSTDESK_KEY=<key>
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
|
volumes:
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=abc123456789
|
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||||
volumes:
|
networks:
|
||||||
- /data/rustdesk/api:/app/data #将数据库挂载
|
- rustdesk-net
|
||||||
networks:
|
restart: unless-stopped
|
||||||
- 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:
|
||||||
|
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||||
|
networks:
|
||||||
|
- rustdesk-net
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
#### 下载release直接运行
|
#### 下载release直接运行
|
||||||
|
|
||||||
下载地址[release](https://github.com/lejianwen/rustdesk-api/releases)
|
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
|
||||||
|
|
||||||
#### 源码安装
|
#### 源码安装
|
||||||
|
|
||||||
@@ -379,7 +455,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)
|
||||||
486
README_EN.md
486
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.
|
|
||||||
|
|
||||||
```bash
|
#### The PC client uses version ***1.3.0***, and versions ***1.2.6+*** have been tested to work.
|
||||||
hbbs -r <relay-server-ip[:port]> -k <key>
|
|
||||||
hbbr -k <key>
|
|
||||||
```
|
|
||||||
|
|
||||||
Example:
|
#### 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`
|
||||||
|
|
||||||
```bash
|
##### Four Solutions
|
||||||
hbbs -r <relay-server-ip[:port]> -k abc1234567
|
1. Specify the key on the server.
|
||||||
hbbr -k abc1234567
|
- Advantage: Simple
|
||||||
```
|
- Disadvantage: The connection is not encrypted
|
||||||
|
```bash
|
||||||
|
hbbs -r <relay-server-ip[:port]> -k <key>
|
||||||
|
hbbr -k <key>
|
||||||
|
```
|
||||||
|
For example
|
||||||
|
```bash
|
||||||
|
hbbs -r <relay-server-ip[:port]> -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,33 +179,40 @@ 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 |
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| ----- GORM Configuration ----- | --------------------------------------- | ------------------------------ |
|
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
||||||
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
|
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
||||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
|
||||||
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
||||||
| ----- MYSQL Configuration ----- | --------------------------------------- | ------------------------------ |
|
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
||||||
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
||||||
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
||||||
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
||||||
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ------------------------------ |
|
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
||||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
|
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
||||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
|
||||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
|
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
|
||||||
|
| ---- PROXY ----- | --------------- | ---------- |
|
||||||
|
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
|
||||||
|
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
|
||||||
|
|
||||||
### Installation Steps
|
### Installation Steps
|
||||||
|
|
||||||
@@ -180,166 +220,201 @@ rustdesk:
|
|||||||
|
|
||||||
1. Run directly with Docker. Configuration can be modified by mounting the config file `/app/conf/config.yaml`, or by
|
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.
|
using environment variables to override settings.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
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 RUSTDESK_API_LANG=en \
|
-e RUSTDESK_API_LANG=en \
|
||||||
-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
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/api:/app/data # Mount the database for easy backup
|
- /data/rustdesk/api:/app/data # Mount the database for easy backup
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
```
|
```
|
||||||
|
|
||||||
- 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.
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
rustdesk-net:
|
||||||
|
external: false
|
||||||
|
services:
|
||||||
|
hbbs:
|
||||||
|
container_name: hbbs
|
||||||
|
ports:
|
||||||
|
- 21115:21115
|
||||||
|
- 21116:21116 # 自定义 hbbs 映射端口
|
||||||
|
- 21116:21116/udp # 自定义 hbbs 映射端口
|
||||||
|
- 21118:21118 # web client
|
||||||
|
image: rustdesk/rustdesk-server
|
||||||
|
command: hbbs -r <relay-server-ip[:port]> -k <key> # 填入个人域名或 IP + hbbr 暴露端口
|
||||||
|
volumes:
|
||||||
|
- ./data:/root # 自定义挂载目录
|
||||||
|
networks:
|
||||||
|
- rustdesk-net
|
||||||
|
depends_on:
|
||||||
|
- hbbr
|
||||||
|
restart: unless-stopped
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 64M
|
||||||
|
hbbr:
|
||||||
|
container_name: hbbr
|
||||||
|
ports:
|
||||||
|
- 21117:21117 # 自定义 hbbr 映射端口
|
||||||
|
- 21119:21119 # web client
|
||||||
|
image: rustdesk/rustdesk-server
|
||||||
|
command: hbbr -k <key>
|
||||||
|
volumes:
|
||||||
|
- ./data:/root
|
||||||
|
networks:
|
||||||
|
- rustdesk-net
|
||||||
|
restart: unless-stopped
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 64M
|
||||||
|
rustdesk-api:
|
||||||
|
container_name: 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>
|
||||||
|
ports:
|
||||||
|
- 21114:21114
|
||||||
|
image: lejianwen/rustdesk-api
|
||||||
|
volumes:
|
||||||
|
- /data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
||||||
|
networks:
|
||||||
|
- rustdesk-net
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
```docker-compose
|
- S6 image
|
||||||
networks:
|
- - 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.
|
||||||
rustdesk-net:
|
1. Create `hbbr/run`, only needed for custom KEY
|
||||||
external: false
|
```bash
|
||||||
services:
|
#!/command/with-contenv sh
|
||||||
hbbs:
|
cd /data
|
||||||
container_name: hbbs
|
PARAMS=
|
||||||
ports:
|
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
||||||
- 21115:21115
|
/usr/bin/hbbr $PARAMS
|
||||||
- 21116:21116 # 自定义 hbbs 映射端口
|
```
|
||||||
- 21116:21116/udp # 自定义 hbbs 映射端口
|
2. Create `hbbs/run`, only needed for custom KEY
|
||||||
- 21118:21118 # web client
|
```bash
|
||||||
- 21119:21119 # web client
|
#!/command/with-contenv sh
|
||||||
image: rustdesk/rustdesk-server
|
sleep 2
|
||||||
command: hbbs -r <relay-server-ip[:port]> -k 123456789 # 填入个人域名或 IP + hbbr 暴露端口
|
cd /data
|
||||||
volumes:
|
PARAMS=
|
||||||
- /data/rustdesk/hbbs:/root # 自定义挂载目录
|
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
||||||
|
/usr/bin/hbbs -r $RELAY $PARAMS
|
||||||
|
```
|
||||||
|
3. Modify the `s6` section in `docker-compose.yml`
|
||||||
|
```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
|
||||||
|
- KEY=<key> #KEY
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
||||||
|
- ./hbbs/run:/etc/s6-overlay/s6-rc.d/hbbs/run
|
||||||
|
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:
|
||||||
|
- 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:
|
networks:
|
||||||
- rustdesk-net
|
rustdesk-net:
|
||||||
depends_on:
|
external: false
|
||||||
- hbbr
|
services:
|
||||||
restart: unless-stopped
|
rustdesk-server:
|
||||||
deploy:
|
container_name: rustdesk-server
|
||||||
resources:
|
ports:
|
||||||
limits:
|
- 21115:21115
|
||||||
memory: 64M
|
- 21116:21116
|
||||||
hbbr:
|
- 21116:21116/udp
|
||||||
container_name: hbbr
|
- 21117:21117
|
||||||
ports:
|
- 21118:21118
|
||||||
- 21117:21117 # 自定义 hbbr 映射端口
|
- 21119:21119
|
||||||
image: rustdesk/rustdesk-server
|
image: rustdesk/rustdesk-server-s6:latest
|
||||||
command: hbbr -k 123456789
|
environment:
|
||||||
#command: hbbr
|
- RELAY=192.168.1.66:21117
|
||||||
volumes:
|
- ENCRYPTED_ONLY=1
|
||||||
- /data/rustdesk/hbbr:/root # 自定义挂载目录
|
volumes:
|
||||||
networks:
|
- ./data:/data
|
||||||
- rustdesk-net
|
restart: unless-stopped
|
||||||
restart: unless-stopped
|
rustdesk-api:
|
||||||
deploy:
|
container_name: rustdesk-api
|
||||||
resources:
|
ports:
|
||||||
limits:
|
- 21114:21114
|
||||||
memory: 64M
|
image: lejianwen/rustdesk-api
|
||||||
rustdesk-api:
|
environment:
|
||||||
container_name: rustdesk-api
|
- TZ=Asia/Shanghai
|
||||||
environment:
|
- 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=<key>
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
volumes:
|
||||||
ports:
|
- /data/rustdesk/api:/app/data
|
||||||
- 21114:21114
|
networks:
|
||||||
image: lejianwen/rustdesk-api
|
- rustdesk-net
|
||||||
volumes:
|
restart: unless-stopped
|
||||||
- /data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
```
|
||||||
networks:
|
|
||||||
- rustdesk-net
|
|
||||||
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`
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/command/with-contenv sh
|
|
||||||
cd /data
|
|
||||||
PARAMS=
|
|
||||||
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
|
||||||
/usr/bin/hbbr $PARAMS
|
|
||||||
```
|
|
||||||
|
|
||||||
2. create `hbbs/run`
|
|
||||||
```bash
|
|
||||||
#!/command/with-contenv sh
|
|
||||||
sleep 2
|
|
||||||
cd /data
|
|
||||||
PARAMS=
|
|
||||||
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
|
|
||||||
/usr/bin/hbbs -r $RELAY $PARAMS
|
|
||||||
```
|
|
||||||
3. edit `docker-compose.yml`
|
|
||||||
```
|
|
||||||
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
|
|
||||||
- KEY=abc123456789
|
|
||||||
volumes:
|
|
||||||
- ./data:/data
|
|
||||||
- ./hbbr/run:/etc/s6-overlay/s6-rc.d/hbbr/run
|
|
||||||
- ./hbbs/run:/etc/s6-overlay/s6-rc.d/hbbs/run
|
|
||||||
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=abc123456789
|
|
||||||
volumes:
|
|
||||||
- /data/rustdesk/api:/app/data #将数据库挂载
|
|
||||||
networks:
|
|
||||||
- rustdesk-net
|
|
||||||
restart: unless-stopped
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Running from Release
|
#### Running from Release
|
||||||
|
|
||||||
@@ -388,7 +463,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)
|
||||||
@@ -200,7 +200,7 @@ func getTranslatorForLang(lang string) ut.Translator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func DatabaseAutoUpdate() {
|
func DatabaseAutoUpdate() {
|
||||||
version := 220
|
version := 235
|
||||||
|
|
||||||
db := global.DB
|
db := global.DB
|
||||||
|
|
||||||
@@ -262,6 +262,8 @@ func Migrate(version uint) {
|
|||||||
&model.Oauth{},
|
&model.Oauth{},
|
||||||
&model.LoginLog{},
|
&model.LoginLog{},
|
||||||
&model.ShareRecord{},
|
&model.ShareRecord{},
|
||||||
|
&model.AuditConn{},
|
||||||
|
&model.AuditFile{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("migrate err :=>", err)
|
fmt.Println("migrate err :=>", err)
|
||||||
|
|||||||
@@ -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,13 +18,16 @@ 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:
|
||||||
path: "./runtime/log.txt"
|
path: "./runtime/log.txt"
|
||||||
level: "warn" #trace,debug,info,warn,error,fatal
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
report-caller: true
|
report-caller: true
|
||||||
|
proxy:
|
||||||
|
enable: false
|
||||||
|
host: ""
|
||||||
redis:
|
redis:
|
||||||
addr: "127.0.0.1:6379"
|
addr: "127.0.0.1:6379"
|
||||||
password: ""
|
password: ""
|
||||||
@@ -42,4 +47,4 @@ oss:
|
|||||||
max-byte: 10240
|
max-byte: 10240
|
||||||
jwt:
|
jwt:
|
||||||
private-key: "./conf/jwt_pri.pem"
|
private-key: "./conf/jwt_pri.pem"
|
||||||
expire-duration: 360000
|
expire-duration: 360000
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -25,6 +30,7 @@ type Config struct {
|
|||||||
Oss Oss
|
Oss Oss
|
||||||
Jwt Jwt
|
Jwt Jwt
|
||||||
Rustdesk Rustdesk
|
Rustdesk Rustdesk
|
||||||
|
Proxy Proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init 初始化配置
|
// Init 初始化配置
|
||||||
|
|||||||
6
config/proxy.go
Normal file
6
config/proxy.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type Proxy struct {
|
||||||
|
Enable bool `mapstructure:"enable"`
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
}
|
||||||
@@ -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,157 @@ 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/audit_conn/delete": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "文件日志删除",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"文件日志"
|
||||||
|
],
|
||||||
|
"summary": "文件日志删除",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "文件日志信息",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.AuditFile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/audit_conn/list": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "文件日志列表",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"文件日志"
|
||||||
|
],
|
||||||
|
"summary": "文件日志列表",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "页码",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "页大小",
|
||||||
|
"name": "page_size",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "目标设备",
|
||||||
|
"name": "peer_id",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "来源设备",
|
||||||
|
"name": "from_peer",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/model.AuditFileList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/file/oss_token": {
|
"/admin/file/oss_token": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1371,6 +1567,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 +1683,7 @@ const docTemplateadmin = `{
|
|||||||
"tags": [
|
"tags": [
|
||||||
"ADMIN"
|
"ADMIN"
|
||||||
],
|
],
|
||||||
"summary": "服务配置",
|
"summary": "RUSTDESK服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -2358,6 +2566,9 @@ const docTemplateadmin = `{
|
|||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2456,6 +2667,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": [
|
||||||
@@ -2626,6 +2864,134 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"model.AuditConn": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"close_time": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"conn_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_peer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"session_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model.AuditConnList": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"list": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/model.AuditConn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"page_size": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model.AuditFile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"created_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_peer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"is_file": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"num": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model.AuditFileList": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"list": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/model.AuditFile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"page_size": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"model.Group": {
|
"model.Group": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -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,157 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/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/audit_conn/delete": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "文件日志删除",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"文件日志"
|
||||||
|
],
|
||||||
|
"summary": "文件日志删除",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "文件日志信息",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/model.AuditFile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/audit_conn/list": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "文件日志列表",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"文件日志"
|
||||||
|
],
|
||||||
|
"summary": "文件日志列表",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "页码",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "页大小",
|
||||||
|
"name": "page_size",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "目标设备",
|
||||||
|
"name": "peer_id",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "来源设备",
|
||||||
|
"name": "from_peer",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/model.AuditFileList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/file/oss_token": {
|
"/admin/file/oss_token": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1364,6 +1560,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 +1676,7 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"ADMIN"
|
"ADMIN"
|
||||||
],
|
],
|
||||||
"summary": "服务配置",
|
"summary": "RUSTDESK服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -2351,6 +2559,9 @@
|
|||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2449,6 +2660,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": [
|
||||||
@@ -2619,6 +2857,134 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"model.AuditConn": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"close_time": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"conn_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_peer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"session_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model.AuditConnList": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"list": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/model.AuditConn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"page_size": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model.AuditFile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"created_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"from_peer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"is_file": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"num": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model.AuditFileList": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"list": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/model.AuditFile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"page_size": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"model.Group": {
|
"model.Group": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ definitions:
|
|||||||
type: integer
|
type: integer
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
|
type:
|
||||||
|
type: integer
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
type: object
|
type: object
|
||||||
@@ -141,6 +143,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:
|
||||||
@@ -254,6 +275,90 @@ definitions:
|
|||||||
total:
|
total:
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
|
model.AuditConn:
|
||||||
|
properties:
|
||||||
|
action:
|
||||||
|
type: string
|
||||||
|
close_time:
|
||||||
|
type: integer
|
||||||
|
conn_id:
|
||||||
|
type: integer
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
from_name:
|
||||||
|
type: string
|
||||||
|
from_peer:
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
ip:
|
||||||
|
type: string
|
||||||
|
peer_id:
|
||||||
|
type: string
|
||||||
|
session_id:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: integer
|
||||||
|
updated_at:
|
||||||
|
type: string
|
||||||
|
uuid:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
model.AuditConnList:
|
||||||
|
properties:
|
||||||
|
list:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/model.AuditConn'
|
||||||
|
type: array
|
||||||
|
page:
|
||||||
|
type: integer
|
||||||
|
page_size:
|
||||||
|
type: integer
|
||||||
|
total:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
model.AuditFile:
|
||||||
|
properties:
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
from_name:
|
||||||
|
type: string
|
||||||
|
from_peer:
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
info:
|
||||||
|
type: string
|
||||||
|
ip:
|
||||||
|
type: string
|
||||||
|
is_file:
|
||||||
|
type: boolean
|
||||||
|
num:
|
||||||
|
type: integer
|
||||||
|
path:
|
||||||
|
type: string
|
||||||
|
peer_id:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: integer
|
||||||
|
updated_at:
|
||||||
|
type: string
|
||||||
|
uuid:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
model.AuditFileList:
|
||||||
|
properties:
|
||||||
|
list:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/model.AuditFile'
|
||||||
|
type: array
|
||||||
|
page:
|
||||||
|
type: integer
|
||||||
|
page_size:
|
||||||
|
type: integer
|
||||||
|
total:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
model.Group:
|
model.Group:
|
||||||
properties:
|
properties:
|
||||||
created_at:
|
created_at:
|
||||||
@@ -618,6 +723,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 +784,98 @@ 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/audit_conn/delete:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 文件日志删除
|
||||||
|
parameters:
|
||||||
|
- description: 文件日志信息
|
||||||
|
in: body
|
||||||
|
name: body
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/model.AuditFile'
|
||||||
|
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/audit_conn/list:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 文件日志列表
|
||||||
|
parameters:
|
||||||
|
- description: 页码
|
||||||
|
in: query
|
||||||
|
name: page
|
||||||
|
type: integer
|
||||||
|
- description: 页大小
|
||||||
|
in: query
|
||||||
|
name: page_size
|
||||||
|
type: integer
|
||||||
|
- description: 目标设备
|
||||||
|
in: query
|
||||||
|
name: peer_id
|
||||||
|
type: integer
|
||||||
|
- description: 来源设备
|
||||||
|
in: query
|
||||||
|
name: from_peer
|
||||||
|
type: integer
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/definitions/response.Response'
|
||||||
|
- properties:
|
||||||
|
data:
|
||||||
|
$ref: '#/definitions/model.AuditFileList'
|
||||||
|
type: object
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
security:
|
||||||
|
- token: []
|
||||||
|
summary: 文件日志列表
|
||||||
|
tags:
|
||||||
|
- 文件日志
|
||||||
/admin/file/oss_token:
|
/admin/file/oss_token:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -1283,6 +1508,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 +1588,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 |
@@ -121,40 +121,6 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/ab/add": {
|
|
||||||
"post": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "标签",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"地址[Personal]"
|
|
||||||
],
|
|
||||||
"summary": "标签添加",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.ErrorResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/ab/peer/add/{guid}": {
|
"/ab/peer/add/{guid}": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -176,8 +142,8 @@ const docTemplateapi = `{
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -217,8 +183,8 @@ const docTemplateapi = `{
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -260,8 +226,8 @@ const docTemplateapi = `{
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -302,12 +268,22 @@ const docTemplateapi = `{
|
|||||||
"summary": "地址列表",
|
"summary": "地址列表",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"type": "integer",
|
||||||
"name": "string",
|
"description": "页码",
|
||||||
"in": "body",
|
"name": "current",
|
||||||
"schema": {
|
"in": "query"
|
||||||
"type": "string"
|
},
|
||||||
}
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "每页数量",
|
||||||
|
"name": "pageSize",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "ab",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -434,12 +410,16 @@ const docTemplateapi = `{
|
|||||||
"summary": "共享地址簿",
|
"summary": "共享地址簿",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"type": "integer",
|
||||||
"name": "string",
|
"description": "页码",
|
||||||
"in": "body",
|
"name": "current",
|
||||||
"schema": {
|
"in": "query"
|
||||||
"type": "string"
|
},
|
||||||
}
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "每页数量",
|
||||||
|
"name": "pageSize",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -458,6 +438,49 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/ab/tag/add/{guid}": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "标签",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"地址[Personal]"
|
||||||
|
],
|
||||||
|
"summary": "标签添加",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/ab/tag/rename/{guid}": {
|
"/ab/tag/rename/{guid}": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -476,6 +499,15 @@ const docTemplateapi = `{
|
|||||||
"地址[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "标签重命名",
|
"summary": "标签重命名",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -510,6 +542,15 @@ const docTemplateapi = `{
|
|||||||
"地址[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "标签修改颜色",
|
"summary": "标签修改颜色",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -544,6 +585,15 @@ const docTemplateapi = `{
|
|||||||
"地址[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "标签删除",
|
"summary": "标签删除",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -581,8 +631,8 @@ const docTemplateapi = `{
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -637,6 +687,86 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/audit/conn": {
|
||||||
|
"post": {
|
||||||
|
"description": "审计连接",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"审计"
|
||||||
|
],
|
||||||
|
"summary": "审计连接",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "审计连接",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.AuditConnForm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/audit/file": {
|
||||||
|
"post": {
|
||||||
|
"description": "审计文件",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"审计"
|
||||||
|
],
|
||||||
|
"summary": "审计文件",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "审计文件",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.AuditFileForm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/heartbeat": {
|
"/heartbeat": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "心跳",
|
"description": "心跳",
|
||||||
@@ -945,13 +1075,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"
|
||||||
@@ -1113,6 +1267,64 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"api.AuditConnForm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"conn_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"session_id": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"api.AuditFileForm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"is_file": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"api.DeviceInfoInLogin": {
|
"api.DeviceInfoInLogin": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -114,40 +114,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/ab/add": {
|
|
||||||
"post": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "标签",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"地址[Personal]"
|
|
||||||
],
|
|
||||||
"summary": "标签添加",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.ErrorResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/ab/peer/add/{guid}": {
|
"/ab/peer/add/{guid}": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -169,8 +135,8 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -210,8 +176,8 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -253,8 +219,8 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -295,12 +261,22 @@
|
|||||||
"summary": "地址列表",
|
"summary": "地址列表",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"type": "integer",
|
||||||
"name": "string",
|
"description": "页码",
|
||||||
"in": "body",
|
"name": "current",
|
||||||
"schema": {
|
"in": "query"
|
||||||
"type": "string"
|
},
|
||||||
}
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "每页数量",
|
||||||
|
"name": "pageSize",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "ab",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -427,12 +403,16 @@
|
|||||||
"summary": "共享地址簿",
|
"summary": "共享地址簿",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"type": "integer",
|
||||||
"name": "string",
|
"description": "页码",
|
||||||
"in": "body",
|
"name": "current",
|
||||||
"schema": {
|
"in": "query"
|
||||||
"type": "string"
|
},
|
||||||
}
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "每页数量",
|
||||||
|
"name": "pageSize",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -451,6 +431,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/ab/tag/add/{guid}": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "标签",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"地址[Personal]"
|
||||||
|
],
|
||||||
|
"summary": "标签添加",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/ab/tag/rename/{guid}": {
|
"/ab/tag/rename/{guid}": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -469,6 +492,15 @@
|
|||||||
"地址[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "标签重命名",
|
"summary": "标签重命名",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -503,6 +535,15 @@
|
|||||||
"地址[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "标签修改颜色",
|
"summary": "标签修改颜色",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -537,6 +578,15 @@
|
|||||||
"地址[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "标签删除",
|
"summary": "标签删除",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "guid",
|
||||||
|
"name": "guid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -574,8 +624,8 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "id",
|
"description": "guid",
|
||||||
"name": "id",
|
"name": "guid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@@ -630,6 +680,86 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/audit/conn": {
|
||||||
|
"post": {
|
||||||
|
"description": "审计连接",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"审计"
|
||||||
|
],
|
||||||
|
"summary": "审计连接",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "审计连接",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.AuditConnForm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/audit/file": {
|
||||||
|
"post": {
|
||||||
|
"description": "审计文件",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"审计"
|
||||||
|
],
|
||||||
|
"summary": "审计文件",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "审计文件",
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.AuditFileForm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/heartbeat": {
|
"/heartbeat": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "心跳",
|
"description": "心跳",
|
||||||
@@ -938,13 +1068,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"
|
||||||
@@ -1106,6 +1260,64 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"api.AuditConnForm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"conn_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"session_id": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"api.AuditFileForm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"is_file": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"peer_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"api.DeviceInfoInLogin": {
|
"api.DeviceInfoInLogin": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -6,6 +6,44 @@ definitions:
|
|||||||
example: '{"tags":["tag1","tag2","tag3"],"peers":[{"id":"abc","username":"abv-l","hostname":"","platform":"Windows","alias":"","tags":["tag1","tag2"],"hash":"hash"}],"tag_colors":"{\"tag1\":4288585374,\"tag2\":4278238420,\"tag3\":4291681337}"}'
|
example: '{"tags":["tag1","tag2","tag3"],"peers":[{"id":"abc","username":"abv-l","hostname":"","platform":"Windows","alias":"","tags":["tag1","tag2"],"hash":"hash"}],"tag_colors":"{\"tag1\":4288585374,\"tag2\":4278238420,\"tag3\":4291681337}"}'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
api.AuditConnForm:
|
||||||
|
properties:
|
||||||
|
action:
|
||||||
|
type: string
|
||||||
|
conn_id:
|
||||||
|
type: integer
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
ip:
|
||||||
|
type: string
|
||||||
|
peer:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
session_id:
|
||||||
|
type: number
|
||||||
|
type:
|
||||||
|
type: integer
|
||||||
|
uuid:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
api.AuditFileForm:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
info:
|
||||||
|
type: string
|
||||||
|
is_file:
|
||||||
|
type: boolean
|
||||||
|
path:
|
||||||
|
type: string
|
||||||
|
peer_id:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: integer
|
||||||
|
uuid:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
api.DeviceInfoInLogin:
|
api.DeviceInfoInLogin:
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
@@ -208,36 +246,15 @@ paths:
|
|||||||
summary: 地址更新
|
summary: 地址更新
|
||||||
tags:
|
tags:
|
||||||
- 地址
|
- 地址
|
||||||
/ab/add:
|
|
||||||
post:
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
description: 标签
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
"500":
|
|
||||||
description: Internal Server Error
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
summary: 标签添加
|
|
||||||
tags:
|
|
||||||
- 地址[Personal]
|
|
||||||
/ab/peer/add/{guid}:
|
/ab/peer/add/{guid}:
|
||||||
delete:
|
delete:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 删除地址
|
description: 删除地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: id
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
name: id
|
name: guid
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
@@ -261,9 +278,9 @@ paths:
|
|||||||
- application/json
|
- application/json
|
||||||
description: 添加地址
|
description: 添加地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: id
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
name: id
|
name: guid
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
@@ -288,9 +305,9 @@ paths:
|
|||||||
- application/json
|
- application/json
|
||||||
description: 更新地址
|
description: 更新地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: id
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
name: id
|
name: guid
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
@@ -315,11 +332,18 @@ paths:
|
|||||||
- application/json
|
- application/json
|
||||||
description: 地址
|
description: 地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: string valid
|
- description: 页码
|
||||||
in: body
|
in: query
|
||||||
name: string
|
name: current
|
||||||
schema:
|
type: integer
|
||||||
type: string
|
- description: 每页数量
|
||||||
|
in: query
|
||||||
|
name: pageSize
|
||||||
|
type: integer
|
||||||
|
- description: guid
|
||||||
|
in: query
|
||||||
|
name: ab
|
||||||
|
type: string
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -396,11 +420,14 @@ paths:
|
|||||||
- application/json
|
- application/json
|
||||||
description: 共享
|
description: 共享
|
||||||
parameters:
|
parameters:
|
||||||
- description: string valid
|
- description: 页码
|
||||||
in: body
|
in: query
|
||||||
name: string
|
name: current
|
||||||
schema:
|
type: integer
|
||||||
type: string
|
- description: 每页数量
|
||||||
|
in: query
|
||||||
|
name: pageSize
|
||||||
|
type: integer
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -422,6 +449,12 @@ paths:
|
|||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 标签
|
description: 标签
|
||||||
|
parameters:
|
||||||
|
- description: guid
|
||||||
|
in: path
|
||||||
|
name: guid
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -438,11 +471,44 @@ paths:
|
|||||||
summary: 标签删除
|
summary: 标签删除
|
||||||
tags:
|
tags:
|
||||||
- 地址[Personal]
|
- 地址[Personal]
|
||||||
|
/ab/tag/add/{guid}:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 标签
|
||||||
|
parameters:
|
||||||
|
- description: guid
|
||||||
|
in: path
|
||||||
|
name: guid
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
summary: 标签添加
|
||||||
|
tags:
|
||||||
|
- 地址[Personal]
|
||||||
/ab/tag/rename/{guid}:
|
/ab/tag/rename/{guid}:
|
||||||
put:
|
put:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 标签
|
description: 标签
|
||||||
|
parameters:
|
||||||
|
- description: guid
|
||||||
|
in: path
|
||||||
|
name: guid
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -464,6 +530,12 @@ paths:
|
|||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 标签
|
description: 标签
|
||||||
|
parameters:
|
||||||
|
- description: guid
|
||||||
|
in: path
|
||||||
|
name: guid
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -486,9 +558,9 @@ paths:
|
|||||||
- application/json
|
- application/json
|
||||||
description: 标签
|
description: 标签
|
||||||
parameters:
|
parameters:
|
||||||
- description: id
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
name: id
|
name: guid
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
@@ -528,6 +600,58 @@ paths:
|
|||||||
summary: 用户信息
|
summary: 用户信息
|
||||||
tags:
|
tags:
|
||||||
- 用户
|
- 用户
|
||||||
|
/audit/conn:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 审计连接
|
||||||
|
parameters:
|
||||||
|
- description: 审计连接
|
||||||
|
in: body
|
||||||
|
name: body
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/api.AuditConnForm'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
summary: 审计连接
|
||||||
|
tags:
|
||||||
|
- 审计
|
||||||
|
/audit/file:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 审计文件
|
||||||
|
parameters:
|
||||||
|
- description: 审计文件
|
||||||
|
in: body
|
||||||
|
name: body
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/api.AuditFileForm'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
summary: 审计文件
|
||||||
|
tags:
|
||||||
|
- 审计
|
||||||
/heartbeat:
|
/heartbeat:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -727,6 +851,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 +893,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 |
148
http/controller/admin/audit.go
Normal file
148
http/controller/admin/audit.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Audit struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnList 列表
|
||||||
|
// @Tags 链接日志
|
||||||
|
// @Summary 链接日志列表
|
||||||
|
// @Description 链接日志列表
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @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]
|
||||||
|
// @Security token
|
||||||
|
func (a *Audit) ConnList(c *gin.Context) {
|
||||||
|
query := &admin.AuditQuery{}
|
||||||
|
if err := c.ShouldBindQuery(query); err != nil {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res := service.AllService.AuditService.AuditConnList(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||||
|
if query.PeerId != "" {
|
||||||
|
tx.Where("peer_id like ?", "%"+query.PeerId+"%")
|
||||||
|
}
|
||||||
|
if query.FromPeer != "" {
|
||||||
|
tx.Where("from_peer like ?", "%"+query.FromPeer+"%")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
response.Success(c, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnDelete 删除
|
||||||
|
// @Tags 链接日志
|
||||||
|
// @Summary 链接日志删除
|
||||||
|
// @Description 链接日志删除
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param body body model.AuditConn true "链接日志信息"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 500 {object} response.Response
|
||||||
|
// @Router /admin/audit_conn/delete [post]
|
||||||
|
// @Security token
|
||||||
|
func (a *Audit) ConnDelete(c *gin.Context) {
|
||||||
|
f := &model.AuditConn{}
|
||||||
|
if err := c.ShouldBindJSON(f); err != nil {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := f.Id
|
||||||
|
errList := global.Validator.ValidVar(c, id, "required,gt=0")
|
||||||
|
if len(errList) > 0 {
|
||||||
|
response.Fail(c, 101, errList[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := service.AllService.AuditService.ConnInfoById(f.Id)
|
||||||
|
if l.Id > 0 {
|
||||||
|
err := service.AllService.AuditService.DeleteAuditConn(l)
|
||||||
|
if err == nil {
|
||||||
|
response.Success(c, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Fail(c, 101, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileList 列表
|
||||||
|
// @Tags 文件日志
|
||||||
|
// @Summary 文件日志列表
|
||||||
|
// @Description 文件日志列表
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @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_conn/list [get]
|
||||||
|
// @Security token
|
||||||
|
func (a *Audit) FileList(c *gin.Context) {
|
||||||
|
query := &admin.AuditQuery{}
|
||||||
|
if err := c.ShouldBindQuery(query); err != nil {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res := service.AllService.AuditService.AuditFileList(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||||
|
if query.PeerId != "" {
|
||||||
|
tx.Where("peer_id like ?", "%"+query.PeerId+"%")
|
||||||
|
}
|
||||||
|
if query.FromPeer != "" {
|
||||||
|
tx.Where("from_peer like ?", "%"+query.FromPeer+"%")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
response.Success(c, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileDelete 删除
|
||||||
|
// @Tags 文件日志
|
||||||
|
// @Summary 文件日志删除
|
||||||
|
// @Description 文件日志删除
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param body body model.AuditFile true "文件日志信息"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 500 {object} response.Response
|
||||||
|
// @Router /admin/audit_conn/delete [post]
|
||||||
|
// @Security token
|
||||||
|
func (a *Audit) FileDelete(c *gin.Context) {
|
||||||
|
f := &model.AuditFile{}
|
||||||
|
if err := c.ShouldBindJSON(f); err != nil {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := f.Id
|
||||||
|
errList := global.Validator.ValidVar(c, id, "required,gt=0")
|
||||||
|
if len(errList) > 0 {
|
||||||
|
response.Fail(c, 101, errList[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := service.AllService.AuditService.FileInfoById(f.Id)
|
||||||
|
if l.Id > 0 {
|
||||||
|
err := service.AllService.AuditService.DeleteAuditFile(l)
|
||||||
|
if err == nil {
|
||||||
|
response.Success(c, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Fail(c, 101, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
@@ -119,9 +118,10 @@ func (a *Ab) Tags(c *gin.Context) {
|
|||||||
// @Description 标签
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/add [post]
|
// @Router /ab/tag/add/{guid} [post]
|
||||||
// @Security BearerAuth
|
// @Security BearerAuth
|
||||||
func (a *Ab) TagAdd(c *gin.Context) {
|
func (a *Ab) TagAdd(c *gin.Context) {
|
||||||
t := &model.Tag{}
|
t := &model.Tag{}
|
||||||
@@ -151,6 +151,7 @@ func (a *Ab) TagAdd(c *gin.Context) {
|
|||||||
// @Description 标签
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/tag/rename/{guid} [put]
|
// @Router /ab/tag/rename/{guid} [put]
|
||||||
@@ -188,6 +189,7 @@ func (a *Ab) TagRename(c *gin.Context) {
|
|||||||
// @Description 标签
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/tag/update/{guid} [put]
|
// @Router /ab/tag/update/{guid} [put]
|
||||||
@@ -220,6 +222,7 @@ func (a *Ab) TagUpdate(c *gin.Context) {
|
|||||||
// @Description 标签
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/tag/{guid} [delete]
|
// @Router /ab/tag/{guid} [delete]
|
||||||
@@ -274,7 +277,7 @@ func (a *Ab) Personal(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"guid": guid,
|
"guid": guid,
|
||||||
"name": user.Username,
|
"name": user.Username,
|
||||||
"rule": 0,
|
"rule": 3,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
c.JSON(http.StatusOK, nil)
|
c.JSON(http.StatusOK, nil)
|
||||||
@@ -305,7 +308,8 @@ func (a *Ab) Settings(c *gin.Context) {
|
|||||||
// @Description 共享
|
// @Description 共享
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param string body string false "string valid"
|
// @Param current query int false "页码"
|
||||||
|
// @Param pageSize query int false "每页数量"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /ab/shared/profiles [post]
|
// @Router /ab/shared/profiles [post]
|
||||||
@@ -323,14 +327,14 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
|
|||||||
"name": "admin",
|
"name": "admin",
|
||||||
"owner": "admin",
|
"owner": "admin",
|
||||||
"note": "admin11",
|
"note": "admin11",
|
||||||
"rule": 0,
|
"rule": 3,
|
||||||
}
|
}
|
||||||
item2 := map[string]interface{}{
|
item2 := map[string]interface{}{
|
||||||
"guid": "2",
|
"guid": "2",
|
||||||
"name": "admin2",
|
"name": "admin2",
|
||||||
"owner": "admin2",
|
"owner": "admin2",
|
||||||
"note": "admin22",
|
"note": "admin22",
|
||||||
"rule": 0,
|
"rule": 2,
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"total": 2,
|
"total": 2,
|
||||||
@@ -349,7 +353,9 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
|
|||||||
// @Description 地址
|
// @Description 地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param string body string false "string valid"
|
// @Param current query int false "页码"
|
||||||
|
// @Param pageSize query int false "每页数量"
|
||||||
|
// @Param ab query string false "guid"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /ab/peers [post]
|
// @Router /ab/peers [post]
|
||||||
@@ -370,7 +376,7 @@ func (a *Ab) Peers(c *gin.Context) {
|
|||||||
// @Description 标签
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "id"
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {object} model.TagList
|
// @Success 200 {object} model.TagList
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/tags/{guid} [post]
|
// @Router /ab/tags/{guid} [post]
|
||||||
@@ -388,24 +394,35 @@ func (a *Ab) PTags(c *gin.Context) {
|
|||||||
// @Description 添加地址
|
// @Description 添加地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "id"
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @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{}
|
||||||
|
//guid := c.Param("guid")
|
||||||
f := &requstform.PersonalAddressBookForm{}
|
f := &requstform.PersonalAddressBookForm{}
|
||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
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())
|
||||||
@@ -420,7 +437,7 @@ func (a *Ab) PeerAdd(c *gin.Context) {
|
|||||||
// @Description 删除地址
|
// @Description 删除地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "id"
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/peer/add/{guid} [delete]
|
// @Router /ab/peer/add/{guid} [delete]
|
||||||
@@ -455,7 +472,7 @@ func (a *Ab) PeerDel(c *gin.Context) {
|
|||||||
// @Description 更新地址
|
// @Description 更新地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "id"
|
// @Param guid path string true "guid"
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab/peer/update/{guid} [put]
|
// @Router /ab/peer/update/{guid} [put]
|
||||||
|
|||||||
84
http/controller/api/audit.go
Normal file
84
http/controller/api/audit.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
request "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Audit struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuditConn
|
||||||
|
// @Tags 审计
|
||||||
|
// @Summary 审计连接
|
||||||
|
// @Description 审计连接
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param body body request.AuditConnForm true "审计连接"
|
||||||
|
// @Success 200 {string} string ""
|
||||||
|
// @Failure 500 {object} response.Response
|
||||||
|
// @Router /audit/conn [post]
|
||||||
|
func (a *Audit) AuditConn(c *gin.Context) {
|
||||||
|
af := &request.AuditConnForm{}
|
||||||
|
err := c.ShouldBindBodyWith(af, binding.JSON)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
/*ttt := &gin.H{}
|
||||||
|
c.ShouldBindBodyWith(ttt, binding.JSON)
|
||||||
|
fmt.Println(ttt)*/
|
||||||
|
ac := af.ToAuditConn()
|
||||||
|
if af.Action == model.AuditActionNew {
|
||||||
|
service.AllService.AuditService.CreateAuditConn(ac)
|
||||||
|
} else if af.Action == model.AuditActionClose {
|
||||||
|
ex := service.AllService.AuditService.InfoByPeerIdAndConnId(af.Id, af.ConnId)
|
||||||
|
if ex.Id != 0 {
|
||||||
|
ex.CloseTime = time.Now().Unix()
|
||||||
|
service.AllService.AuditService.UpdateAuditConn(ex)
|
||||||
|
}
|
||||||
|
} else if af.Action == "" {
|
||||||
|
ex := service.AllService.AuditService.InfoByPeerIdAndConnId(af.Id, af.ConnId)
|
||||||
|
if ex.Id != 0 {
|
||||||
|
up := &model.AuditConn{
|
||||||
|
IdModel: model.IdModel{Id: ex.Id},
|
||||||
|
FromPeer: ac.FromPeer,
|
||||||
|
FromName: ac.FromName,
|
||||||
|
SessionId: ac.SessionId,
|
||||||
|
Type: ac.Type,
|
||||||
|
}
|
||||||
|
service.AllService.AuditService.UpdateAuditConn(up)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.Success(c, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuditFile
|
||||||
|
// @Tags 审计
|
||||||
|
// @Summary 审计文件
|
||||||
|
// @Description 审计文件
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param body body request.AuditFileForm true "审计文件"
|
||||||
|
// @Success 200 {string} string ""
|
||||||
|
// @Failure 500 {object} response.Response
|
||||||
|
// @Router /audit/file [post]
|
||||||
|
func (a *Audit) AuditFile(c *gin.Context) {
|
||||||
|
aff := &request.AuditFileForm{}
|
||||||
|
err := c.ShouldBindBodyWith(aff, binding.JSON)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//ttt := &gin.H{}
|
||||||
|
//c.ShouldBindBodyWith(ttt, binding.JSON)
|
||||||
|
//fmt.Println(ttt)
|
||||||
|
af := aff.ToAuditFile()
|
||||||
|
service.AllService.AuditService.CreateAuditFile(af)
|
||||||
|
response.Success(c, "")
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
requstform "Gwen/http/request/api"
|
requstform "Gwen/http/request/api"
|
||||||
"Gwen/http/response"
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
"Gwen/service"
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -53,7 +54,11 @@ func (i *Index) Heartbeat(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, gin.H{})
|
c.JSON(http.StatusOK, gin.H{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
peer.LastOnlineTime = time.Now().Unix()
|
//如果在一分钟以内则不更新
|
||||||
service.AllService.PeerService.Update(peer)
|
if time.Now().Unix()-peer.LastOnlineTime > 60 {
|
||||||
|
peer.LastOnlineTime = time.Now().Unix()
|
||||||
|
upp := &model.Peer{RowId: peer.RowId, LastOnlineTime: peer.LastOnlineTime}
|
||||||
|
service.AllService.PeerService.Update(upp)
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{})
|
c.JSON(http.StatusOK, gin.H{})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,19 +29,30 @@ 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 下次心跳会上传
|
||||||
//直接响应文本
|
//直接响应文本
|
||||||
c.String(http.StatusOK, "")
|
c.String(http.StatusOK, "SYSINFO_UPDATED")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type User struct {
|
|||||||
// @Security token
|
// @Security token
|
||||||
//func (u *User) currentUser(c *gin.Context) {
|
//func (u *User) currentUser(c *gin.Context) {
|
||||||
// user := service.AllService.UserService.CurUser(c)
|
// user := service.AllService.UserService.CurUser(c)
|
||||||
// up := (&apiResp.UserPayload{}).FromUser(user)
|
// up := (&apiResp.UserPayload{}).FromName(user)
|
||||||
// c.JSON(http.StatusOK, up)
|
// c.JSON(http.StatusOK, up)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|||||||
@@ -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 == "" {
|
||||||
|
|||||||
7
http/request/admin/audit.go
Normal file
7
http/request/admin/audit.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
type AuditQuery struct {
|
||||||
|
PeerId string `form:"peer_id"`
|
||||||
|
FromPeer string `form:"from_peer"`
|
||||||
|
PageQuery
|
||||||
|
}
|
||||||
@@ -5,11 +5,13 @@ import "Gwen/model"
|
|||||||
type GroupForm struct {
|
type GroupForm struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gf *GroupForm) FromGroup(group *model.Group) *GroupForm {
|
func (gf *GroupForm) FromGroup(group *model.Group) *GroupForm {
|
||||||
gf.Id = group.Id
|
gf.Id = group.Id
|
||||||
gf.Name = group.Name
|
gf.Name = group.Name
|
||||||
|
gf.Type = group.Type
|
||||||
return gf
|
return gf
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,5 +19,6 @@ func (gf *GroupForm) ToGroup() *model.Group {
|
|||||||
group := &model.Group{}
|
group := &model.Group{}
|
||||||
group.Id = gf.Id
|
group.Id = gf.Id
|
||||||
group.Name = gf.Name
|
group.Name = gf.Name
|
||||||
|
group.Type = gf.Type
|
||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,5 +35,7 @@ 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"`
|
||||||
}
|
}
|
||||||
|
|||||||
78
http/request/api/audit.go
Normal file
78
http/request/api/audit.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/model"
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuditConnForm struct {
|
||||||
|
Action string `json:"action"`
|
||||||
|
ConnId int64 `json:"conn_id"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Peer []string `json:"peer"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
SessionId float64 `json:"session_id"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Uuid string `json:"uuid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AuditConnForm) ToAuditConn() *model.AuditConn {
|
||||||
|
fp := ""
|
||||||
|
fn := ""
|
||||||
|
if len(a.Peer) >= 1 {
|
||||||
|
fp = a.Peer[0]
|
||||||
|
if len(a.Peer) == 2 {
|
||||||
|
fn = a.Peer[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ssid := strconv.FormatFloat(a.SessionId, 'f', -1, 64)
|
||||||
|
return &model.AuditConn{
|
||||||
|
Action: a.Action,
|
||||||
|
ConnId: a.ConnId,
|
||||||
|
PeerId: a.Id,
|
||||||
|
FromPeer: fp,
|
||||||
|
FromName: fn,
|
||||||
|
Ip: a.Ip,
|
||||||
|
SessionId: ssid,
|
||||||
|
Type: a.Type,
|
||||||
|
Uuid: a.Uuid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuditFileForm struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Info string `json:"info"`
|
||||||
|
IsFile bool `json:"is_file"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
PeerId string `json:"peer_id"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Uuid string `json:"uuid"`
|
||||||
|
}
|
||||||
|
type AuditFileInfo struct {
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Num int `json:"num"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AuditFileForm) ToAuditFile() *model.AuditFile {
|
||||||
|
fi := &AuditFileInfo{}
|
||||||
|
err := json.Unmarshal([]byte(a.Info), fi)
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Warn("ToAuditFile", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.AuditFile{
|
||||||
|
PeerId: a.Id,
|
||||||
|
Info: a.Info,
|
||||||
|
IsFile: a.IsFile,
|
||||||
|
FromPeer: a.PeerId,
|
||||||
|
Path: a.Path,
|
||||||
|
Type: a.Type,
|
||||||
|
Uuid: a.Uuid,
|
||||||
|
FromName: fi.Name,
|
||||||
|
Ip: fi.Ip,
|
||||||
|
Num: fi.Num,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,9 +27,10 @@ func Init(g *gin.Engine) {
|
|||||||
PeerBind(adg)
|
PeerBind(adg)
|
||||||
OauthBind(adg)
|
OauthBind(adg)
|
||||||
LoginLogBind(adg)
|
LoginLogBind(adg)
|
||||||
|
AuditBind(adg)
|
||||||
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"))
|
||||||
@@ -142,6 +143,15 @@ func LoginLogBind(rg *gin.RouterGroup) {
|
|||||||
aR.GET("/list", cont.List)
|
aR.GET("/list", cont.List)
|
||||||
aR.POST("/delete", cont.Delete)
|
aR.POST("/delete", cont.Delete)
|
||||||
}
|
}
|
||||||
|
func AuditBind(rg *gin.RouterGroup) {
|
||||||
|
cont := &admin.Audit{}
|
||||||
|
aR := rg.Group("/audit_conn").Use(middleware.AdminPrivilege())
|
||||||
|
aR.GET("/list", cont.ConnList)
|
||||||
|
aR.POST("/delete", cont.ConnDelete)
|
||||||
|
afR := rg.Group("/audit_file").Use(middleware.AdminPrivilege())
|
||||||
|
afR.GET("/list", cont.FileList)
|
||||||
|
afR.POST("/delete", cont.FileDelete)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func FileBind(rg *gin.RouterGroup) {
|
func FileBind(rg *gin.RouterGroup) {
|
||||||
|
|||||||
@@ -47,17 +47,15 @@ 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)
|
|
||||||
}
|
}
|
||||||
|
au := &api.Audit{}
|
||||||
|
//[method:POST] [uri:/api/audit/conn]
|
||||||
|
frg.POST("/audit/conn", au.AuditConn)
|
||||||
|
//[method:POST] [uri:/api/audit/file]
|
||||||
|
frg.POST("/audit/file", au.AuditFile)
|
||||||
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 +113,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)
|
||||||
g.GET("/webclient-config/index.js", i.ConfigJs)
|
|
||||||
g.StaticFS("/webclient", http.Dir(global.Config.Gin.ResourcesPath+"/web"))
|
if global.Config.App.WebClient == 1 {
|
||||||
|
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("/_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{
|
||||||
|
|||||||
46
model/audit.go
Normal file
46
model/audit.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuditActionNew = "new"
|
||||||
|
AuditActionClose = "close"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuditConn struct {
|
||||||
|
IdModel
|
||||||
|
Action string `json:"action" gorm:"default:'';not null;"`
|
||||||
|
ConnId int64 `json:"conn_id" gorm:"default:0;not null;index"`
|
||||||
|
PeerId string `json:"peer_id" gorm:"default:'';not null;index"`
|
||||||
|
FromPeer string `json:"from_peer" gorm:"default:'';not null;"`
|
||||||
|
FromName string `json:"from_name" gorm:"default:'';not null;"`
|
||||||
|
Ip string `json:"ip" gorm:"default:'';not null;"`
|
||||||
|
SessionId string `json:"session_id" gorm:"default:'';not null;"`
|
||||||
|
Type int `json:"type" gorm:"default:0;not null;"`
|
||||||
|
Uuid string `json:"uuid" gorm:"default:'';not null;"`
|
||||||
|
CloseTime int64 `json:"close_time" gorm:"default:0;not null;"`
|
||||||
|
TimeModel
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuditConnList struct {
|
||||||
|
AuditConns []*AuditConn `json:"list"`
|
||||||
|
Pagination
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuditFile struct {
|
||||||
|
IdModel
|
||||||
|
FromPeer string `json:"from_peer" gorm:"default:'';not null;index"`
|
||||||
|
Info string `json:"info" gorm:"default:'';not null;"`
|
||||||
|
IsFile bool `json:"is_file" gorm:"default:0;not null;"`
|
||||||
|
Path string `json:"path" gorm:"default:'';not null;"`
|
||||||
|
PeerId string `json:"peer_id" gorm:"default:'';not null;index"`
|
||||||
|
Type int `json:"type" gorm:"default:0;not null;"`
|
||||||
|
Uuid string `json:"uuid" gorm:"default:'';not null;"`
|
||||||
|
Ip string `json:"ip" gorm:"default:'';not null;"`
|
||||||
|
Num int `json:"num" gorm:"default:0;not null;"`
|
||||||
|
FromName string `json:"from_name" gorm:"default:'';not null;"`
|
||||||
|
TimeModel
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuditFileList struct {
|
||||||
|
AuditFiles []*AuditFile `json:"list"`
|
||||||
|
Pagination
|
||||||
|
}
|
||||||
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
545
resources/web/js/src/globals.js
vendored
545
resources/web/js/src/globals.js
vendored
@@ -1,41 +1,44 @@
|
|||||||
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)
|
||||||
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0, 4));
|
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDesktop() {
|
export function isDesktop() {
|
||||||
return !isMobile();
|
return !isMobile();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function msgbox(type, title, text) {
|
export function msgbox(type, title, text) {
|
||||||
if (!type || (type == 'error' && !text)) return;
|
if (!type || (type == 'error' && !text)) return;
|
||||||
const text2 = text.toLowerCase();
|
const text2 = text.toLowerCase();
|
||||||
var hasRetry = checkIfRetry(type, title, text) ? 'true' : '';
|
var hasRetry = checkIfRetry(type, title, text) ? 'true' : '';
|
||||||
onGlobalEvent(JSON.stringify({ name: 'msgbox', type, title, text, hasRetry }));
|
onGlobalEvent(JSON.stringify({name: 'msgbox', type, title, text, hasRetry}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsonfyForDart(payload) {
|
function jsonfyForDart(payload) {
|
||||||
var tmp = {};
|
var tmp = {};
|
||||||
for (const [key, value] of Object.entries(payload)) {
|
for (const [key, value] of Object.entries(payload)) {
|
||||||
if (!key) continue;
|
if (!key) continue;
|
||||||
tmp[key] = value instanceof Uint8Array ? '[' + value.toString() + ']' : JSON.stringify(value);
|
tmp[key] = value instanceof Uint8Array ? '[' + value.toString() + ']' : JSON.stringify(value);
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pushEvent(name, payload) {
|
export function pushEvent(name, payload) {
|
||||||
payload = jsonfyForDart(payload);
|
payload = jsonfyForDart(payload);
|
||||||
payload.name = name;
|
payload.name = name;
|
||||||
onGlobalEvent(JSON.stringify(payload));
|
onGlobalEvent(JSON.stringify(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
let yuvWorker;
|
let yuvWorker;
|
||||||
@@ -45,339 +48,347 @@ let pixels;
|
|||||||
let flipPixels;
|
let flipPixels;
|
||||||
let oldSize;
|
let oldSize;
|
||||||
if (YUVCanvas.WebGLFrameSink.isAvailable()) {
|
if (YUVCanvas.WebGLFrameSink.isAvailable()) {
|
||||||
var canvas = document.createElement('canvas');
|
var canvas = document.createElement('canvas');
|
||||||
yuvCanvas = YUVCanvas.attach(canvas, { webGL: true });
|
yuvCanvas = YUVCanvas.attach(canvas, {webGL: true});
|
||||||
gl = canvas.getContext("webgl");
|
gl = canvas.getContext("webgl");
|
||||||
} else {
|
} else {
|
||||||
yuvWorker = new Worker("./yuv.js");
|
yuvWorker = new Worker("./yuv.js");
|
||||||
}
|
}
|
||||||
let testSpeed = [0, 0];
|
let testSpeed = [0, 0];
|
||||||
|
|
||||||
export function draw(frame) {
|
export function draw(frame) {
|
||||||
if (yuvWorker) {
|
if (yuvWorker) {
|
||||||
// frame's (y/u/v).bytes already detached, can not transferrable any more.
|
// frame's (y/u/v).bytes already detached, can not transferrable any more.
|
||||||
yuvWorker.postMessage(frame);
|
yuvWorker.postMessage(frame);
|
||||||
} else {
|
} else {
|
||||||
var tm0 = new Date().getTime();
|
var tm0 = new Date().getTime();
|
||||||
yuvCanvas.drawFrame(frame);
|
yuvCanvas.drawFrame(frame);
|
||||||
var width = canvas.width;
|
var width = canvas.width;
|
||||||
var height = canvas.height;
|
var height = canvas.height;
|
||||||
var size = width * height * 4;
|
var size = width * height * 4;
|
||||||
if (size != oldSize) {
|
if (size != oldSize) {
|
||||||
pixels = new Uint8Array(size);
|
pixels = new Uint8Array(size);
|
||||||
flipPixels = new Uint8Array(size);
|
flipPixels = new Uint8Array(size);
|
||||||
oldSize = size;
|
oldSize = size;
|
||||||
|
}
|
||||||
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
||||||
|
const row = width * 4;
|
||||||
|
const end = (height - 1) * row;
|
||||||
|
for (let i = 0; i < size; i += row) {
|
||||||
|
flipPixels.set(pixels.subarray(i, i + row), end - i);
|
||||||
|
}
|
||||||
|
onRgba(flipPixels);
|
||||||
|
testSpeed[1] += new Date().getTime() - tm0;
|
||||||
|
testSpeed[0] += 1;
|
||||||
|
if (testSpeed[0] > 30) {
|
||||||
|
console.log('gl: ' + parseInt('' + testSpeed[1] / testSpeed[0]));
|
||||||
|
testSpeed = [0, 0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
/*
|
||||||
const row = width * 4;
|
var testCanvas = document.getElementById("test-yuv-decoder-canvas");
|
||||||
const end = (height - 1) * row;
|
if (testCanvas && currentFrame) {
|
||||||
for (let i = 0; i < size; i += row) {
|
var ctx = testCanvas.getContext("2d");
|
||||||
flipPixels.set(pixels.subarray(i, i + row), end - i);
|
testCanvas.width = frame.format.displayWidth;
|
||||||
|
testCanvas.height = frame.format.displayHeight;
|
||||||
|
var img = ctx.createImageData(testCanvas.width, testCanvas.height);
|
||||||
|
img.data.set(currentFrame);
|
||||||
|
ctx.putImageData(img, 0, 0);
|
||||||
}
|
}
|
||||||
onRgba(flipPixels);
|
*/
|
||||||
testSpeed[1] += new Date().getTime() - tm0;
|
|
||||||
testSpeed[0] += 1;
|
|
||||||
if (testSpeed[0] > 30) {
|
|
||||||
console.log('gl: ' + parseInt('' + testSpeed[1] / testSpeed[0]));
|
|
||||||
testSpeed = [0, 0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
var testCanvas = document.getElementById("test-yuv-decoder-canvas");
|
|
||||||
if (testCanvas && currentFrame) {
|
|
||||||
var ctx = testCanvas.getContext("2d");
|
|
||||||
testCanvas.width = frame.format.displayWidth;
|
|
||||||
testCanvas.height = frame.format.displayHeight;
|
|
||||||
var img = ctx.createImageData(testCanvas.width, testCanvas.height);
|
|
||||||
img.data.set(currentFrame);
|
|
||||||
ctx.putImageData(img, 0, 0);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendOffCanvas(c) {
|
export function sendOffCanvas(c) {
|
||||||
let canvas = c.transferControlToOffscreen();
|
let canvas = c.transferControlToOffscreen();
|
||||||
yuvWorker.postMessage({ canvas }, [canvas]);
|
yuvWorker.postMessage({canvas}, [canvas]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setConn(conn) {
|
export function setConn(conn) {
|
||||||
window.curConn = conn;
|
window.curConn = conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getConn() {
|
export function getConn() {
|
||||||
return window.curConn;
|
return window.curConn;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startConn(id) {
|
export async function startConn(id) {
|
||||||
setByName('remote_id', id);
|
setByName('remote_id', id);
|
||||||
await curConn.start(id);
|
await curConn.start(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function close() {
|
export function close() {
|
||||||
getConn()?.close();
|
getConn()?.close();
|
||||||
setConn(undefined);
|
setConn(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function newConn() {
|
export function newConn() {
|
||||||
window.curConn?.close();
|
window.curConn?.close();
|
||||||
const conn = new Connection();
|
const conn = new Connection();
|
||||||
setConn(conn);
|
setConn(conn);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
sodium = _sodium;
|
sodium = _sodium;
|
||||||
}
|
}
|
||||||
if (typeof pk == 'string') {
|
if (typeof pk == 'string') {
|
||||||
pk = decodeBase64(pk);
|
pk = decodeBase64(pk);
|
||||||
}
|
}
|
||||||
return sodium.crypto_sign_open(signed, pk);
|
return sodium.crypto_sign_open(signed, pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeBase64(pk) {
|
export function decodeBase64(pk) {
|
||||||
return sodium.from_base64(pk, sodium.base64_variants.ORIGINAL);
|
return sodium.from_base64(pk, sodium.base64_variants.ORIGINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function genBoxKeyPair() {
|
export function genBoxKeyPair() {
|
||||||
const pair = sodium.crypto_box_keypair();
|
const pair = sodium.crypto_box_keypair();
|
||||||
const sk = pair.privateKey;
|
const sk = pair.privateKey;
|
||||||
const pk = pair.publicKey;
|
const pk = pair.publicKey;
|
||||||
return [sk, pk];
|
return [sk, pk];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function genSecretKey() {
|
export function genSecretKey() {
|
||||||
return sodium.crypto_secretbox_keygen();
|
return sodium.crypto_secretbox_keygen();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function seal(unsigned, theirPk, ourSk) {
|
export function seal(unsigned, theirPk, ourSk) {
|
||||||
const nonce = Uint8Array.from(Array(24).fill(0));
|
const nonce = Uint8Array.from(Array(24).fill(0));
|
||||||
return sodium.crypto_box_easy(unsigned, nonce, theirPk, ourSk);
|
return sodium.crypto_box_easy(unsigned, nonce, theirPk, ourSk);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeOnce(value) {
|
function makeOnce(value) {
|
||||||
var byteArray = Array(24).fill(0);
|
var byteArray = Array(24).fill(0);
|
||||||
|
|
||||||
for (var index = 0; index < byteArray.length && value > 0; index++) {
|
for (var index = 0; index < byteArray.length && value > 0; index++) {
|
||||||
var byte = value & 0xff;
|
var byte = value & 0xff;
|
||||||
byteArray[index] = byte;
|
byteArray[index] = byte;
|
||||||
value = (value - byte) / 256;
|
value = (value - byte) / 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Uint8Array.from(byteArray);
|
return Uint8Array.from(byteArray);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function encrypt(unsigned, nonce, key) {
|
export function encrypt(unsigned, nonce, key) {
|
||||||
return sodium.crypto_secretbox_easy(unsigned, makeOnce(nonce), key);
|
return sodium.crypto_secretbox_easy(unsigned, makeOnce(nonce), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decrypt(signed, nonce, key) {
|
export function decrypt(signed, nonce, key) {
|
||||||
return sodium.crypto_secretbox_open_easy(signed, makeOnce(nonce), key);
|
return sodium.crypto_secretbox_open_easy(signed, makeOnce(nonce), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.setByName = (name, value) => {
|
window.setByName = (name, value) => {
|
||||||
switch (name) {
|
myconsole('setByName', name, value);
|
||||||
case 'remote_id':
|
switch (name) {
|
||||||
localStorage.setItem('remote-id', value);
|
case 'remote_id':
|
||||||
break;
|
localStorage.setItem('remote-id', value);
|
||||||
case 'connect':
|
break;
|
||||||
newConn();
|
case 'connect':
|
||||||
startConn(value);
|
newConn();
|
||||||
break;
|
startConn(value);
|
||||||
case 'login':
|
break;
|
||||||
value = JSON.parse(value);
|
case 'login':
|
||||||
curConn.setRemember(value.remember == 'true');
|
value = JSON.parse(value);
|
||||||
curConn.login(value.password);
|
curConn.setRemember(value.remember == 'true');
|
||||||
break;
|
curConn.login(value.password);
|
||||||
case 'close':
|
break;
|
||||||
close();
|
case 'close':
|
||||||
break;
|
close();
|
||||||
case 'refresh':
|
break;
|
||||||
curConn.refresh();
|
case 'refresh':
|
||||||
break;
|
curConn.refresh();
|
||||||
case 'reconnect':
|
break;
|
||||||
curConn.reconnect();
|
case 'reconnect':
|
||||||
break;
|
curConn.reconnect();
|
||||||
case 'toggle_option':
|
break;
|
||||||
curConn.toggleOption(value);
|
case 'toggle_option':
|
||||||
break;
|
curConn.toggleOption(value);
|
||||||
case 'image_quality':
|
break;
|
||||||
curConn.setImageQuality(value);
|
case 'image_quality':
|
||||||
break;
|
curConn.setImageQuality(value);
|
||||||
case 'lock_screen':
|
break;
|
||||||
curConn.lockScreen();
|
case 'lock_screen':
|
||||||
break;
|
curConn.lockScreen();
|
||||||
case 'ctrl_alt_del':
|
break;
|
||||||
curConn.ctrlAltDel();
|
case 'ctrl_alt_del':
|
||||||
break;
|
curConn.ctrlAltDel();
|
||||||
case 'switch_display':
|
break;
|
||||||
curConn.switchDisplay(value);
|
case 'switch_display':
|
||||||
break;
|
curConn.switchDisplay(value);
|
||||||
case 'remove':
|
break;
|
||||||
const peers = getPeers();
|
case 'remove':
|
||||||
delete peers[value];
|
const peers = getPeers();
|
||||||
localStorage.setItem('peers', JSON.stringify(peers));
|
delete peers[value];
|
||||||
break;
|
localStorage.setItem('peers', JSON.stringify(peers));
|
||||||
case 'input_key':
|
break;
|
||||||
value = JSON.parse(value);
|
case 'input_key':
|
||||||
curConn.inputKey(value.name, value.down == 'true', value.press == 'true', value.alt == 'true', value.ctrl == 'true', value.shift == 'true', value.command == 'true');
|
value = JSON.parse(value);
|
||||||
break;
|
curConn.inputKey(value.name, value.down == 'true', value.press == 'true', value.alt == 'true', value.ctrl == 'true', value.shift == 'true', value.command == 'true');
|
||||||
case 'input_string':
|
break;
|
||||||
curConn.inputString(value);
|
case 'input_string':
|
||||||
break;
|
curConn.inputString(value);
|
||||||
case 'send_mouse':
|
break;
|
||||||
let mask = 0;
|
case 'send_mouse':
|
||||||
value = JSON.parse(value);
|
let mask = 0;
|
||||||
switch (value.type) {
|
value = JSON.parse(value);
|
||||||
case 'down':
|
switch (value.type) {
|
||||||
mask = 1;
|
case 'down':
|
||||||
break;
|
mask = 1;
|
||||||
case 'up':
|
break;
|
||||||
mask = 2;
|
case 'up':
|
||||||
break;
|
mask = 2;
|
||||||
case 'wheel':
|
break;
|
||||||
mask = 3;
|
case 'wheel':
|
||||||
break;
|
mask = 3;
|
||||||
}
|
break;
|
||||||
switch (value.buttons) {
|
}
|
||||||
case 'left':
|
switch (value.buttons) {
|
||||||
mask |= 1 << 3;
|
case 'left':
|
||||||
break;
|
mask |= 1 << 3;
|
||||||
case 'right':
|
break;
|
||||||
mask |= 2 << 3;
|
case 'right':
|
||||||
break;
|
mask |= 2 << 3;
|
||||||
case 'wheel':
|
break;
|
||||||
mask |= 4 << 3;
|
case 'wheel':
|
||||||
}
|
mask |= 4 << 3;
|
||||||
curConn.inputMouse(mask, parseInt(value.x || '0'), parseInt(value.y || '0'), value.alt == 'true', value.ctrl == 'true', value.shift == 'true', value.command == 'true');
|
}
|
||||||
break;
|
curConn.inputMouse(mask, parseInt(value.x || '0'), parseInt(value.y || '0'), value.alt == 'true', value.ctrl == 'true', value.shift == 'true', value.command == 'true');
|
||||||
case 'option':
|
break;
|
||||||
value = JSON.parse(value);
|
case 'option':
|
||||||
localStorage.setItem(value.name, value.value);
|
value = JSON.parse(value);
|
||||||
break;
|
localStorage.setItem(value.name, value.value);
|
||||||
case 'peer_option':
|
if (value.name === 'access_token' && value.value) {
|
||||||
value = JSON.parse(value);
|
getServerConf(value.value);
|
||||||
curConn.setOption(value.name, value.value);
|
}
|
||||||
break;
|
break;
|
||||||
case 'input_os_password':
|
case 'peer_option':
|
||||||
curConn.inputOsPassword(value);
|
value = JSON.parse(value);
|
||||||
break;
|
curConn.setOption(value.name, value.value);
|
||||||
default:
|
break;
|
||||||
break;
|
case 'input_os_password':
|
||||||
}
|
curConn.inputOsPassword(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.getByName = (name, arg) => {
|
window.getByName = (name, arg) => {
|
||||||
let v = _getByName(name, arg);
|
let v = _getByName(name, arg);
|
||||||
if (typeof v == 'string' || v instanceof String) return v;
|
myconsole('getByName', name, arg, v);
|
||||||
if (v == undefined || v == null) return '';
|
if (typeof v == 'string' || v instanceof String) return v;
|
||||||
return JSON.stringify(v);
|
if (v == undefined || v == null) return '';
|
||||||
|
return JSON.stringify(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPeersForDart() {
|
function getPeersForDart() {
|
||||||
const peers = [];
|
const peers = [];
|
||||||
for (const [id, value] of Object.entries(getPeers())) {
|
for (const [id, value] of Object.entries(getPeers())) {
|
||||||
if (!id) continue;
|
if (!id) continue;
|
||||||
const tm = value['tm'];
|
const tm = value['tm'];
|
||||||
const info = value['info'];
|
const info = value['info'];
|
||||||
if (!tm || !info) continue;
|
if (!tm || !info) continue;
|
||||||
peers.push([tm, id, info]);
|
peers.push([tm, id, info]);
|
||||||
}
|
}
|
||||||
return peers.sort().reverse().map(x => x.slice(1));
|
return peers.sort().reverse().map(x => x.slice(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getByName(name, arg) {
|
function _getByName(name, arg) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'peers':
|
case 'peers':
|
||||||
return getPeersForDart();
|
return getPeersForDart();
|
||||||
case 'remote_id':
|
case 'remote_id':
|
||||||
return localStorage.getItem('remote-id');
|
return localStorage.getItem('remote-id');
|
||||||
case 'remember':
|
case 'remember':
|
||||||
return curConn.getRemember();
|
return curConn.getRemember();
|
||||||
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);
|
||||||
case 'image_quality':
|
if (arg === 'access_token' && v) {
|
||||||
return curConn.getImageQuality();
|
getServerConf(v);
|
||||||
case 'translate':
|
}
|
||||||
arg = JSON.parse(arg);
|
return v;
|
||||||
return translate(arg.locale, arg.text);
|
case 'image_quality':
|
||||||
case 'peer_option':
|
return curConn.getImageQuality();
|
||||||
return curConn.getOption(arg);
|
case 'translate':
|
||||||
case 'test_if_valid_server':
|
arg = JSON.parse(arg);
|
||||||
break;
|
return translate(arg.locale, arg.text);
|
||||||
case 'version':
|
case 'peer_option':
|
||||||
return version;
|
return curConn.getOption(arg);
|
||||||
}
|
case 'test_if_valid_server':
|
||||||
return '';
|
break;
|
||||||
|
case 'version':
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
let opusWorker = new Worker("./libopus.js");
|
let opusWorker = new Worker("./libopus.js");
|
||||||
let pcmPlayer;
|
let pcmPlayer;
|
||||||
|
|
||||||
export function initAudio(channels, sampleRate) {
|
export function initAudio(channels, sampleRate) {
|
||||||
pcmPlayer = newAudioPlayer(channels, sampleRate);
|
pcmPlayer = newAudioPlayer(channels, sampleRate);
|
||||||
opusWorker.postMessage({ channels, sampleRate });
|
opusWorker.postMessage({channels, sampleRate});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function playAudio(packet) {
|
export function playAudio(packet) {
|
||||||
opusWorker.postMessage(packet, [packet.buffer]);
|
opusWorker.postMessage(packet, [packet.buffer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.init = async () => {
|
window.init = async () => {
|
||||||
if (yuvWorker) {
|
if (yuvWorker) {
|
||||||
yuvWorker.onmessage = (e) => {
|
yuvWorker.onmessage = (e) => {
|
||||||
onRgba(e.data);
|
onRgba(e.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
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');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPeers() {
|
export function getPeers() {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(localStorage.getItem('peers')) || {};
|
return JSON.parse(localStorage.getItem('peers')) || {};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function newAudioPlayer(channels, sampleRate) {
|
function newAudioPlayer(channels, sampleRate) {
|
||||||
return new PCMPlayer({
|
return new PCMPlayer({
|
||||||
channels,
|
channels,
|
||||||
sampleRate,
|
sampleRate,
|
||||||
flushingTime: 2000
|
flushingTime: 2000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function copyToClipboard(text) {
|
export function copyToClipboard(text) {
|
||||||
if (window.clipboardData && window.clipboardData.setData) {
|
if (window.clipboardData && window.clipboardData.setData) {
|
||||||
// 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.
|
document.body.appendChild(textarea);
|
||||||
document.body.appendChild(textarea);
|
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) {
|
||||||
|
console.warn("Copy to clipboard failed.", ex);
|
||||||
|
// return prompt("Copy to clipboard: Ctrl+C, Enter", text);
|
||||||
|
} finally {
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ex) {
|
|
||||||
console.warn("Copy to clipboard failed.", ex);
|
|
||||||
// return prompt("Copy to clipboard: Ctrl+C, Enter", text);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
document.body.removeChild(textarea);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
93
resources/web/js/src/ljw.js
vendored
93
resources/web/js/src/ljw.js
vendored
@@ -49,52 +49,51 @@ 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
|
||||||
fetch(apiserver + "/api/server-config", {
|
}
|
||||||
method: 'POST',
|
fetching = true
|
||||||
headers: {
|
fetch(apiserver + "/api/server-config", {
|
||||||
'Content-Type': 'application/json',
|
method: 'POST',
|
||||||
'Authorization': 'Bearer ' + token
|
headers: {
|
||||||
}
|
'Content-Type': 'application/json',
|
||||||
}
|
'Authorization': 'Bearer ' + token
|
||||||
).then(res => res.json()).then(res => {
|
}
|
||||||
if (res.code === 0) {
|
|
||||||
if (!localStorage.getItem('custom-rendezvous-server') || !localStorage.getItem('key')) {
|
|
||||||
localStorage.setItem('custom-rendezvous-server', res.data.id_server)
|
|
||||||
localStorage.setItem('key', res.data.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.data.peers) {
|
|
||||||
const oldPeers = JSON.parse(localStorage.getItem('peers')) || {}
|
|
||||||
let needUpdate = false
|
|
||||||
Object.keys(res.data.peers).forEach(k => {
|
|
||||||
if (!oldPeers[k]) {
|
|
||||||
oldPeers[k] = res.data.peers[k]
|
|
||||||
needUpdate = true
|
|
||||||
} else {
|
|
||||||
oldPeers[k].info = res.data.peers[k].info
|
|
||||||
}
|
|
||||||
if (oldPeers[k].info && oldPeers[k].info.hash && !oldPeers[k].password) {
|
|
||||||
let p1 = window.atob(oldPeers[k].info.hash)
|
|
||||||
const pwd = stringToUint8Array(p1)
|
|
||||||
oldPeers[k].password = pwd.toString()
|
|
||||||
oldPeers[k].remember = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
localStorage.setItem('peers', JSON.stringify(oldPeers))
|
|
||||||
if (needUpdate) {
|
|
||||||
window.location.reload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
autoWriteServer()
|
|
||||||
}
|
}
|
||||||
}, 1000)
|
).then(res => res.json()).then(res => {
|
||||||
|
fetching = false
|
||||||
|
if (res.code === 0) {
|
||||||
|
if (!localStorage.getItem('custom-rendezvous-server') || !localStorage.getItem('key')) {
|
||||||
|
localStorage.setItem('custom-rendezvous-server', res.data.id_server)
|
||||||
|
localStorage.setItem('key', res.data.key)
|
||||||
|
}
|
||||||
|
if (res.data.peers) {
|
||||||
|
const oldPeers = JSON.parse(localStorage.getItem('peers')) || {}
|
||||||
|
let needUpdate = false
|
||||||
|
Object.keys(res.data.peers).forEach(k => {
|
||||||
|
if (!oldPeers[k]) {
|
||||||
|
oldPeers[k] = res.data.peers[k]
|
||||||
|
needUpdate = true
|
||||||
|
} else {
|
||||||
|
oldPeers[k].info = res.data.peers[k].info
|
||||||
|
}
|
||||||
|
if (oldPeers[k].info && oldPeers[k].info.hash && !oldPeers[k].password) {
|
||||||
|
let p1 = window.atob(oldPeers[k].info.hash)
|
||||||
|
const pwd = stringToUint8Array(p1)
|
||||||
|
oldPeers[k].password = pwd.toString()
|
||||||
|
oldPeers[k].remember = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
localStorage.setItem('peers', JSON.stringify(oldPeers))
|
||||||
|
if (needUpdate) {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(_ => {
|
||||||
|
fetching = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
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 ""
|
||||||
|
}
|
||||||
|
|||||||
87
service/audit.go
Normal file
87
service/audit.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuditService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *AuditService) AuditConnList(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AuditConnList) {
|
||||||
|
res = &model.AuditConnList{}
|
||||||
|
res.Page = int64(page)
|
||||||
|
res.PageSize = int64(pageSize)
|
||||||
|
tx := global.DB.Model(&model.AuditConn{})
|
||||||
|
if where != nil {
|
||||||
|
where(tx)
|
||||||
|
}
|
||||||
|
tx.Count(&res.Total)
|
||||||
|
tx.Scopes(Paginate(page, pageSize))
|
||||||
|
tx.Find(&res.AuditConns)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 创建
|
||||||
|
func (as *AuditService) CreateAuditConn(u *model.AuditConn) error {
|
||||||
|
res := global.DB.Create(u).Error
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
func (as *AuditService) DeleteAuditConn(u *model.AuditConn) error {
|
||||||
|
return global.DB.Delete(u).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 更新
|
||||||
|
func (as *AuditService) UpdateAuditConn(u *model.AuditConn) error {
|
||||||
|
return global.DB.Model(u).Updates(u).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// InfoByPeerIdAndConnId
|
||||||
|
func (as *AuditService) InfoByPeerIdAndConnId(peerId string, connId int64) (res *model.AuditConn) {
|
||||||
|
res = &model.AuditConn{}
|
||||||
|
global.DB.Where("peer_id = ? and conn_id = ?", peerId, connId).First(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnInfoById
|
||||||
|
func (as *AuditService) ConnInfoById(id uint) (res *model.AuditConn) {
|
||||||
|
res = &model.AuditConn{}
|
||||||
|
global.DB.Where("id = ?", id).First(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileInfoById
|
||||||
|
func (as *AuditService) FileInfoById(id uint) (res *model.AuditFile) {
|
||||||
|
res = &model.AuditFile{}
|
||||||
|
global.DB.Where("id = ?", id).First(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *AuditService) AuditFileList(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AuditFileList) {
|
||||||
|
res = &model.AuditFileList{}
|
||||||
|
res.Page = int64(page)
|
||||||
|
res.PageSize = int64(pageSize)
|
||||||
|
tx := global.DB.Model(&model.AuditFile{})
|
||||||
|
if where != nil {
|
||||||
|
where(tx)
|
||||||
|
}
|
||||||
|
tx.Count(&res.Total)
|
||||||
|
tx.Scopes(Paginate(page, pageSize))
|
||||||
|
tx.Find(&res.AuditFiles)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAuditFile
|
||||||
|
func (as *AuditService) CreateAuditFile(u *model.AuditFile) error {
|
||||||
|
res := global.DB.Create(u).Error
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
func (as *AuditService) DeleteAuditFile(u *model.AuditFile) error {
|
||||||
|
return global.DB.Delete(u).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 更新
|
||||||
|
func (as *AuditService) UpdateAuditFile(u *model.AuditFile) error {
|
||||||
|
return global.DB.Model(u).Updates(u).Error
|
||||||
|
}
|
||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/github"
|
"golang.org/x/oauth2/github"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -167,36 +168,60 @@ func (os *OauthService) GetOauthConfig(op string) (error, *oauth2.Config) {
|
|||||||
return errors.New("ConfigNotFound"), nil
|
return errors.New("ConfigNotFound"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getHTTPClientWithProxy() *http.Client {
|
||||||
|
if global.Config.Proxy.Enable {
|
||||||
|
if global.Config.Proxy.Host == "" {
|
||||||
|
global.Logger.Warn("Proxy is enabled but proxy host is empty.")
|
||||||
|
return http.DefaultClient
|
||||||
|
}
|
||||||
|
proxyURL, err := url.Parse(global.Config.Proxy.Host)
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Warn("Invalid proxy URL: ", err)
|
||||||
|
return http.DefaultClient
|
||||||
|
}
|
||||||
|
transport := &http.Transport{
|
||||||
|
Proxy: http.ProxyURL(proxyURL),
|
||||||
|
}
|
||||||
|
return &http.Client{Transport: transport}
|
||||||
|
}
|
||||||
|
return http.DefaultClient
|
||||||
|
}
|
||||||
|
|
||||||
func (os *OauthService) GithubCallback(code string) (error error, userData *GithubUserdata) {
|
func (os *OauthService) GithubCallback(code string) (error error, userData *GithubUserdata) {
|
||||||
err, oauthConfig := os.GetOauthConfig(model.OauthTypeGithub)
|
err, oauthConfig := os.GetOauthConfig(model.OauthTypeGithub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
token, err := oauthConfig.Exchange(context.Background(), code)
|
|
||||||
|
// 使用代理配置创建 HTTP 客户端
|
||||||
|
httpClient := getHTTPClientWithProxy()
|
||||||
|
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, httpClient)
|
||||||
|
|
||||||
|
token, err := oauthConfig.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn(fmt.Printf("oauthConfig.Exchange() failed: %s\n", err))
|
global.Logger.Warn("oauthConfig.Exchange() failed: ", err)
|
||||||
error = errors.New("GetOauthTokenError")
|
error = errors.New("GetOauthTokenError")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建一个 HTTP 客户端,并将 access_token 添加到 Authorization 头中
|
// 使用带有代理的 HTTP 客户端获取用户信息
|
||||||
client := oauthConfig.Client(context.Background(), token)
|
client := oauthConfig.Client(ctx, token)
|
||||||
resp, err := client.Get("https://api.github.com/user")
|
resp, err := client.Get("https://api.github.com/user")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn("failed getting user info: %s\n", err)
|
global.Logger.Warn("failed getting user info: ", err)
|
||||||
error = errors.New("GetOauthUserInfoError")
|
error = errors.New("GetOauthUserInfoError")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func(Body io.ReadCloser) {
|
defer func(Body io.ReadCloser) {
|
||||||
err := Body.Close()
|
err := Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn("failed closing response body: %s\n", err)
|
global.Logger.Warn("failed closing response body: ", err)
|
||||||
}
|
}
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
// 在这里处理 GitHub 用户信息
|
// 解析用户信息
|
||||||
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
||||||
global.Logger.Warn("failed decoding user info: %s\n", err)
|
global.Logger.Warn("failed decoding user info: ", err)
|
||||||
error = errors.New("DecodeOauthUserInfoError")
|
error = errors.New("DecodeOauthUserInfoError")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -205,29 +230,39 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith
|
|||||||
|
|
||||||
func (os *OauthService) GoogleCallback(code string) (error error, userData *GoogleUserdata) {
|
func (os *OauthService) GoogleCallback(code string) (error error, userData *GoogleUserdata) {
|
||||||
err, oauthConfig := os.GetOauthConfig(model.OauthTypeGoogle)
|
err, oauthConfig := os.GetOauthConfig(model.OauthTypeGoogle)
|
||||||
token, err := oauthConfig.Exchange(context.Background(), code)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn(fmt.Printf("oauthConfig.Exchange() failed: %s\n", err))
|
return err, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用代理配置创建 HTTP 客户端
|
||||||
|
httpClient := getHTTPClientWithProxy()
|
||||||
|
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, httpClient)
|
||||||
|
|
||||||
|
token, err := oauthConfig.Exchange(ctx, code)
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Warn("oauthConfig.Exchange() failed: ", err)
|
||||||
error = errors.New("GetOauthTokenError")
|
error = errors.New("GetOauthTokenError")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 创建 HTTP 客户端,并将 access_token 添加到 Authorization 头中
|
|
||||||
client := oauthConfig.Client(context.Background(), token)
|
// 使用带有代理的 HTTP 客户端获取用户信息
|
||||||
|
client := oauthConfig.Client(ctx, token)
|
||||||
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
|
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn("failed getting user info: %s\n", err)
|
global.Logger.Warn("failed getting user info: ", err)
|
||||||
error = errors.New("GetOauthUserInfoError")
|
error = errors.New("GetOauthUserInfoError")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func(Body io.ReadCloser) {
|
defer func(Body io.ReadCloser) {
|
||||||
err := Body.Close()
|
err := Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn("failed closing response body: %s\n", err)
|
global.Logger.Warn("failed closing response body: ", err)
|
||||||
}
|
}
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
|
// 解析用户信息
|
||||||
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
||||||
global.Logger.Warn("failed decoding user info: %s\n", err)
|
global.Logger.Warn("failed decoding user info: ", err)
|
||||||
error = errors.New("DecodeOauthUserInfoError")
|
error = errors.New("DecodeOauthUserInfoError")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type Service struct {
|
|||||||
*GroupService
|
*GroupService
|
||||||
*OauthService
|
*OauthService
|
||||||
*LoginLogService
|
*LoginLogService
|
||||||
|
*AuditService
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *Service {
|
func New() *Service {
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ func (us *UserService) InfoById(id uint) *model.User {
|
|||||||
global.DB.Where("id = ?", id).First(u)
|
global.DB.Where("id = ?", id).First(u)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
func (us *UserService) InfoByUsername(un string) *model.User {
|
||||||
|
u := &model.User{}
|
||||||
|
global.DB.Where("username = ?", un).First(u)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
// InfoByOpenid 根据openid取用户信息
|
// InfoByOpenid 根据openid取用户信息
|
||||||
func (us *UserService) InfoByOpenid(openid string) *model.User {
|
func (us *UserService) InfoByOpenid(openid string) *model.User {
|
||||||
@@ -262,3 +267,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