Compare commits

...

9 Commits

Author SHA1 Message Date
lejianwen
fdd841e82a add batch add ab from peer and up my 2024-12-13 16:27:12 +08:00
lejianwen
2d6f0a116a add share record manage 2024-12-13 12:32:36 +08:00
lejianwen
bd13fe4ef4 up web client v2 2024-12-10 18:26:08 +08:00
lejianwen
6e1b208464 up README.md 2024-12-10 15:28:05 +08:00
lejianwen
76433a409e up README.md 2024-12-09 13:43:04 +08:00
lejianwen
9b4fa679c2 add batch add ab from peer
add batch update ab tags
2024-12-06 19:45:41 +08:00
lejianwen
c2ae95c4cc up api docs 2024-12-06 10:36:40 +08:00
lejianwen
b2b7f60fd5 add batch delete user token 2024-12-06 10:36:27 +08:00
lejianwen
a465888b31 up username length to 32 #70 2024-12-06 10:22:28 +08:00
28 changed files with 55858 additions and 54649 deletions

199
README.md
View File

@@ -263,189 +263,8 @@ proxy:
lejianwen/rustdesk-api
```
2. 使用`docker compose`
- 简单示例
```yaml
services:
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
```
2. 使用`docker compose`,参考[wiki](https://github.com/lejianwen/rustdesk-api/wiki)
- 根据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`
```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
```
- S6的镜像
- 如果使用***自定义KEY***,会需要修改启动脚本,覆盖镜像中的`/etc/s6-overlay/s6-rc.d/hbbr/run`和`/etc/s6-overlay/s6-rc.d/hbbr/run`
1. 创建`hbbr/run`自定义KEY才需要
```bash
#!/command/with-contenv sh
cd /data
PARAMS=
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
/usr/bin/hbbr $PARAMS
```
2. 创建`hbbs/run`自定义KEY才需要
```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`部分
```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
```
- 如果使用***系统生成的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直接运行
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
@@ -488,21 +307,7 @@ proxy:
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)

View File

