Compare commits

..

3 Commits

Author SHA1 Message Date
ljw
ef414855f0 up docs 2024-09-24 15:16:07 +08:00
ljw
76cf35cdf0 up readme 2024-09-24 15:15:26 +08:00
ljw
9d7aa05032 add personal apis 2024-09-24 14:43:27 +08:00
22 changed files with 1784 additions and 181 deletions

View File

@@ -2,7 +2,7 @@
[English Doc](README_EN.md) [English Doc](README_EN.md)
本项目使用 Go 实现了 RustDesk 的 API并包含了 Web UI 和 Web 客户端。RustDesk 是一个远程桌面软件,提供了自托管的解决方案。 本项目使用 Go 实现了 RustDesk 的 API并包含了 Web Admin 和 Web 客户端。RustDesk 是一个远程桌面软件,提供了自托管的解决方案。
<div align=center> <div align=center>
<img src="https://img.shields.io/badge/golang-1.22-blue"/> <img src="https://img.shields.io/badge/golang-1.22-blue"/>
@@ -10,8 +10,30 @@
<img src="https://img.shields.io/badge/gorm-v1.25.7-green"/> <img src="https://img.shields.io/badge/gorm-v1.25.7-green"/>
<img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/> <img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/>
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/release.yml/badge.svg"/> <img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/release.yml/badge.svg"/>
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/docker.yml/badge.svg"/>
</div> </div>
# 特性
- PC端API
- 个人版API
- 登录
- 地址簿
- 群组
- 授权登录,支持`github``google`登录,支持`web后台`授权登录
- Web Admin
- 用户管理
- 设备管理
- 地址簿管理
- 标签管理
- 群组管理
- Oauth 管理
- 快速使用web client
- Web Client
- 自动获取API server
- 自动获取ID服务器和KEY
- 自动获取地址簿
## 使用前准备 ## 使用前准备
### [Rustdesk](https://github.com/rustdesk/rustdesk) ### [Rustdesk](https://github.com/rustdesk/rustdesk)
@@ -33,7 +55,7 @@
## 功能 ## 功能
### API 服务: 基本实现了PC端基础的接口。 ### API 服务: 基本实现了PC端基础的接口。支持Personal版本接口可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_PERSONAL`来控制是否启用
#### 登录 #### 登录
@@ -50,7 +72,7 @@
![pc_gr](docs/pc_gr.png) ![pc_gr](docs/pc_gr.png)
### **Web UI**: 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。 ### **Web Admin**: 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。
***前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)*** ***前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
@@ -119,7 +141,7 @@ rustdesk:
* 环境变量,变量名前缀是RUSTDESK_API环境变量如果存在将覆盖配置文件中的配置 * 环境变量,变量名前缀是RUSTDESK_API环境变量如果存在将覆盖配置文件中的配置
| 变量名 | 说明 | 示例 | | 变量名 | 说明 | 示例 |
|:------------------------------------|:-------------------------------------|-----------------------------| |-------------------------------------|--------------------------------------|-----------------------------|
| TZ | 时区 | Asia/Shanghai | | TZ | 时区 | Asia/Shanghai |
| -----GIN配置----- | ---------- | ---------- | | -----GIN配置----- | ---------- | ---------- |
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 | | RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
@@ -127,7 +149,8 @@ rustdesk:
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql默认sqlite | sqlite | | RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql默认sqlite | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 | | RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 | | RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
| -----MYSQL配置----- | -----数据库类型为sqlite时不用填----- | ---------- | | RUSTDESK_PERSONAL | 是否启用个人版API 1:启用,0:不启用; 默认启用 | 1 |
| -----MYSQL配置----- | ---------- | ---------- |
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root | | RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 | | RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 | | RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
@@ -241,6 +264,72 @@ lejianwen/rustdesk-api
``` ```
- 如果使用的是S6的镜像会需要修改启动脚本覆盖镜像中的`/etc/s6-overlay/s6-rc.d/hbbr/run`
和`/etc/s6-overlay/s6-rc.d/hbbr/run`
1. 创建`hbbr/run`
```bash
#!/command/with-contenv sh
cd /data
PARAMS=
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
/usr/bin/hbbr $PARAMS
```
2. 创建`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. 修改`docker-compose.yml`中的`s6`部分
```
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
```
#### 下载release直接运行 #### 下载release直接运行
下载地址[release](https://github.com/lejianwen/rustdesk-api/releases) 下载地址[release](https://github.com/lejianwen/rustdesk-api/releases)

View File

@@ -8,8 +8,31 @@ desktop software that provides self-hosted solutions.
<img src="https://img.shields.io/badge/gin-v1.9.0-lightBlue"/> <img src="https://img.shields.io/badge/gin-v1.9.0-lightBlue"/>
<img src="https://img.shields.io/badge/gorm-v1.25.7-green"/> <img src="https://img.shields.io/badge/gorm-v1.25.7-green"/>
<img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/> <img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/>
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/release.yml/badge.svg"/>
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/docker.yml/badge.svg"/>
</div> </div>
# Features
- PC API
- Personal API
- Login
- Address Book
- Groups
- Authorized login, supports `GitHub` and `Google` login, supports `web admin` authorized login
- Web Admin
- User Management
- Device Management
- Address Book Management
- Tag Management
- Group Management
- OAuth Management
- Quick access to web client
- Web Client
- Automatically obtain API server
- Automatically obtain ID server and KEY
- Automatically obtain address book
## Prerequisites ## Prerequisites
### [Rustdesk](https://github.com/rustdesk/rustdesk) ### [Rustdesk](https://github.com/rustdesk/rustdesk)
@@ -32,11 +55,12 @@ desktop software that provides self-hosted solutions.
## Features ## Features
### API Service: Basic implementation of the PC client's primary interfaces. ### 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_PERSONAL` environment variable.
#### Login #### Login
- Added `GitHub` and `Google` login, which can be used after configuration in the admin panel. See the OAuth configuration section - Added `GitHub` and `Google` login, which can be used after configuration in the admin panel. See the OAuth
configuration section
for details. for details.
- Added authorization login for the web admin panel. - Added authorization login for the web admin panel.
@@ -50,7 +74,10 @@ desktop software that provides self-hosted solutions.
![pc_gr](docs/pc_gr.png) ![pc_gr](docs/pc_gr.png)
### **Web UI**: The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and displaying data. ### **Web UI
**: 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)*** ***Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
@@ -67,7 +94,8 @@ installation are `admin` `admin`, please change the password immediately.***
![web_admin_gr](docs/web_admin_gr.png) ![web_admin_gr](docs/web_admin_gr.png)
5. You can open the web client directly for convenience: 5. You can open the web client directly for convenience:
![web_webclient](docs/admin_webclient.png) ![web_webclient](docs/admin_webclient.png)
6. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in the admin 6. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in
the admin
panel. panel.
![web_admin_oauth](docs/web_admin_oauth.png) ![web_admin_oauth](docs/web_admin_oauth.png)
- Create a `GitHub OAuth App` - Create a `GitHub OAuth App`
@@ -84,7 +112,9 @@ installation are `admin` `admin`, please change the password immediately.***
3. After logging in, the ID server and key will be automatically synced. 3. After logging in, the ID server and key will be automatically synced.
4. The address book will also be automatically saved to the web client for convenient use. 4. The address book will also be automatically saved to the web client for convenient use.
### **Automated Documentation** : API documentation is generated using Swag, making it easier for developers to understand and use the API. ### **Automated Documentation
** : API documentation is generated using Swag, making it easier for developers to understand and use the API.
1. Admin panel docs: `<your server>/admin/swagger/index.html` 1. Admin panel docs: `<your server>/admin/swagger/index.html`
2. PC client docs: `<your server>/swagger/index.html` 2. PC client docs: `<your server>/swagger/index.html`
@@ -125,11 +155,13 @@ rustdesk:
| Variable Name | Description | Example | | Variable Name | Description | Example |
|------------------------------------|-----------------------------------------------------------|--------------------------------| |------------------------------------|-----------------------------------------------------------|--------------------------------|
| ----- GIN Configuration ----- | --------------------------------------- | ------------------------------ | | ----- GIN Configuration ----- | --------------------------------------- | ------------------------------ |
| TZ | 时区 | Asia/Shanghai |
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 | | RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
| ----- GORM Configuration ----- | --------------------------------------- | ------------------------------ | | ----- GORM Configuration ----- | --------------------------------------- | ------------------------------ |
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite | | RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 | | RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 | | RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
| RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
| ----- MYSQL Configuration ----- | --------------------------------------- | ------------------------------ | | ----- MYSQL Configuration ----- | --------------------------------------- | ------------------------------ |
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root | | RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 | | RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
@@ -241,6 +273,70 @@ lejianwen/rustdesk-api
restart: unless-stopped restart: unless-stopped
``` ```
- If you are using an S6 image, you need to modify the startup script `/etc/s6-overlay/s6-rc.d/hbbr/run`
and `/etc/s6-overlay/s6-rc.d/hbbr/run`
1. create `hbbr/run`
```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

View File

@@ -157,7 +157,7 @@ func ApiInitValidator() {
} }
func DatabaseAutoUpdate() { func DatabaseAutoUpdate() {
version := 103 version := 126
db := global.DB db := global.DB

View File

@@ -17,6 +17,7 @@ rustdesk:
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://192.168.1.66:21114"
key: "123456789" key: "123456789"
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

View File

@@ -5,4 +5,5 @@ type Rustdesk struct {
RelayServer string `mapstructure:"relay-server"` RelayServer string `mapstructure:"relay-server"`
ApiServer string `mapstructure:"api-server"` ApiServer string `mapstructure:"api-server"`
Key string `mapstructure:"key"` Key string `mapstructure:"key"`
Personal int `mapstructure:"personal"`
} }

View File

@@ -2266,7 +2266,7 @@ const docTemplateadmin = `{
"alias": { "alias": {
"type": "string" "type": "string"
}, },
"force_always_relay": { "forceAlwaysRelay": {
"type": "boolean" "type": "boolean"
}, },
"hash": { "hash": {
@@ -2434,8 +2434,7 @@ const docTemplateadmin = `{
"type": "object", "type": "object",
"required": [ "required": [
"color", "color",
"name", "name"
"user_id"
], ],
"properties": { "properties": {
"color": { "color": {

View File

@@ -2259,7 +2259,7 @@
"alias": { "alias": {
"type": "string" "type": "string"
}, },
"force_always_relay": { "forceAlwaysRelay": {
"type": "boolean" "type": "boolean"
}, },
"hash": { "hash": {
@@ -2427,8 +2427,7 @@
"type": "object", "type": "object",
"required": [ "required": [
"color", "color",
"name", "name"
"user_id"
], ],
"properties": { "properties": {
"color": { "color": {

View File

@@ -16,7 +16,7 @@ definitions:
properties: properties:
alias: alias:
type: string type: string
force_always_relay: forceAlwaysRelay:
type: boolean type: boolean
hash: hash:
type: string type: string
@@ -141,7 +141,6 @@ definitions:
required: required:
- color - color
- name - name
- user_id
type: object type: object
admin.UserForm: admin.UserForm:
properties: properties:

View File

@@ -136,7 +136,7 @@ const docTemplateapi = `{
"application/json" "application/json"
], ],
"tags": [ "tags": [
"地址" "地址[Personal]"
], ],
"summary": "标签添加", "summary": "标签添加",
"responses": { "responses": {
@@ -155,14 +155,14 @@ const docTemplateapi = `{
} }
} }
}, },
"/ab/personal": { "/ab/peer/add/{guid}": {
"post": { "post": {
"security": [ "security": [
{ {
"BearerAuth": [] "BearerAuth": []
} }
], ],
"description": "个人信息", "description": "添加地址",
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@@ -170,9 +170,136 @@ const docTemplateapi = `{
"application/json" "application/json"
], ],
"tags": [ "tags": [
"用户" "地址[Personal]"
], ],
"summary": "个人信息", "summary": "添加地址",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "删除地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "删除地址",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/ab/peer/update/{guid}": {
"put": {
"security": [
{
"BearerAuth": []
}
],
"description": "更新地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "更新地址",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/ab/peers": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "地址列表",
"parameters": [ "parameters": [
{ {
"description": "string valid", "description": "string valid",
@@ -199,6 +326,283 @@ const docTemplateapi = `{
} }
} }
}, },
"/ab/personal": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "个人地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "个人地址",
"parameters": [
{
"description": "string valid",
"name": "string",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/ab/settings": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "设置",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "设置",
"parameters": [
{
"description": "string valid",
"name": "string",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/ab/shared/profiles": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "共享",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "共享地址簿",
"parameters": [
{
"description": "string valid",
"name": "string",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/ab/tag/rename/{guid}": {
"put": {
"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/tag/update/{guid}": {
"put": {
"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/tag/{guid}": {
"delete": {
"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/tags/{guid}": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "标签",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "标签",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/model.TagList"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/api": { "/api": {
"get": { "get": {
"security": [ "security": [
@@ -389,35 +793,6 @@ const docTemplateapi = `{
} }
} }
}, },
"/oauth/login": {
"get": {
"description": "WebOauthLogin",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Oauth"
],
"summary": "WebOauthLogin",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/oidc/auth": { "/oidc/auth": {
"post": { "post": {
"description": "OidcAuth", "description": "OidcAuth",
@@ -882,6 +1257,26 @@ const docTemplateapi = `{
} }
} }
}, },
"model.TagList": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Tag"
}
},
"page": {
"type": "integer"
},
"page_size": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
},
"response.DataResponse": { "response.DataResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -129,7 +129,7 @@
"application/json" "application/json"
], ],
"tags": [ "tags": [
"地址" "地址[Personal]"
], ],
"summary": "标签添加", "summary": "标签添加",
"responses": { "responses": {
@@ -148,14 +148,14 @@
} }
} }
}, },
"/ab/personal": { "/ab/peer/add/{guid}": {
"post": { "post": {
"security": [ "security": [
{ {
"BearerAuth": [] "BearerAuth": []
} }
], ],
"description": "个人信息", "description": "添加地址",
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@@ -163,9 +163,136 @@
"application/json" "application/json"
], ],
"tags": [ "tags": [
"用户" "地址[Personal]"
], ],
"summary": "个人信息", "summary": "添加地址",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "删除地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "删除地址",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/ab/peer/update/{guid}": {
"put": {
"security": [
{
"BearerAuth": []
}
],
"description": "更新地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "更新地址",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/ab/peers": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "地址列表",
"parameters": [ "parameters": [
{ {
"description": "string valid", "description": "string valid",
@@ -192,6 +319,283 @@
} }
} }
}, },
"/ab/personal": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "个人地址",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "个人地址",
"parameters": [
{
"description": "string valid",
"name": "string",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/ab/settings": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "设置",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "设置",
"parameters": [
{
"description": "string valid",
"name": "string",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/ab/shared/profiles": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "共享",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "共享地址簿",
"parameters": [
{
"description": "string valid",
"name": "string",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/ab/tag/rename/{guid}": {
"put": {
"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/tag/update/{guid}": {
"put": {
"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/tag/{guid}": {
"delete": {
"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/tags/{guid}": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "标签",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"地址[Personal]"
],
"summary": "标签",
"parameters": [
{
"type": "string",
"description": "id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/model.TagList"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.ErrorResponse"
}
}
}
}
},
"/api": { "/api": {
"get": { "get": {
"security": [ "security": [
@@ -382,35 +786,6 @@
} }
} }
}, },
"/oauth/login": {
"get": {
"description": "WebOauthLogin",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Oauth"
],
"summary": "WebOauthLogin",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/oidc/auth": { "/oidc/auth": {
"post": { "post": {
"description": "OidcAuth", "description": "OidcAuth",
@@ -875,6 +1250,26 @@
} }
} }
}, },
"model.TagList": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Tag"
}
},
"page": {
"type": "integer"
},
"page_size": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
},
"response.DataResponse": { "response.DataResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -103,6 +103,19 @@ definitions:
user_id: user_id:
type: integer type: integer
type: object type: object
model.TagList:
properties:
list:
items:
$ref: '#/definitions/model.Tag'
type: array
page:
type: integer
page_size:
type: integer
total:
type: integer
type: object
response.DataResponse: response.DataResponse:
properties: properties:
data: {} data: {}
@@ -215,12 +228,92 @@ paths:
- BearerAuth: [] - BearerAuth: []
summary: 标签添加 summary: 标签添加
tags: tags:
- 地址 - 地址[Personal]
/ab/personal: /ab/peer/add/{guid}:
delete:
consumes:
- application/json
description: 删除地址
parameters:
- description: id
in: path
name: id
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]
post: post:
consumes: consumes:
- application/json - application/json
description: 个人信息 description: 添加地址
parameters:
- description: id
in: path
name: id
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/peer/update/{guid}:
put:
consumes:
- application/json
description: 更新地址
parameters:
- description: id
in: path
name: id
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/peers:
post:
consumes:
- application/json
description: 地址
parameters: parameters:
- description: string valid - description: string valid
in: body in: body
@@ -240,9 +333,180 @@ paths:
$ref: '#/definitions/response.Response' $ref: '#/definitions/response.Response'
security: security:
- BearerAuth: [] - BearerAuth: []
summary: 个人信息 summary: 地址列表
tags: tags:
- 用户 - 地址[Personal]
/ab/personal:
post:
consumes:
- application/json
description: 个人地址
parameters:
- description: string valid
in: body
name: string
schema:
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: 个人地址
tags:
- 地址[Personal]
/ab/settings:
post:
consumes:
- application/json
description: 设置
parameters:
- description: string valid
in: body
name: string
schema:
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: 设置
tags:
- 地址[Personal]
/ab/shared/profiles:
post:
consumes:
- application/json
description: 共享
parameters:
- description: string valid
in: body
name: string
schema:
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.Response'
security:
- BearerAuth: []
summary: 共享地址簿
tags:
- 地址[Personal]
/ab/tag/{guid}:
delete:
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/tag/rename/{guid}:
put:
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/tag/update/{guid}:
put:
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/tags/{guid}:
post:
consumes:
- application/json
description: 标签
parameters:
- description: id
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/model.TagList'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.ErrorResponse'
security:
- BearerAuth: []
summary: 标签
tags:
- 地址[Personal]
/api: /api:
get: get:
consumes: consumes:
@@ -366,25 +630,6 @@ paths:
summary: OauthCallback summary: OauthCallback
tags: tags:
- Oauth - Oauth
/oauth/login:
get:
consumes:
- application/json
description: WebOauthLogin
produces:
- application/json
responses:
"200":
description: OK
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
summary: WebOauthLogin
tags:
- Oauth
/oidc/auth: /oidc/auth:
post: post:
consumes: consumes:

View File

@@ -1,14 +1,17 @@
package api package api
import ( import (
"Gwen/global"
requstform "Gwen/http/request/api" requstform "Gwen/http/request/api"
"Gwen/http/response" "Gwen/http/response"
"Gwen/http/response/api" "Gwen/http/response/api"
"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"
) )
type Ab struct { type Ab struct {
@@ -118,7 +121,7 @@ func (a *Ab) Tags(c *gin.Context) {
} }
// TagAdd // TagAdd
// @Tags 地址 // @Tags 地址[Personal]
// @Summary 标签添加 // @Summary 标签添加
// @Description 标签 // @Description 标签
// @Accept json // @Accept json
@@ -133,14 +136,359 @@ func (a *Ab) TagAdd(c *gin.Context) {
if err != nil { if err != nil {
response.Error(c, "参数错误") response.Error(c, "参数错误")
return return
} }
//u := service.AllService.UserService.CurUser(c) u := service.AllService.UserService.CurUser(c)
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name)
//err = service.AllService.TagService.UpdateTags(t.Name, t.Color, user.Id) if tag != nil && tag.Id != 0 {
//if err != nil { response.Error(c, "已存在")
// response.Error(c, "操作失败") return
// return }
//} t.UserId = u.Id
c.JSON(http.StatusOK, "") err = service.AllService.TagService.Create(t)
if err != nil {
response.Error(c, "操作失败")
return
}
c.String(http.StatusOK, "")
}
// TagRename
// @Tags 地址[Personal]
// @Summary 标签重命名
// @Description 标签
// @Accept json
// @Produce json
// @Success 200 {string} string
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/tag/rename/{guid} [put]
// @Security BearerAuth
func (a *Ab) TagRename(c *gin.Context) {
t := &requstform.TagRenameForm{}
err := c.ShouldBindJSON(t)
if err != nil {
response.Error(c, "参数错误")
return
}
u := service.AllService.UserService.CurUser(c)
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Old)
if tag == nil || tag.Id == 0 {
response.Error(c, "参数错误")
return
}
ntag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.New)
if ntag != nil && ntag.Id != 0 {
response.Error(c, "已存在")
return
}
tag.Name = t.New
err = service.AllService.TagService.Update(tag)
if err != nil {
response.Error(c, "操作失败")
return
}
c.String(http.StatusOK, "")
}
// TagUpdate
// @Tags 地址[Personal]
// @Summary 标签修改颜色
// @Description 标签
// @Accept json
// @Produce json
// @Success 200 {string} string
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/tag/update/{guid} [put]
// @Security BearerAuth
func (a *Ab) TagUpdate(c *gin.Context) {
t := &requstform.TagColorForm{}
err := c.ShouldBindJSON(t)
if err != nil {
response.Error(c, "参数错误")
return
}
u := service.AllService.UserService.CurUser(c)
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name)
if tag == nil || tag.Id == 0 {
response.Error(c, "参数错误")
return
}
tag.Color = t.Color
err = service.AllService.TagService.Update(tag)
if err != nil {
response.Error(c, "操作失败")
return
}
c.String(http.StatusOK, "")
}
// TagDel
// @Tags 地址[Personal]
// @Summary 标签删除
// @Description 标签
// @Accept json
// @Produce json
// @Success 200 {string} string
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/tag/{guid} [delete]
// @Security BearerAuth
func (a *Ab) TagDel(c *gin.Context) {
t := &[]string{}
err := c.ShouldBind(t)
if err != nil {
response.Error(c, "参数错误")
return
}
//fmt.Println(t)
u := service.AllService.UserService.CurUser(c)
for _, name := range *t {
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, name)
if tag == nil || tag.Id == 0 {
response.Error(c, "参数错误")
return
}
err = service.AllService.TagService.Delete(tag)
if err != nil {
response.Error(c, "操作失败")
return
}
}
c.String(http.StatusOK, "")
}
// Personal
// @Tags 地址[Personal]
// @Summary 个人地址
// @Description 个人地址
// @Accept json
// @Produce json
// @Param string body string false "string valid"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /ab/personal [post]
// @Security BearerAuth
func (a *Ab) Personal(c *gin.Context) {
user := service.AllService.UserService.CurUser(c)
/**
guid = json['guid'] ?? '',
name = json['name'] ?? '',
owner = json['owner'] ?? '',
note = json['note'] ?? '',
rule = json['rule'] ?? 0;
*/
if global.Config.Rustdesk.Personal == 1 {
guid := strconv.Itoa(int(user.GroupId)) + "-" + strconv.Itoa(int(user.Id))
//如果返回了guid后面的请求会有变化
c.JSON(http.StatusOK, gin.H{
"guid": guid,
"name": user.Username,
"rule": 0,
})
} else {
c.JSON(http.StatusOK, nil)
}
}
// Settings
// @Tags 地址[Personal]
// @Summary 设置
// @Description 设置
// @Accept json
// @Produce json
// @Param string body string false "string valid"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /ab/settings [post]
// @Security BearerAuth
func (a *Ab) Settings(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"max_peer_one_ab": 0, //最大peer数0表示不限制
})
}
// SharedProfiles
// @Tags 地址[Personal]
// @Summary 共享地址簿
// @Description 共享
// @Accept json
// @Produce json
// @Param string body string false "string valid"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /ab/shared/profiles [post]
// @Security BearerAuth
func (a *Ab) SharedProfiles(c *gin.Context) {
//AbProfile.fromJson(Map<String, dynamic> json)
//: guid = json['guid'] ?? '',
// name = json['name'] ?? '',
// owner = json['owner'] ?? '',
// note = json['note'] ?? '',
// rule = json['rule'] ?? 0;
//暂时没必要返回数据,可能是为了共享地址簿
/*item := map[string]interface{}{
"guid": "1",
"name": "admin",
"owner": "admin",
"note": "admin11",
"rule": 0,
}
item2 := map[string]interface{}{
"guid": "2",
"name": "admin2",
"owner": "admin2",
"note": "admin22",
"rule": 0,
}
c.JSON(http.StatusOK, gin.H{
"total": 2,
"data": []interface{}{item, item2},
})*/
c.JSON(http.StatusOK, gin.H{
"total": 0,
"data": nil,
})
}
// Peers
// @Tags 地址[Personal]
// @Summary 地址列表
// @Description 地址
// @Accept json
// @Produce json
// @Param string body string false "string valid"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /ab/peers [post]
// @Security BearerAuth
func (a *Ab) Peers(c *gin.Context) {
user := service.AllService.UserService.CurUser(c)
al := service.AllService.AddressBookService.ListByUserId(user.Id, 1, 1000)
c.JSON(http.StatusOK, gin.H{
"total": al.Total,
"data": al.AddressBooks,
"licensed_devices": 99999,
})
}
// PTags
// @Tags 地址[Personal]
// @Summary 标签
// @Description 标签
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Success 200 {object} model.TagList
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/tags/{guid} [post]
// @Security BearerAuth
func (a *Ab) PTags(c *gin.Context) {
user := service.AllService.UserService.CurUser(c)
tags := service.AllService.TagService.ListByUserId(user.Id)
c.JSON(http.StatusOK, tags.Tags)
}
// PeerAdd
// @Tags 地址[Personal]
// @Summary 添加地址
// @Description 添加地址
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Success 200 {string} string
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/peer/add/{guid} [post]
// @Security BearerAuth
func (a *Ab) PeerAdd(c *gin.Context) {
// forceAlwaysRelay永远是字符串"false",真是坑
//f := &gin.H{}
f := &requstform.PersonalAddressBookForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Error(c, "参数错误"+err.Error())
return
}
fmt.Println(f)
u := service.AllService.UserService.CurUser(c)
f.UserId = u.Id
ab := f.ToAddressBook()
err = service.AllService.AddressBookService.AddAddressBook(ab)
if err != nil {
response.Error(c, "操作失败")
return
}
c.String(http.StatusOK, "")
}
// PeerDel
// @Tags 地址[Personal]
// @Summary 删除地址
// @Description 删除地址
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Success 200 {string} string
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/peer/add/{guid} [delete]
// @Security BearerAuth
func (a *Ab) PeerDel(c *gin.Context) {
f := &[]string{}
err := c.ShouldBind(f)
if err != nil {
response.Error(c, "参数错误")
return
}
u := service.AllService.UserService.CurUser(c)
for _, id := range *f {
ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, id)
if ab == nil || ab.RowId == 0 {
response.Error(c, "参数错误")
return
}
err = service.AllService.AddressBookService.Delete(ab)
if err != nil {
response.Error(c, "操作失败")
return
}
}
c.String(http.StatusOK, "")
}
// PeerUpdate
// @Tags 地址[Personal]
// @Summary 更新地址
// @Description 更新地址
// @Accept json
// @Produce json
// @Param id path string true "id"
// @Success 200 {string} string
// @Failure 500 {object} response.ErrorResponse
// @Router /ab/peer/update/{guid} [put]
// @Security BearerAuth
func (a *Ab) PeerUpdate(c *gin.Context) {
//f := &gin.H{}
f := &requstform.PersonalAddressBookForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Error(c, "参数错误")
return
}
fmt.Println(f)
//return
u := service.AllService.UserService.CurUser(c)
ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, f.Id)
if ab == nil || ab.RowId == 0 {
response.Error(c, "参数错误")
return
}
nab := f.ToAddressBook()
nab.RowId = ab.RowId
err = service.AllService.AddressBookService.Update(nab)
if err != nil {
response.Error(c, "操作失败")
return
}
c.String(http.StatusOK, "")
} }

View File

@@ -264,16 +264,3 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
c.String(http.StatusInternalServerError, "授权配置错误,请联系管理员") c.String(http.StatusInternalServerError, "授权配置错误,请联系管理员")
} }
// WebOauthLogin
// @Tags Oauth
// @Summary WebOauthLogin
// @Description WebOauthLogin
// @Accept json
// @Produce json
// @Success 200 {string} string
// @Failure 500 {string} string
// @Router /oauth/login [get]
func (o *Oauth) WebOauthLogin(c *gin.Context) {
}

View File

@@ -3,7 +3,6 @@ package api
import ( import (
apiResp "Gwen/http/response/api" apiResp "Gwen/http/response/api"
"Gwen/service" "Gwen/service"
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
) )
@@ -42,33 +41,3 @@ func (u *User) Info(c *gin.Context) {
up := (&apiResp.UserPayload{}).FromUser(user) up := (&apiResp.UserPayload{}).FromUser(user)
c.JSON(http.StatusOK, up) c.JSON(http.StatusOK, up)
} }
// Personal
// @Tags 用户
// @Summary 个人信息
// @Description 个人信息
// @Accept json
// @Produce json
// @Param string body string false "string valid"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /ab/personal [post]
// @Security BearerAuth
func (u *User) Personal(c *gin.Context) {
//打印全部body
fmt.Println(c.Request.Body)
/**
guid = json['guid'] ?? '',
name = json['name'] ?? '',
owner = json['owner'] ?? '',
note = json['note'] ?? '',
rule = json['rule'] ?? 0;
*/
//如果返回了guid后面的请求会有变化
c.JSON(http.StatusOK, gin.H{
//"guid": "123456",
//"name": "admindddd",
//"rule": 1,
})
}

View File

@@ -8,6 +8,10 @@ import (
type Index struct { type Index struct {
} }
func (i *Index) Index(c *gin.Context) {
c.Redirect(302, "/_admin/")
}
func (i *Index) ConfigJs(c *gin.Context) { func (i *Index) ConfigJs(c *gin.Context) {
apiServer := global.Config.Rustdesk.ApiServer apiServer := global.Config.Rustdesk.ApiServer

View File

@@ -16,7 +16,7 @@ type AddressBookForm struct {
Tags []string `json:"tags"` Tags []string `json:"tags"`
Hash string `json:"hash"` Hash string `json:"hash"`
UserId uint `json:"user_id"` UserId uint `json:"user_id"`
ForceAlwaysRelay bool `json:"force_always_relay"` ForceAlwaysRelay bool `json:"forceAlwaysRelay"`
RdpPort string `json:"rdp_port"` RdpPort string `json:"rdp_port"`
RdpUsername string `json:"rdp_username"` RdpUsername string `json:"rdp_username"`
Online bool `json:"online"` Online bool `json:"online"`

View File

@@ -35,3 +35,39 @@ func (pf *PeerForm) ToPeer() *model.Peer {
Version: pf.Version, Version: pf.Version,
} }
} }
// PersonalAddressBookForm 个人地址簿表单
type PersonalAddressBookForm struct {
model.AddressBook
ForceAlwaysRelay string `json:"forceAlwaysRelay"`
}
func (pabf *PersonalAddressBookForm) ToAddressBook() *model.AddressBook {
return &model.AddressBook{
RowId: pabf.RowId,
Id: pabf.Id,
Username: pabf.Username,
Password: pabf.Password,
Hostname: pabf.Hostname,
Alias: pabf.Alias,
Platform: pabf.Platform,
Tags: pabf.Tags,
Hash: pabf.Hash,
UserId: pabf.UserId,
ForceAlwaysRelay: pabf.ForceAlwaysRelay == "true",
RdpPort: pabf.RdpPort,
RdpUsername: pabf.RdpUsername,
Online: pabf.Online,
LoginName: pabf.LoginName,
SameServer: pabf.SameServer,
}
}
type TagRenameForm struct {
Old string `json:"old"`
New string `json:"new"`
}
type TagColorForm struct {
Name string `json:"name"`
Color uint `json:"color"`
}

View File

@@ -59,16 +59,13 @@ func (gpp *GroupPeerPayload) FromAddressBook(a *model.AddressBook, username stri
gpp.UserName = username gpp.UserName = username
} }
//func (gpp *GroupPeerPayload) FromPeer(p *model.Peer) { func (gpp *GroupPeerPayload) FromPeer(p *model.Peer) {
// gpp.Id = p.Id gpp.Id = p.Id
// gpp.Info = &PeerPayloadInfo{ gpp.Info = &PeerPayloadInfo{
// DeviceName: p.Hostname, DeviceName: p.Hostname,
// Os: p.Os, Os: p.Os,
// Username: p.Username, Username: p.Username,
// } }
// gpp.Note = "" gpp.Note = ""
// if p.User.Id != 0 { gpp.UserName = p.User.Username
// //gpp.User = p.User.Username }
// gpp.UserName = p.User.Username
// }
//}

View File

@@ -74,7 +74,38 @@ func ApiInit(g *gin.Engine) {
//更新地址 //更新地址
frg.POST("/ab", ab.UpAb) frg.POST("/ab", ab.UpAb)
} }
PersonalRoutes(frg)
//访问静态文件 //访问静态文件
g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/public/upload")) g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/public/upload"))
} }
func PersonalRoutes(frg *gin.RouterGroup) {
{
ab := &api.Ab{}
frg.POST("/ab/personal", ab.Personal)
//[method:POST] [uri:/api/ab/settings] Request
frg.POST("/ab/settings", ab.Settings)
// [method:POST] [uri:/api/ab/shared/profiles?current=1&pageSize=100]
frg.POST("/ab/shared/profiles", ab.SharedProfiles)
//[method:POST] [uri:/api/ab/peers?current=1&pageSize=100&ab=1]
frg.POST("/ab/peers", ab.Peers)
// [method:POST] [uri:/api/ab/tags/1]
frg.POST("/ab/tags/:guid", ab.PTags)
//[method:POST] api/ab/peer/add/1
frg.POST("/ab/peer/add/:guid", ab.PeerAdd)
//[method:DELETE] [uri:/api/ab/peer/1]
frg.DELETE("/ab/peer/:guid", ab.PeerDel)
//[method:PUT] [uri:/api/ab/peer/update/1]
frg.PUT("/ab/peer/update/:guid", ab.PeerUpdate)
//[method:POST] [uri:/api/ab/tag/add/1]
frg.POST("/ab/tag/add/:guid", ab.TagAdd)
//[method:PUT] [uri:/api/ab/tag/rename/1]
frg.PUT("/ab/tag/rename/:guid", ab.TagRename)
//[method:PUT] [uri:/api/ab/tag/update/1]
frg.PUT("/ab/tag/update/:guid", ab.TagUpdate)
//[method:DELETE] [uri:/api/ab/tag/1]
frg.DELETE("/ab/tag/:guid", ab.TagDel)
}
}

View File

@@ -9,6 +9,7 @@ import (
func WebInit(g *gin.Engine) { func WebInit(g *gin.Engine) {
i := &web.Index{} i := &web.Index{}
g.GET("/", i.Index)
g.GET("/webclient-config/index.js", i.ConfigJs) g.GET("/webclient-config/index.js", i.ConfigJs)
g.StaticFS("/webclient", http.Dir(global.Config.Gin.ResourcesPath+"/web")) g.StaticFS("/webclient", http.Dir(global.Config.Gin.ResourcesPath+"/web"))
g.StaticFS("/_admin", http.Dir(global.Config.Gin.ResourcesPath+"/admin")) g.StaticFS("/_admin", http.Dir(global.Config.Gin.ResourcesPath+"/admin"))

View File

@@ -9,11 +9,17 @@ import (
type AddressBookService struct { type AddressBookService struct {
} }
func (s *AddressBookService) Info(id uint) *model.AddressBook { func (s *AddressBookService) Info(id string) *model.AddressBook {
p := &model.AddressBook{} p := &model.AddressBook{}
global.DB.Where("id = ?", id).First(p) global.DB.Where("id = ?", id).First(p)
return p return p
} }
func (s *AddressBookService) InfoByUserIdAndId(userid uint, id string) *model.AddressBook {
p := &model.AddressBook{}
global.DB.Where("user_id = ? and id = ?", userid, id).First(p)
return p
}
func (s *AddressBookService) InfoByRowId(id uint) *model.AddressBook { func (s *AddressBookService) InfoByRowId(id uint) *model.AddressBook {
p := &model.AddressBook{} p := &model.AddressBook{}
global.DB.Where("row_id = ?", id).First(p) global.DB.Where("row_id = ?", id).First(p)

View File

@@ -14,6 +14,11 @@ func (s *TagService) Info(id uint) *model.Tag {
global.DB.Where("id = ?", id).First(p) global.DB.Where("id = ?", id).First(p)
return p return p
} }
func (s *TagService) InfoByUserIdAndName(userid uint, name string) *model.Tag {
p := &model.Tag{}
global.DB.Where("user_id = ? and name = ?", userid, name).First(p)
return p
}
func (s *TagService) ListByUserId(userId uint) (res *model.TagList) { func (s *TagService) ListByUserId(userId uint) (res *model.TagList) {
res = s.List(1, 1000, func(tx *gorm.DB) { res = s.List(1, 1000, func(tx *gorm.DB) {