@@ -267,189 +267,7 @@ The prefix for variable names is `RUSTDESK_API`. If environment variables exist,
lejianwen/rustdesk-api
```
2. Using `docker-compose`
- Simple example:
```yaml
services:
rustdesk-api:
container_name: rustdesk-api
environment:
- RUSTDESK_API_LANG=en
- 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 # Mount the database for easy backup
networks:
- rustdesk-net
restart: unless-stopped
```
- 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
```
- S6 image
- - If using ***custom KEY***, you will need to modify the startup script to override the `/etc/s6-overlay/s6-rc.d/hbbr/run` and `/etc/s6-overlay/s6-rc.d/hbbr/run` in the image.
1. Create `hbbr/run`, only needed for custom KEY
```bash
#!/command/with-contenv sh
cd /data
PARAMS=
[ "${ENCRYPTED_ONLY}" = "1" ] && PARAMS="-k ${KEY}"
/usr/bin/hbbr $PARAMS
```
2. Create `hbbs/run`, only needed for custom KEY
```bash
#!/command/with-contenv sh
sleep 2
cd /data
PARAMS=
[ "${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:
rustdesk-net:
external: false
services:
rustdesk-server:
container_name: rustdesk-server
ports:
- 21115:21115
- 21116:21116
- 21116:21116/udp
- 21117:21117
- 21118:21118
- 21119:21119
image: rustdesk/rustdesk-server-s6:latest
environment:
- RELAY=192.168.1.66:21117
- ENCRYPTED_ONLY=1
volumes:
- ./data:/data
restart: unless-stopped
rustdesk-api:
container_name: rustdesk-api
ports:
- 21114:21114
image: lejianwen/rustdesk-api
environment:
- TZ=Asia/Shanghai
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
- RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114
- RUSTDESK_API_RUSTDESK_KEY=<key>
volumes:
- /data/rustdesk/api:/app/data
networks:
- rustdesk-net
restart: unless-stopped
```
2. Using `docker-compose`,look [wiki](https://github.com/lejianwen/rustdesk-api/wiki)
#### Running from Release
@@ -498,21 +316,7 @@ 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
change the password promptly.
#### 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)

View File

@@ -2019,6 +2019,144 @@ const docTemplateadmin = `{
}
}
},
"/admin/my/share_record/batchDelete": {
"post": {
"security": [
{
"token": []
}
],
"description": "批量删除我的分享记录",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"我的"
],
"summary": "批量删除我的分享记录",
"parameters": [
{
"description": "id",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.PeerShareRecordBatchDeleteForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/my/share_record/delete": {
"post": {
"security": [
{
"token": []
}
],
"description": "分享记录删除",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"我的"
],
"summary": "分享记录删除",
"parameters": [
{
"description": "分享记录信息",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.ShareRecordForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/my/share_record/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"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/oauth/create": {
"post": {
"security": [
@@ -2727,6 +2865,150 @@ const docTemplateadmin = `{
}
}
},
"/admin/share_record/batchDelete": {
"post": {
"security": [
{
"token": []
}
],
"description": "批量分享记录",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"分享记录"
],
"summary": "批量分享记录",
"parameters": [
{
"description": "id",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.PeerShareRecordBatchDeleteForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/share_record/delete": {
"post": {
"security": [
{
"token": []
}
],
"description": "分享记录删除",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"分享记录"
],
"summary": "分享记录删除",
"parameters": [
{
"description": "分享记录信息",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.ShareRecordForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/share_record/list": {
"get": {
"security": [
{
"token": []
}
],
"description": "分享记录列表",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"分享记录"
],
"summary": "分享记录列表",
"parameters": [
{
"type": "integer",
"description": "用户ID",
"name": "user_id",
"in": "query"
},
{
"type": "integer",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "页大小",
"name": "page_size",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/tag/create": {
"post": {
"security": [
@@ -3562,6 +3844,51 @@ const docTemplateadmin = `{
}
}
},
"/admin/user_token/batchDelete": {
"post": {
"security": [
{
"token": []
}
],
"description": "登录凭证批量删除",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"登录凭证"
],
"summary": "登录凭证批量删除",
"parameters": [
{
"description": "登录凭证信息",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.UserTokenBatchDeleteForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/user_token/delete": {
"post": {
"security": [
@@ -3798,12 +4125,12 @@ const docTemplateadmin = `{
"properties": {
"new_password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
},
"old_password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
}
}
@@ -3949,6 +4276,20 @@ const docTemplateadmin = `{
}
}
},
"admin.PeerShareRecordBatchDeleteForm": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
}
}
},
"admin.ShareByWebClientForm": {
"type": "object",
"required": [
@@ -3976,6 +4317,17 @@ const docTemplateadmin = `{
}
}
},
"admin.ShareRecordForm": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"user_id": {
"type": "integer"
}
}
},
"admin.TagForm": {
"type": "object",
"required": [
@@ -4038,7 +4390,7 @@ const docTemplateadmin = `{
},
"username": {
"type": "string",
"maxLength": 10,
"maxLength": 32,
"minLength": 2
}
}
@@ -4066,11 +4418,25 @@ const docTemplateadmin = `{
},
"password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
}
}
},
"admin.UserTokenBatchDeleteForm": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
}
}
},
"model.AddressBook": {
"type": "object",
"properties": {

View File

@@ -2012,6 +2012,144 @@
}
}
},
"/admin/my/share_record/batchDelete": {
"post": {
"security": [
{
"token": []
}
],
"description": "批量删除我的分享记录",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"我的"
],
"summary": "批量删除我的分享记录",
"parameters": [
{
"description": "id",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.PeerShareRecordBatchDeleteForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/my/share_record/delete": {
"post": {
"security": [
{
"token": []
}
],
"description": "分享记录删除",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"我的"
],
"summary": "分享记录删除",
"parameters": [
{
"description": "分享记录信息",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.ShareRecordForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/my/share_record/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"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/oauth/create": {
"post": {
"security": [
@@ -2720,6 +2858,150 @@
}
}
},
"/admin/share_record/batchDelete": {
"post": {
"security": [
{
"token": []
}
],
"description": "批量分享记录",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"分享记录"
],
"summary": "批量分享记录",
"parameters": [
{
"description": "id",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.PeerShareRecordBatchDeleteForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/share_record/delete": {
"post": {
"security": [
{
"token": []
}
],
"description": "分享记录删除",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"分享记录"
],
"summary": "分享记录删除",
"parameters": [
{
"description": "分享记录信息",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.ShareRecordForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/share_record/list": {
"get": {
"security": [
{
"token": []
}
],
"description": "分享记录列表",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"分享记录"
],
"summary": "分享记录列表",
"parameters": [
{
"type": "integer",
"description": "用户ID",
"name": "user_id",
"in": "query"
},
{
"type": "integer",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "页大小",
"name": "page_size",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/tag/create": {
"post": {
"security": [
@@ -3555,6 +3837,51 @@
}
}
},
"/admin/user_token/batchDelete": {
"post": {
"security": [
{
"token": []
}
],
"description": "登录凭证批量删除",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"登录凭证"
],
"summary": "登录凭证批量删除",
"parameters": [
{
"description": "登录凭证信息",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/admin.UserTokenBatchDeleteForm"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/admin/user_token/delete": {
"post": {
"security": [
@@ -3791,12 +4118,12 @@
"properties": {
"new_password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
},
"old_password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
}
}
@@ -3942,6 +4269,20 @@
}
}
},
"admin.PeerShareRecordBatchDeleteForm": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
}
}
},
"admin.ShareByWebClientForm": {
"type": "object",
"required": [
@@ -3969,6 +4310,17 @@
}
}
},
"admin.ShareRecordForm": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"user_id": {
"type": "integer"
}
}
},
"admin.TagForm": {
"type": "object",
"required": [
@@ -4031,7 +4383,7 @@
},
"username": {
"type": "string",
"maxLength": 10,
"maxLength": 32,
"minLength": 2
}
}
@@ -4059,11 +4411,25 @@
},
"password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
}
}
},
"admin.UserTokenBatchDeleteForm": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "integer"
}
}
}
},
"model.AddressBook": {
"type": "object",
"properties": {

View File

@@ -78,11 +78,11 @@ definitions:
admin.ChangeCurPasswordForm:
properties:
new_password:
maxLength: 20
maxLength: 32
minLength: 4
type: string
old_password:
maxLength: 20
maxLength: 32
minLength: 4
type: string
required:
@@ -182,6 +182,15 @@ definitions:
version:
type: string
type: object
admin.PeerShareRecordBatchDeleteForm:
properties:
ids:
items:
type: integer
type: array
required:
- ids
type: object
admin.ShareByWebClientForm:
properties:
expire:
@@ -201,6 +210,13 @@ definitions:
- password
- password_type
type: object
admin.ShareRecordForm:
properties:
id:
type: integer
user_id:
type: integer
type: object
admin.TagForm:
properties:
collection_id:
@@ -238,7 +254,7 @@ definitions:
- $ref: '#/definitions/model.StatusCode'
minimum: 0
username:
maxLength: 10
maxLength: 32
minLength: 2
type: string
required:
@@ -258,13 +274,22 @@ definitions:
id:
type: integer
password:
maxLength: 20
maxLength: 32
minLength: 4
type: string
required:
- id
- password
type: object
admin.UserTokenBatchDeleteForm:
properties:
ids:
items:
type: integer
type: array
required:
- ids
type: object
model.AddressBook:
properties:
alias:
@@ -1950,6 +1975,92 @@ paths:
summary: 登出
tags:
- 登录
/admin/my/share_record/batchDelete:
post:
consumes:
- application/json
description: 批量删除我的分享记录
parameters:
- description: id
in: body
name: body
required: true
schema:
$ref: '#/definitions/admin.PeerShareRecordBatchDeleteForm'
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/my/share_record/delete:
post:
consumes:
- application/json
description: 分享记录删除
parameters:
- description: 分享记录信息
in: body
name: body
required: true
schema:
$ref: '#/definitions/admin.ShareRecordForm'
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/my/share_record/list:
get:
consumes:
- application/json
description: 分享记录列表
parameters:
- description: 页码
in: query
name: page
type: integer
- description: 页大小
in: query
name: page_size
type: integer
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/oauth/create:
post:
consumes:
@@ -2372,6 +2483,96 @@ paths:
summary: RUSTDESK服务配置
tags:
- ADMIN
/admin/share_record/batchDelete:
post:
consumes:
- application/json
description: 批量分享记录
parameters:
- description: id
in: body
name: body
required: true
schema:
$ref: '#/definitions/admin.PeerShareRecordBatchDeleteForm'
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/share_record/delete:
post:
consumes:
- application/json
description: 分享记录删除
parameters:
- description: 分享记录信息
in: body
name: body
required: true
schema:
$ref: '#/definitions/admin.ShareRecordForm'
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/share_record/list:
get:
consumes:
- application/json
description: 分享记录列表
parameters:
- description: 用户ID
in: query
name: user_id
type: integer
- description: 页码
in: query
name: page
type: integer
- description: 页大小
in: query
name: page_size
type: integer
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/tag/create:
post:
consumes:
@@ -2867,6 +3068,34 @@ paths:
summary: 修改密码
tags:
- 用户
/admin/user_token/batchDelete:
post:
consumes:
- application/json
description: 登录凭证批量删除
parameters:
- description: 登录凭证信息
in: body
name: body
required: true
schema:
$ref: '#/definitions/admin.UserTokenBatchDeleteForm'
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/user_token/delete:
post:
consumes:

View File

@@ -1042,6 +1042,40 @@ const docTemplateapi = `{
}
},
"/server-config": {
"get": {
"security": [
{
"token": []
}
],
"description": "服务配置,给webclient提供api-server",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"WEBCLIENT"
],
"summary": "服务配置",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/server-config-v2": {
"get": {
"security": [
{
@@ -1356,7 +1390,7 @@ const docTemplateapi = `{
},
"password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
},
"type": {
@@ -1364,7 +1398,7 @@ const docTemplateapi = `{
},
"username": {
"type": "string",
"maxLength": 10,
"maxLength": 32,
"minLength": 2
},
"uuid": {

View File

@@ -1035,6 +1035,40 @@
}
},
"/server-config": {
"get": {
"security": [
{
"token": []
}
],
"description": "服务配置,给webclient提供api-server",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"WEBCLIENT"
],
"summary": "服务配置",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.Response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.Response"
}
}
}
}
},
"/server-config-v2": {
"get": {
"security": [
{
@@ -1349,7 +1383,7 @@
},
"password": {
"type": "string",
"maxLength": 20,
"maxLength": 32,
"minLength": 4
},
"type": {
@@ -1357,7 +1391,7 @@
},
"username": {
"type": "string",
"maxLength": 10,
"maxLength": 32,
"minLength": 2
},
"uuid": {

View File

@@ -62,13 +62,13 @@ definitions:
id:
type: string
password:
maxLength: 20
maxLength: 32
minLength: 4
type: string
type:
type: string
username:
maxLength: 10
maxLength: 32
minLength: 2
type: string
uuid:
@@ -850,6 +850,27 @@ paths:
tags:
- 群组
/server-config:
get:
consumes:
- application/json
description: 服务配置,给webclient提供api-server
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:
- WEBCLIENT
/server-config-v2:
get:
consumes:
- application/json

View File

@@ -6,6 +6,7 @@ import (
"Gwen/http/response"
"Gwen/model"
"Gwen/service"
"encoding/json"
_ "encoding/json"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@@ -327,3 +328,71 @@ func (ct *AddressBook) ShareByWebClient(c *gin.Context) {
"share_token": m.ShareToken,
})
}
func (ct *AddressBook) BatchCreateFromPeers(c *gin.Context) {
f := &admin.BatchCreateFromPeersForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if f.UserId == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
if f.CollectionId != 0 {
collection := service.AllService.AddressBookService.CollectionInfoById(f.CollectionId)
if collection.Id == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
}
pl := int64(len(f.PeerIds))
peers := service.AllService.PeerService.List(1, uint(pl), func(tx *gorm.DB) {
tx.Where("row_id in ?", f.PeerIds)
})
if peers.Total == 0 || pl != peers.Total {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
tags, _ := json.Marshal(f.Tags)
for _, peer := range peers.Peers {
ab := service.AllService.AddressBookService.FromPeer(peer)
ab.Tags = tags
ab.CollectionId = f.CollectionId
ab.UserId = f.UserId
ex := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(f.UserId, ab.Id, ab.CollectionId)
if ex.RowId != 0 {
continue
}
service.AllService.AddressBookService.Create(ab)
}
response.Success(c, nil)
}
func (ct *AddressBook) BatchUpdateTags(c *gin.Context) {
f := &admin.BatchUpdateTagsForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
abs := service.AllService.AddressBookService.List(1, 999, func(tx *gorm.DB) {
tx.Where("row_id in ?", f.RowIds)
tx.Where("user_id = ?", u.Id)
})
if abs.Total == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
err := service.AllService.AddressBookService.BatchUpdateTags(abs.AddressBooks, f.Tags)
if err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
}

View File

@@ -0,0 +1,59 @@
package my
import (
"Gwen/http/request/admin"
"Gwen/http/response"
"Gwen/service"
"encoding/json"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type AddressBook struct{}
func (ct *AddressBook) BatchCreateFromPeers(c *gin.Context) {
f := &admin.BatchCreateFromPeersForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
if f.CollectionId != 0 {
collection := service.AllService.AddressBookService.CollectionInfoById(f.CollectionId)
if collection.Id == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
if collection.UserId != u.Id {
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
}
if len(f.PeerIds) == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
pl := int64(len(f.PeerIds))
peers := service.AllService.PeerService.List(1, uint(pl), func(tx *gorm.DB) {
tx.Where("row_id in ?", f.PeerIds)
tx.Where("user_id = ?", u.Id)
})
if peers.Total == 0 || pl != peers.Total {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
tags, _ := json.Marshal(f.Tags)
for _, peer := range peers.Peers {
ab := service.AllService.AddressBookService.FromPeer(peer)
ab.Tags = tags
ab.CollectionId = f.CollectionId
ex := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(u.Id, ab.Id, ab.CollectionId)
if ex.RowId != 0 {
continue
}
service.AllService.AddressBookService.Create(ab)
}
response.Success(c, nil)
}

View File

@@ -0,0 +1,119 @@
package my
import (
"Gwen/global"
"Gwen/http/request/admin"
"Gwen/http/response"
"Gwen/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ShareRecord struct {
}
// List 分享记录列表
// @Tags 我的
// @Summary 分享记录列表
// @Description 分享记录列表
// @Accept json
// @Produce json
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/share_record/list [get]
// @Security token
func (sr *ShareRecord) List(c *gin.Context) {
query := &admin.PageQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
res := service.AllService.ShareRecordService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
tx.Where("user_id = ?", u.Id)
})
response.Success(c, res)
}
// Delete 分享记录删除
// @Tags 我的
// @Summary 分享记录删除
// @Description 分享记录删除
// @Accept json
// @Produce json
// @Param body body admin.ShareRecordForm true "分享记录信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/share_record/delete [post]
// @Security token
func (sr *ShareRecord) Delete(c *gin.Context) {
f := &admin.ShareRecordForm{}
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
}
u := service.AllService.UserService.CurUser(c)
i := service.AllService.ShareRecordService.InfoById(f.Id)
if i.UserId != u.Id {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
if i.Id == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
err := service.AllService.ShareRecordService.Delete(i)
if err == nil {
response.Success(c, nil)
return
}
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
}
// BatchDelete 批量删除我的分享记录
// @Tags 我的
// @Summary 批量删除我的分享记录
// @Description 批量删除我的分享记录
// @Accept json
// @Produce json
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/my/share_record/batchDelete [post]
// @Security token
func (sr *ShareRecord) BatchDelete(c *gin.Context) {
f := &admin.PeerShareRecordBatchDeleteForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if len(f.Ids) == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
u := service.AllService.UserService.CurUser(c)
var l int64
l = int64(len(f.Ids))
res := service.AllService.ShareRecordService.List(1, uint(l), func(tx *gorm.DB) {
tx.Where("user_id = ?", u.Id)
tx.Where("id in ?", f.Ids)
})
if res.Total != l {
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
err := service.AllService.ShareRecordService.BatchDelete(f.Ids)
if err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
}

View File

@@ -0,0 +1,105 @@
package admin
import (
"Gwen/global"
"Gwen/http/request/admin"
"Gwen/http/response"
"Gwen/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ShareRecord struct {
}
// List 列表
// @Tags 分享记录
// @Summary 分享记录列表
// @Description 分享记录列表
// @Accept json
// @Produce json
// @Param user_id query int false "用户ID"
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/share_record/list [get]
// @Security token
func (sr *ShareRecord) List(c *gin.Context) {
query := &admin.ShareRecordQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
res := service.AllService.ShareRecordService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
if query.UserId > 0 {
tx.Where("user_id = ?", query.UserId)
}
})
response.Success(c, res)
}
// Delete 删除
// @Tags 分享记录
// @Summary 分享记录删除
// @Description 分享记录删除
// @Accept json
// @Produce json
// @Param body body admin.ShareRecordForm true "分享记录信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/share_record/delete [post]
// @Security token
func (sr *ShareRecord) Delete(c *gin.Context) {
f := &admin.ShareRecordForm{}
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
}
i := service.AllService.ShareRecordService.InfoById(f.Id)
if i.Id > 0 {
err := service.AllService.ShareRecordService.Delete(i)
if err == nil {
response.Success(c, nil)
return
}
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchDelete 批量删除
// @Tags 分享记录
// @Summary 批量分享记录
// @Description 批量分享记录
// @Accept json
// @Produce json
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/share_record/batchDelete [post]
// @Security token
func (sr *ShareRecord) BatchDelete(c *gin.Context) {
f := &admin.PeerShareRecordBatchDeleteForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if len(f.Ids) == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
err := service.AllService.ShareRecordService.BatchDelete(f.Ids)
if err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
}

View File

@@ -81,3 +81,33 @@ func (ct *UserToken) Delete(c *gin.Context) {
}
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// BatchDelete 批量删除
// @Tags 登录凭证
// @Summary 登录凭证批量删除
// @Description 登录凭证批量删除
// @Accept json
// @Produce json
// @Param body body admin.UserTokenBatchDeleteForm true "登录凭证信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/user_token/batchDelete [post]
// @Security token
func (ct *UserToken) BatchDelete(c *gin.Context) {
f := &admin.UserTokenBatchDeleteForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
ids := f.Ids
if len(ids) == 0 {
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
err := service.AllService.UserService.BatchDeleteUserToken(ids)
if err == nil {
response.Success(c, nil)
return
}
response.Fail(c, 101, err.Error())
}

View File

@@ -94,7 +94,7 @@ func (i *WebClient) SharedPeer(c *gin.Context) {
// @Produce json
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /server-config [get]
// @Router /server-config-v2 [get]
// @Security token
func (i *WebClient) ServerConfigV2(c *gin.Context) {
response.Success(

View File

@@ -122,3 +122,14 @@ type AddressBookCollectionRuleQuery struct {
IsMy int `form:"is_my"`
PageQuery
}
type BatchCreateFromPeersForm struct {
CollectionId uint `json:"collection_id"`
PeerIds []uint `json:"peer_ids"`
Tags []string `json:"tags"`
UserId uint `json:"user_id"`
}
type BatchUpdateTagsForm struct {
RowIds []uint `json:"row_ids"`
Tags []string `json:"tags"`
}

View File

@@ -0,0 +1,15 @@
package admin
type ShareRecordQuery struct {
UserId uint `json:"user_id" form:"user_id"`
PageQuery
}
type ShareRecordForm struct {
Id uint `json:"id" form:"id"`
UserId uint `json:"user_id" form:"user_id"`
}
type PeerShareRecordBatchDeleteForm struct {
Ids []uint `json:"ids" validate:"required"`
}

View File

@@ -6,7 +6,7 @@ import (
type UserForm struct {
Id uint `json:"id"`
Username string `json:"username" validate:"required,gte=2,lte=10"`
Username string `json:"username" validate:"required,gte=2,lte=32"`
Email string `json:"email"` //validate:"required,email" email不强制
//Password string `json:"password" validate:"required,gte=4,lte=20"`
Nickname string `json:"nickname"`
@@ -51,12 +51,12 @@ type UserQuery struct {
}
type UserPasswordForm struct {
Id uint `json:"id" validate:"required"`
Password string `json:"password" validate:"required,gte=4,lte=20"`
Password string `json:"password" validate:"required,gte=4,lte=32"`
}
type ChangeCurPasswordForm struct {
OldPassword string `json:"old_password" validate:"required,gte=4,lte=20"`
NewPassword string `json:"new_password" validate:"required,gte=4,lte=20"`
OldPassword string `json:"old_password" validate:"required,gte=4,lte=32"`
NewPassword string `json:"new_password" validate:"required,gte=4,lte=32"`
}
type GroupUsersQuery struct {
IsMy int `json:"is_my"`
@@ -64,8 +64,12 @@ type GroupUsersQuery struct {
}
type RegisterForm struct {
Username string `json:"username" validate:"required,gte=2,lte=10"`
Username string `json:"username" validate:"required,gte=2,lte=32"`
Email string `json:"email"` // validate:"required,email"
Password string `json:"password" validate:"required,gte=4,lte=20"`
ConfirmPassword string `json:"confirm_password" validate:"required,gte=4,lte=20"`
Password string `json:"password" validate:"required,gte=4,lte=32"`
ConfirmPassword string `json:"confirm_password" validate:"required,gte=4,lte=32"`
}
type UserTokenBatchDeleteForm struct {
Ids []uint `json:"ids" validate:"required"`
}

View File

@@ -34,8 +34,8 @@ type LoginForm struct {
Id string `json:"id" label:"id"`
Type string `json:"type" label:"type"`
Uuid string `json:"uuid" label:"uuid"`
Username string `json:"username" validate:"required,gte=2,lte=10" label:"用户名"`
Password string `json:"password,omitempty" validate:"gte=4,lte=20" label:"密码"`
Username string `json:"username" validate:"required,gte=2,lte=32" label:"用户名"`
Password string `json:"password,omitempty" validate:"gte=4,lte=32" label:"密码"`
}
type UserListQuery struct {

View File

@@ -4,8 +4,8 @@ import "Gwen/model"
type LoginPayload struct {
Username string `json:"username"`
Email string `json:"email"`
Avatar string `json:"avatar"`
Email string `json:"email"`
Avatar string `json:"avatar"`
Token string `json:"token"`
RouteNames []string `json:"route_names"`
Nickname string `json:"nickname"`
@@ -19,13 +19,13 @@ func (lp *LoginPayload) FromUser(user *model.User) {
}
var UserRouteNames = []string{
"MyTagList", "MyAddressBookList", "MyInfo", "MyAddressBookCollection", "MyPeer",
"MyTagList", "MyAddressBookList", "MyInfo", "MyAddressBookCollection", "MyPeer", "MyShareRecordList",
}
var AdminRouteNames = []string{"*"}
type UserOauthItem struct {
Op string `json:"op"`
Status int `json:"status"`
Op string `json:"op"`
Status int `json:"status"`
}
type GroupUsersPayload struct {

View File

@@ -3,6 +3,7 @@ package router
import (
_ "Gwen/docs/admin"
"Gwen/http/controller/admin"
"Gwen/http/controller/admin/my"
"Gwen/http/middleware"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
@@ -34,11 +35,14 @@ func Init(g *gin.Engine) {
ConfigBind(adg)
//deprecated by ConfigBind
rs := &admin.Rustdesk{}
adg.GET("/server-config", rs.ServerConfig)
adg.GET("/app-config", rs.AppConfig)
//rs := &admin.Rustdesk{}
//adg.GET("/server-config", rs.ServerConfig)
//adg.GET("/app-config", rs.AppConfig)
//deprecated end
ShareRecordBind(adg)
MyBind(adg)
//访问静态文件
//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
}
@@ -108,8 +112,12 @@ func AddressBookBind(rg *gin.RouterGroup) {
aR.POST("/delete", cont.Delete)
aR.POST("/shareByWebClient", cont.ShareByWebClient)
aR.POST("/batchUpdateTags", cont.BatchUpdateTags)
arp := aR.Use(middleware.AdminPrivilege())
arp.POST("/batchCreate", cont.BatchCreate)
arp.POST("/batchCreateFromPeers", cont.BatchCreateFromPeers)
}
}
func PeerBind(rg *gin.RouterGroup) {
@@ -195,6 +203,7 @@ func UserTokenBind(rg *gin.RouterGroup) {
cont := &admin.UserToken{}
aR.GET("/list", cont.List)
aR.POST("/delete", cont.Delete)
aR.POST("/batchDelete", cont.BatchDelete)
}
func ConfigBind(rg *gin.RouterGroup) {
aR := rg.Group("/config")
@@ -216,3 +225,26 @@ func FileBind(rg *gin.RouterGroup) {
aR.POST("/upload", cont.Upload)
}
}*/
func MyBind(rg *gin.RouterGroup) {
{
msr := &my.ShareRecord{}
rg.GET("/my/share_record/list", msr.List)
rg.POST("/my/share_record/delete", msr.Delete)
rg.POST("/my/share_record/batchDelete", msr.BatchDelete)
mab := &my.AddressBook{}
rg.POST("/my/address_book/batchCreateFromPeers", mab.BatchCreateFromPeers)
}
}
func ShareRecordBind(rg *gin.RouterGroup) {
aR := rg.Group("/share_record").Use(middleware.AdminPrivilege())
{
cont := &admin.ShareRecord{}
aR.GET("/list", cont.List)
aR.POST("/delete", cont.Delete)
aR.POST("/batchDelete", cont.BatchDelete)
}
}

View File

@@ -10,3 +10,9 @@ type ShareRecord struct {
Expire int64 `json:"expire" gorm:"default:0;not null;"`
TimeModel
}
// ShareRecordList 分享记录列表
type ShareRecordList struct {
ShareRecords []*ShareRecord `json:"list,omitempty"`
Pagination
}

File diff suppressed because it is too large Load Diff

View File

@@ -25617,9 +25617,9 @@ If you want to access a device on a public server, please input "<id>@public", t
Original: "\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B",
Shrink: "\u0417\u043C\u0435\u043D\u0448\u0438\u0442\u0438",
Stretch: "\u0420\u043E\u0437\u0442\u044F\u0433\u043D\u0443\u0442\u0438",
Scrollbar: "\u0421\u043C\u0443\u0433\u0430 \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438",
ScrollAuto: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u0430 \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430",
"Good image quality": "\u0425\u043E\u0440\u043E\u0448\u0430 \u044F\u043A\u0456\u0441\u0442\u044C \u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F",
Scrollbar: "\u0421\u043C\u0443\u0436\u043A\u0430 \u0433\u043E\u0440\u0442\u0430\u043D\u043D\u044F",
ScrollAuto: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u0435 \u0433\u043E\u0440\u0442\u0430\u043D\u043D\u044F",
"Good image quality": "\u0413\u0430\u0440\u043D\u0430 \u044F\u043A\u0456\u0441\u0442\u044C \u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F",
Balanced: "\u0417\u0431\u0430\u043B\u0430\u043D\u0441\u043E\u0432\u0430\u043D\u0430",
"Optimize reaction time": "\u041E\u043F\u0442\u0438\u043C\u0456\u0437\u0443\u0432\u0430\u0442\u0438 \u0447\u0430\u0441 \u0440\u0435\u0430\u043A\u0446\u0456\u0457",
Custom: "\u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0446\u044C\u043A\u0430",
@@ -25696,10 +25696,10 @@ If you want to access a device on a public server, please input "<id>@public", t
"Please enter the folder name": "\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0432\u0432\u0435\u0434\u0456\u0442\u044C \u043D\u0430\u0437\u0432\u0443 \u0434\u043B\u044F \u0442\u0435\u043A\u0438",
"Fix it": "\u0412\u0438\u043F\u0440\u0430\u0432\u0438\u0442\u0438",
Warning: "\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u0436\u0435\u043D\u043D\u044F",
"Login screen using Wayland is not supported": "\u0412\u0445\u0456\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u0443 \u0437 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F\u043C Wayland \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F",
"Login screen using Wayland is not supported": "\u0415\u043A\u0440\u0430\u043D \u0432\u0445\u043E\u0434\u0443, \u044F\u043A\u0438\u0439 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454 Wayland, \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F",
"Reboot required": "\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0435 \u043F\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
"Unsupported display server": "\u0413\u0440\u0430\u0444\u0456\u0447\u043D\u0438\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F",
"x11 expected": "\u041E\u0447\u0456\u043A\u0443\u0454\u0442\u044C\u0441\u044F X11",
"x11 expected": "\u041F\u043E\u0442\u0440\u0456\u0431\u0435\u043D X11",
Port: "\u041F\u043E\u0440\u0442",
Settings: "\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F",
Username: "\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430",
@@ -25717,21 +25717,21 @@ If you want to access a device on a public server, please input "<id>@public", t
"Verification code": "\u041A\u043E\u0434 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F",
verification_tip: "\u041A\u043E\u0434 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u043D\u043E \u043D\u0430 \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u043E\u0432\u0430\u043D\u0443 email-\u0430\u0434\u0440\u0435\u0441\u0443, \u0432\u0432\u0435\u0434\u0456\u0442\u044C \u043A\u043E\u0434 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F \u0434\u043B\u044F \u043F\u0440\u043E\u0434\u043E\u0432\u0436\u0435\u043D\u043D\u044F \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0456\u0457.",
Logout: "\u0412\u0438\u0439\u0442\u0438",
Tags: "\u0422\u0435\u0433\u0438",
Tags: "\u041C\u0456\u0442\u043A\u0438",
"Search ID": "\u041F\u043E\u0448\u0443\u043A \u0437\u0430 ID",
whitelist_sep: "\u0412\u0456\u0434\u043E\u043A\u0440\u0435\u043C\u043B\u0435\u043D\u043D\u044F \u043A\u043E\u043C\u043E\u044E, \u043A\u0440\u0430\u043F\u043A\u043E\u044E \u0437 \u043A\u043E\u043C\u043E\u044E, \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u043E\u043C \u0430\u0431\u043E \u043D\u043E\u0432\u0438\u043C \u0440\u044F\u0434\u043A\u043E\u043C",
"Add ID": "\u0414\u043E\u0434\u0430\u0442\u0438 ID",
"Add Tag": "\u0414\u043E\u0434\u0430\u0442\u0438 \u043A\u043B\u044E\u0447\u043E\u0432\u0435 \u0441\u043B\u043E\u0432\u043E",
"Unselect all tags": "\u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0431\u0456\u0440 \u0443\u0441\u0456\u0445 \u0442\u0435\u0433\u0456\u0432",
"Add Tag": "\u0414\u043E\u0434\u0430\u0442\u0438 \u043C\u0456\u0442\u043A\u0443",
"Unselect all tags": "\u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0431\u0456\u0440 \u0443\u0441\u0456\u0445 \u043C\u0456\u0442\u043E\u043A",
"Network error": "\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u043C\u0435\u0440\u0435\u0436\u0456",
"Username missed": "\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0454",
"Password missed": "\u041F\u0430\u0440\u043E\u043B\u044C \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439",
"Wrong credentials": "\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456 \u0434\u0430\u043D\u0456",
"The verification code is incorrect or has expired": "\u041A\u043E\u0434 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0438\u0439 \u0430\u0431\u043E \u043F\u0440\u043E\u0442\u0435\u0440\u043C\u0456\u043D\u043E\u0432\u0430\u043D\u0438\u0439",
"Edit Tag": "\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0442\u0435\u0433",
"Edit Tag": "\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u043C\u0456\u0442\u043A\u0443",
"Forget Password": "\u041D\u0435 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C",
Favorites: "\u0412\u0438\u0431\u0440\u0430\u043D\u0435",
"Add to Favorites": "\u0414\u043E\u0434\u0430\u0442\u0438 \u0432 \u043E\u0431\u0440\u0430\u043D\u0435",
"Add to Favorites": "\u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u043E \u043E\u0431\u0440\u0430\u043D\u043E\u0433\u043E",
"Remove from Favorites": "\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u0437 \u043E\u0431\u0440\u0430\u043D\u043E\u0433\u043E",
Empty: "\u041F\u0443\u0441\u0442\u043E",
"Invalid folder name": "\u041D\u0435\u043F\u0440\u0438\u043F\u0443\u0441\u0442\u0438\u043C\u0430 \u043D\u0430\u0437\u0432\u0430 \u0442\u0435\u043A\u0438",
@@ -25743,7 +25743,7 @@ If you want to access a device on a public server, please input "<id>@public", t
Paste: "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u0438",
"Paste here?": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0441\u044E\u0434\u0438?",
"Are you sure to close the connection?": "\u0412\u0438 \u0432\u043F\u0435\u0432\u043D\u0435\u043D\u0456, \u0449\u043E \u0445\u043E\u0447\u0435\u0442\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0438 \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F?",
"Download new version": "\u041E\u0442\u0440\u0438\u043C\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044E",
"Download new version": "\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u043D\u043E\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044E",
"Touch mode": "\u0421\u0435\u043D\u0441\u043E\u0440\u043D\u0438\u0439 \u0440\u0435\u0436\u0438\u043C",
"Mouse mode": "\u0420\u0435\u0436\u0438\u043C \u043C\u0438\u0448\u0456",
"One-Finger Tap": "\u0414\u043E\u0442\u0438\u043A \u043E\u0434\u043D\u0438\u043C \u043F\u0430\u043B\u044C\u0446\u0435\u043C",
@@ -25776,7 +25776,7 @@ If you want to access a device on a public server, please input "<id>@public", t
"Screen Connection": "\u041F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F \u0435\u043A\u0440\u0430\u043D\u0430",
"Do you accept?": "\u0412\u0438 \u0437\u0433\u043E\u0434\u043D\u0456?",
"Open System Setting": "\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0441\u0438\u0441\u0442\u0435\u043C\u0438",
"How to get Android input permission?": "\u042F\u043A \u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 \u0434\u043E\u0437\u0432\u0456\u043B \u043D\u0430 \u0432\u0432\u0435\u0434\u0435\u043D\u043D\u044F Android?",
"How to get Android input permission?": "\u042F\u043A \u043E\u0442\u0440\u0438\u043C\u0430\u0442\u0438 \u0434\u043E\u0437\u0432\u0456\u043B \u043D\u0430 \u0432\u0432\u0435\u0434\u0435\u043D\u043D\u044F \u0432 Android?",
android_input_permission_tip1: '\u0414\u043B\u044F \u0442\u043E\u0433\u043E, \u0449\u043E\u0431 \u0432\u0456\u0434\u0434\u0430\u043B\u0435\u043D\u0438\u0439 \u043F\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043C\u0456\u0433 \u043A\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0432\u0430\u0448\u0438\u043C Android-\u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0454\u043C \u0437\u0430 \u0434\u043E\u043F\u043E\u043C\u043E\u0433\u043E\u044E \u043C\u0438\u0448\u0456 \u0430\u0431\u043E \u0434\u043E\u0442\u0438\u043A\u0443, \u0432\u0430\u043C \u043D\u0435\u043E\u0431\u0445\u0456\u0434\u043D\u043E \u0434\u043E\u0437\u0432\u043E\u043B\u0438\u0442\u0438 RustDesk \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u043B\u0443\u0436\u0431\u0443 "\u0421\u043F\u0435\u0446\u0456\u0430\u043B\u044C\u043D\u0456 \u043C\u043E\u0436\u043B\u0438\u0432\u043E\u0441\u0442\u0456".',
android_input_permission_tip2: "\u0411\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u0435\u0440\u0435\u0439\u0434\u0456\u0442\u044C \u043D\u0430 \u043D\u0430\u0441\u0442\u0443\u043F\u043D\u0443 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0443 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0445 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u044C, \u0437\u043D\u0430\u0439\u0434\u0456\u0442\u044C \u0442\u0430 \u0443\u0432\u0456\u0439\u0434\u0456\u0442\u044C \u0443 [\u0412\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0456 \u0441\u043B\u0443\u0436\u0431\u0438], \u0443\u0432\u0456\u043C\u043A\u043D\u0456\u0442\u044C \u0441\u043B\u0443\u0436\u0431\u0443 [RustDesk Input].",
android_new_connection_tip: "\u041E\u0442\u0440\u0438\u043C\u0430\u043D\u043E \u043D\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0442 \u043D\u0430 \u043A\u0435\u0440\u0443\u0432\u0430\u043D\u043D\u044F \u0432\u0430\u0448\u0438\u043C \u043F\u043E\u0442\u043E\u0447\u043D\u0438\u043C \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0454\u043C.",
@@ -25826,15 +25826,15 @@ If you want to access a device on a public server, please input "<id>@public", t
"Display Settings": "\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0434\u0438\u0441\u043F\u043B\u0435\u044E",
Ratio: "\u0421\u043F\u0456\u0432\u0432\u0456\u0434\u043D\u043E\u0448\u0435\u043D\u043D\u044F",
"Image Quality": "\u042F\u043A\u0456\u0441\u0442\u044C \u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F",
"Scroll Style": "\u0421\u0442\u0438\u043B\u044C \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438",
"Scroll Style": "\u0421\u0442\u0438\u043B\u044C \u0433\u043E\u0440\u0442\u0430\u043D\u043D\u044F",
"Show Toolbar": "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u0430\u043D\u0435\u043B\u044C \u0456\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u0456\u0432",
"Hide Toolbar": "\u041F\u0440\u0438\u0445\u043E\u0432\u0430\u0442\u0438 \u043F\u0430\u043D\u0435\u043B\u044C \u0456\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u0456\u0432",
"Direct Connection": "\u041F\u0440\u044F\u043C\u0435 \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F",
"Relay Connection": "\u0420\u0435\u0442\u0440\u0430\u043D\u0441\u043B\u044C\u043E\u0432\u0430\u043D\u0435 \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F",
"Secure Connection": "\u0411\u0435\u0437\u043F\u0435\u0447\u043D\u0435 \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F",
"Insecure Connection": "\u041D\u0435\u0431\u0435\u0437\u043F\u0435\u0447\u043D\u0435 \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F",
"Scale original": "\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B \u043C\u0430\u0441\u0448\u0442\u0430\u0431\u0443",
"Scale adaptive": "\u041C\u0430\u0441\u0448\u0442\u0430\u0431 \u0430\u0434\u0430\u043F\u0442\u0438\u0432\u043D\u0438\u0439",
"Scale original": "\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u044C\u043D\u0438\u0439 \u043C\u0430\u0441\u0448\u0442\u0430\u0431",
"Scale adaptive": "\u0410\u0434\u0430\u043F\u0442\u0438\u0432\u043D\u0438\u0439 \u043C\u0430\u0441\u0448\u0442\u0430\u0431",
General: "\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0456",
Security: "\u0411\u0435\u0437\u043F\u0435\u043A\u0430",
Theme: "\u0422\u0435\u043C\u0430",
@@ -25899,7 +25899,7 @@ If you want to access a device on a public server, please input "<id>@public", t
"Hide connection management window": "\u041F\u0440\u0438\u0445\u043E\u0432\u0430\u0442\u0438 \u0432\u0456\u043A\u043D\u043E \u043A\u0435\u0440\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F\u043C\u0438",
hide_cm_tip: "\u0414\u043E\u0437\u0432\u043E\u043B\u0435\u043D\u043E \u043F\u0440\u0438\u0445\u043E\u0432\u0430\u0442\u0438 \u043B\u0438\u0448\u0435 \u044F\u043A\u0449\u043E \u0441\u0435\u0430\u043D\u0441 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0443\u0454\u0442\u044C\u0441\u044F \u043F\u043E\u0441\u0442\u0456\u0439\u043D\u0438\u043C \u043F\u0430\u0440\u043E\u043B\u0435\u043C",
wayland_experiment_tip: "\u041F\u0456\u0434\u0442\u0440\u0438\u043C\u043A\u0430 Wayland \u043D\u0430 \u0435\u043A\u0441\u043F\u0435\u0440\u0438\u043C\u0435\u043D\u0442\u0430\u043B\u044C\u043D\u0456\u0439 \u0441\u0442\u0430\u0434\u0456\u0457, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0439\u0442\u0435 X11, \u044F\u043A\u0449\u043E \u043D\u0435\u043E\u0431\u0445\u0456\u0434\u043D\u0438\u0439 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u0438\u0439 \u0434\u043E\u0441\u0442\u0443\u043F.",
"Right click to select tabs": "\u041F\u0440\u0430\u0432\u0438\u0439 \u043A\u043B\u0456\u043A \u0434\u043B\u044F \u0432\u0438\u0431\u043E\u0440\u0443 \u0432\u043A\u043B\u0430\u0434\u043A\u0438",
"Right click to select tabs": "\u0412\u0438\u0431\u0456\u0440 \u0432\u043A\u043B\u0430\u0434\u043E\u043A \u043A\u043B\u0430\u0446\u0430\u043D\u043D\u044F\u043C \u043F\u0440\u0430\u0432\u043E\u044E",
Skipped: "\u041F\u0440\u043E\u043F\u0443\u0449\u0435\u043D\u043E",
"Add to address book": "\u0414\u043E\u0434\u0430\u0442\u0438 IP \u0434\u043E \u0410\u0434\u0440\u0435\u0441\u043D\u043E\u0457 \u043A\u043D\u0438\u0433\u0438",
Group: "\u0413\u0440\u0443\u043F\u0430",
@@ -26013,7 +26013,7 @@ If you want to access a device on a public server, please input "<id>@public", t
Stop: "\u0417\u0443\u043F\u0438\u043D\u0438\u0442\u0438",
exceed_max_devices: "\u0423 \u0432\u0430\u0441 \u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430 \u043A\u0456\u043B\u044C\u043A\u0456\u0441\u0442\u044C \u043A\u0435\u0440\u043E\u0432\u0430\u043D\u0438\u0445 \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0457\u0432.",
"Sync with recent sessions": "\u0421\u0438\u043D\u0445\u0440\u043E\u043D\u0456\u0437\u0430\u0446\u0456\u044F \u0437 \u043D\u0435\u0449\u043E\u0434\u0430\u0432\u043D\u0456\u043C\u0438 \u0441\u0435\u0430\u043D\u0441\u0430\u043C\u0438",
"Sort tags": "\u0421\u043E\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u0435\u0433\u0438",
"Sort tags": "\u0421\u043E\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u043C\u0456\u0442\u043A\u0438",
"Open connection in new tab": "\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043F\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043D\u044F \u0432 \u043D\u043E\u0432\u0456\u0439 \u0432\u043A\u043B\u0430\u0434\u0446\u0456",
"Move tab to new window": "\u041F\u0435\u0440\u0435\u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u0432\u043A\u043B\u0430\u0434\u043A\u0443 \u0434\u043E \u043D\u043E\u0432\u043E\u0433\u043E \u0432\u0456\u043A\u043D\u0430",
"Can not be empty": "\u041D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u043F\u043E\u0440\u043E\u0436\u043D\u0456\u043C",
@@ -26024,7 +26024,7 @@ If you want to access a device on a public server, please input "<id>@public", t
"Grid View": "\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0491\u0440\u0430\u0442\u043A\u043E\u044E",
"List View": "\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0441\u043F\u0438\u0441\u043A\u043E\u043C",
Select: "\u0412\u0438\u0431\u0440\u0430\u0442\u0438",
"Toggle Tags": "\u0412\u0438\u0434\u0438\u043C\u0456\u0441\u0442\u044C \u0442\u0435\u0433\u0456\u0432",
"Toggle Tags": "\u0412\u0438\u0434\u0438\u043C\u0456\u0441\u0442\u044C \u043C\u0456\u0442\u043E\u043A",
pull_ab_failed_tip: "\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u043D\u0443 \u043A\u043D\u0438\u0433\u0443",
push_ab_failed_tip: "\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0456\u0437\u0443\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u043D\u0443 \u043A\u043D\u0438\u0433\u0443",
synced_peer_readded_tip: "\u041F\u0440\u0438\u0441\u0442\u0440\u043E\u0457 \u0437 \u043D\u0435\u0449\u043E\u0434\u0430\u0432\u043D\u0456\u0445 \u0441\u0435\u0430\u043D\u0441\u0456\u0432 \u0431\u0443\u0434\u0443\u0442\u044C \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0456\u0437\u043E\u0432\u0430\u043D\u0456 \u0437 \u0430\u0434\u0440\u0435\u0441\u043D\u043E\u044E \u043A\u043D\u0438\u0433\u043E\u044E.",
@@ -26033,7 +26033,7 @@ If you want to access a device on a public server, please input "<id>@public", t
"HSV Color": "\u041A\u043E\u043B\u0456\u0440 HSV",
"Installation Successful!": "\u0423\u0441\u043F\u0456\u0448\u043D\u0435 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F!",
"Installation failed!": "\u041D\u0435\u0432\u0434\u0430\u043B\u0435 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F!",
"Reverse mouse wheel": "\u0417\u0432\u043E\u0440\u043E\u0442\u043D\u0456\u0439 \u043D\u0430\u043F\u0440\u044F\u043C \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438",
"Reverse mouse wheel": "\u0417\u0432\u043E\u0440\u043E\u0442\u043D\u0456\u0439 \u043D\u0430\u043F\u0440\u044F\u043C \u0433\u043E\u0440\u0442\u0430\u043D\u043D\u044F",
"{} sessions": "{} \u0441\u0435\u0430\u043D\u0441\u0456\u0432",
scam_title: "\u0412\u0430\u0441 \u043C\u043E\u0436\u0443\u0442\u044C \u041E\u0411\u041C\u0410\u041D\u0423\u0422\u0418!",
scam_text1: "\u042F\u043A\u0449\u043E \u0432\u0438 \u0440\u043E\u0437\u043C\u043E\u0432\u043B\u044F\u0454\u0442\u0435 \u043F\u043E \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0437 \u043A\u0438\u043C\u043E\u0441\u044C, \u043A\u043E\u0433\u043E \u041D\u0415 \u0417\u041D\u0410\u0404\u0422\u0415 \u0447\u0438 \u043A\u043E\u043C\u0443 \u041D\u0415 \u0414\u041E\u0412\u0406\u0420\u042F\u0404\u0422\u0415, \u0456 \u0446\u044F \u043E\u0441\u043E\u0431\u0430 \u0445\u043E\u0447\u0435, \u0449\u043E\u0431 \u0432\u0438 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043B\u0438 RustDesk \u0442\u0430 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u043B\u0438 \u0441\u043B\u0443\u0436\u0431\u0443, \u043D\u0435 \u0440\u043E\u0431\u0456\u0442\u044C \u0446\u044C\u043E\u0433\u043E \u0442\u0430 \u043D\u0435\u0433\u0430\u0439\u043D\u043E \u0437\u0430\u0432\u0435\u0440\u0448\u0456\u0442\u044C \u0434\u0437\u0432\u0456\u043D\u043E\u043A.",
@@ -26166,7 +26166,7 @@ If you want to access a device on a public server, please input "<id>@public", t
"Upload files": "\u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0444\u0430\u0439\u043B\u0438",
"Clipboard is synchronized": "\u0411\u0443\u0444\u0435\u0440 \u043E\u0431\u043C\u0456\u043D\u0443 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0456\u0437\u043E\u0432\u0430\u043D\u043E",
"Update client clipboard": "\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u0431\u0443\u0444\u0435\u0440 \u043E\u0431\u043C\u0456\u043D\u0443 \u043A\u043B\u0456\u0454\u043D\u0442\u0430",
Untagged: ""
Untagged: "\u0411\u0435\u0437 \u043C\u0456\u0442\u043E\u043A"
}, cs: {
Status: "Stav",
"Your Desktop": "Va\u0161e plocha",

108026
resources/web2/main.dart.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,7 @@ package service
import (
"Gwen/global"
"Gwen/model"
"encoding/json"
"github.com/google/uuid"
"gorm.io/gorm"
"strings"
@@ -116,6 +117,16 @@ func (s *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB))
return
}
func (s *AddressBookService) FromPeer(peer *model.Peer) (a *model.AddressBook) {
a = &model.AddressBook{}
a.Id = peer.Id
a.Username = peer.Username
a.Hostname = peer.Hostname
a.UserId = peer.UserId
a.Platform = s.PlatformFromOs(peer.Os)
return a
}
// Create 创建
func (s *AddressBookService) Create(u *model.AddressBook) error {
res := global.DB.Create(u).Error
@@ -318,3 +329,12 @@ func (s *AddressBookService) CheckCollectionOwner(uid uint, cid uint) bool {
p := s.CollectionInfoById(cid)
return p.UserId == uid
}
func (s *AddressBookService) BatchUpdateTags(abs []*model.AddressBook, tags []string) error {
ids := make([]uint, 0)
for _, ab := range abs {
ids = append(ids, ab.RowId)
}
tagsv, _ := json.Marshal(tags)
return global.DB.Model(&model.AddressBook{}).Where("row_id in ?", ids).Update("tags", tagsv).Error
}

View File

@@ -16,6 +16,7 @@ type Service struct {
*OauthService
*LoginLogService
*AuditService
*ShareRecordService
}
func New() *Service {

49
service/shareRecord.go Normal file
View File

@@ -0,0 +1,49 @@
package service
import (
"Gwen/global"
"Gwen/model"
"gorm.io/gorm"
)
type ShareRecordService struct {
}
// InfoById 根据用户id取用户信息
func (srs *ShareRecordService) InfoById(id uint) *model.ShareRecord {
u := &model.ShareRecord{}
global.DB.Where("id = ?", id).First(u)
return u
}
func (srs *ShareRecordService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.ShareRecordList) {
res = &model.ShareRecordList{}
res.Page = int64(page)
res.PageSize = int64(pageSize)
tx := global.DB.Model(&model.ShareRecord{})
if where != nil {
where(tx)
}
tx.Count(&res.Total)
tx.Scopes(Paginate(page, pageSize))
tx.Find(&res.ShareRecords)
return
}
// Create 创建
func (srs *ShareRecordService) Create(u *model.ShareRecord) error {
res := global.DB.Create(u).Error
return res
}
func (srs *ShareRecordService) Delete(u *model.ShareRecord) error {
return global.DB.Delete(u).Error
}
// Update 更新
func (srs *ShareRecordService) Update(u *model.ShareRecord) error {
return global.DB.Model(u).Updates(u).Error
}
func (srs *ShareRecordService) BatchDelete(ids []uint) error {
return global.DB.Where("id in (?)", ids).Delete(&model.ShareRecord{}).Error
}

View File

@@ -458,3 +458,7 @@ func (us *UserService) AutoRefreshAccessToken(ut *model.UserToken) {
us.RefreshAccessToken(ut)
}
}
func (us *UserService) BatchDeleteUserToken(ids []uint) error {
return global.DB.Where("id in ?", ids).Delete(&model.UserToken{}).Error
}