mirror of
https://github.com/lejianwen/rustdesk-api.git
synced 2026-01-21 06:20:35 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09fdd34ba3 | ||
|
|
bba10261c5 | ||
|
|
46bfe54097 | ||
|
|
503e7a307e | ||
|
|
821b0a6faf | ||
|
|
d60fdff179 | ||
|
|
fdd841e82a | ||
|
|
2d6f0a116a | ||
|
|
bd13fe4ef4 | ||
|
|
6e1b208464 | ||
|
|
76433a409e | ||
|
|
9b4fa679c2 | ||
|
|
c2ae95c4cc | ||
|
|
b2b7f60fd5 | ||
|
|
a465888b31 |
199
README.md
199
README.md
@@ -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)
|
||||
|
||||
200
README_EN.md
200
README_EN.md
@@ -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)
|
||||
|
||||
@@ -2,6 +2,7 @@ lang: "zh-CN"
|
||||
app:
|
||||
web-client: 1 # 1:启用 0:禁用
|
||||
register: false #是否开启注册
|
||||
show-swagger: 0 # 1:启用 0:禁用
|
||||
admin:
|
||||
title: "RustDesk Api Admin"
|
||||
hello-file: "./conf/admin/hello.html" #优先使用file
|
||||
|
||||
@@ -14,8 +14,9 @@ const (
|
||||
)
|
||||
|
||||
type App struct {
|
||||
WebClient int `mapstructure:"web-client"`
|
||||
Register bool `mapstructure:"register"`
|
||||
WebClient int `mapstructure:"web-client"`
|
||||
Register bool `mapstructure:"register"`
|
||||
ShowSwagger int `mapstructure:"show-swagger"`
|
||||
}
|
||||
type Admin struct {
|
||||
Title string `mapstructure:"title"`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,8 @@ basePath: /api
|
||||
definitions:
|
||||
Gwen_http_request_admin.Login:
|
||||
properties:
|
||||
captcha:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
platform:
|
||||
@@ -78,11 +80,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 +184,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 +212,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 +256,7 @@ definitions:
|
||||
- $ref: '#/definitions/model.StatusCode'
|
||||
minimum: 0
|
||||
username:
|
||||
maxLength: 10
|
||||
maxLength: 32
|
||||
minLength: 2
|
||||
type: string
|
||||
required:
|
||||
@@ -258,13 +276,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:
|
||||
@@ -748,7 +775,7 @@ info:
|
||||
title: 管理系统API
|
||||
version: "1.0"
|
||||
paths:
|
||||
/admin/address_book/create:
|
||||
/admin/address_book/batchCreate:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
@@ -781,6 +808,39 @@ paths:
|
||||
summary: 批量创建地址簿
|
||||
tags:
|
||||
- 地址簿
|
||||
/admin/address_book/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建地址簿
|
||||
parameters:
|
||||
- description: 地址簿信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.AddressBookForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBook'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 创建地址簿
|
||||
tags:
|
||||
- 地址簿
|
||||
/admin/address_book/delete:
|
||||
post:
|
||||
consumes:
|
||||
@@ -1950,6 +2010,683 @@ paths:
|
||||
summary: 登出
|
||||
tags:
|
||||
- 登录
|
||||
/admin/my/address_book/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建地址簿
|
||||
parameters:
|
||||
- description: 地址簿信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.AddressBookForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBook'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 创建地址簿
|
||||
tags:
|
||||
- 我的地址簿
|
||||
/admin/my/address_book/delete:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿删除
|
||||
parameters:
|
||||
- description: 地址簿信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.AddressBookForm'
|
||||
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/address_book/list:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿列表
|
||||
parameters:
|
||||
- description: 页码
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 页大小
|
||||
in: query
|
||||
name: page_size
|
||||
type: integer
|
||||
- description: 用户id
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookList'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 地址簿列表
|
||||
tags:
|
||||
- 我的地址簿
|
||||
/admin/my/address_book/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿编辑
|
||||
parameters:
|
||||
- description: 地址簿信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.AddressBookForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBook'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 地址簿编辑
|
||||
tags:
|
||||
- 我的地址簿
|
||||
/admin/my/address_book_collection/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建地址簿名称
|
||||
parameters:
|
||||
- description: 地址簿名称信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 创建地址簿名称
|
||||
tags:
|
||||
- 我的地址簿名称
|
||||
/admin/my/address_book_collection/delete:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿名称删除
|
||||
parameters:
|
||||
- description: 地址簿名称信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
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/address_book_collection/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:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookCollectionList'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 地址簿名称列表
|
||||
tags:
|
||||
- 我的地址簿名称
|
||||
/admin/my/address_book_collection/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿名称编辑
|
||||
parameters:
|
||||
- description: 地址簿名称信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 地址簿名称编辑
|
||||
tags:
|
||||
- 我的地址簿名称
|
||||
/admin/my/address_book_collection_rule/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建地址簿规则
|
||||
parameters:
|
||||
- description: 地址簿规则信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.AddressBookCollectionRule'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 创建地址簿规则
|
||||
tags:
|
||||
- 我的地址簿规则
|
||||
/admin/my/address_book_collection_rule/delete:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿规则删除
|
||||
parameters:
|
||||
- description: 地址簿规则信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.AddressBookCollectionRule'
|
||||
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/address_book_collection_rule/list:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿规则列表
|
||||
parameters:
|
||||
- description: 页码
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 页大小
|
||||
in: query
|
||||
name: page_size
|
||||
type: integer
|
||||
- description: 是否是我的
|
||||
in: query
|
||||
name: is_my
|
||||
type: integer
|
||||
- description: 用户id
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
- description: 地址簿集合id
|
||||
in: query
|
||||
name: collection_id
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookCollectionList'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 地址簿规则列表
|
||||
tags:
|
||||
- 我的地址簿规则
|
||||
/admin/my/address_book_collection_rule/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 地址簿规则编辑
|
||||
parameters:
|
||||
- description: 地址簿规则信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.AddressBookCollectionRule'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.AddressBookCollection'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 地址簿规则编辑
|
||||
tags:
|
||||
- 我的地址簿规则
|
||||
/admin/my/peer/list:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 设备列表
|
||||
parameters:
|
||||
- description: 页码
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 页大小
|
||||
in: query
|
||||
name: page_size
|
||||
type: integer
|
||||
- description: 时间
|
||||
in: query
|
||||
name: time_ago
|
||||
type: integer
|
||||
- description: ID
|
||||
in: query
|
||||
name: id
|
||||
type: string
|
||||
- description: 主机名
|
||||
in: query
|
||||
name: hostname
|
||||
type: string
|
||||
- description: uuids 用逗号分隔
|
||||
in: query
|
||||
name: uuids
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.PeerList'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
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/my/tag/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建标签
|
||||
parameters:
|
||||
- description: 标签信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.TagForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.Tag'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 创建标签
|
||||
tags:
|
||||
- 我的标签
|
||||
/admin/my/tag/delete:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 标签删除
|
||||
parameters:
|
||||
- description: 标签信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.TagForm'
|
||||
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/tag/list:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 标签列表
|
||||
parameters:
|
||||
- description: 页码
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 页大小
|
||||
in: query
|
||||
name: page_size
|
||||
type: integer
|
||||
- description: 是否是我的
|
||||
in: query
|
||||
name: is_my
|
||||
type: integer
|
||||
- description: 用户id
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.TagList'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 标签列表
|
||||
tags:
|
||||
- 我的标签
|
||||
/admin/my/tag/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 标签编辑
|
||||
parameters:
|
||||
- description: 标签信息
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/admin.TagForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.Tag'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 标签编辑
|
||||
tags:
|
||||
- 我的标签
|
||||
/admin/oauth/create:
|
||||
post:
|
||||
consumes:
|
||||
@@ -2372,6 +3109,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:
|
||||
@@ -2755,57 +3582,6 @@ paths:
|
||||
summary: 我的授权
|
||||
tags:
|
||||
- 用户
|
||||
/admin/user/myPeer:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 我的设备列表
|
||||
parameters:
|
||||
- description: 页码
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: 页大小
|
||||
in: query
|
||||
name: page_size
|
||||
type: integer
|
||||
- description: 时间
|
||||
in: query
|
||||
name: time_ago
|
||||
type: integer
|
||||
- description: ID
|
||||
in: query
|
||||
name: id
|
||||
type: string
|
||||
- description: 主机名
|
||||
in: query
|
||||
name: hostname
|
||||
type: string
|
||||
- description: uuids 用逗号分隔
|
||||
in: query
|
||||
name: uuids
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.Response'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/model.PeerList'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.Response'
|
||||
security:
|
||||
- token: []
|
||||
summary: 我的设备列表
|
||||
tags:
|
||||
- 设备
|
||||
/admin/user/update:
|
||||
post:
|
||||
consumes:
|
||||
@@ -2867,6 +3643,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:
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
|
||||
3
go.mod
3
go.mod
@@ -43,6 +43,7 @@ require (
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
@@ -58,6 +59,7 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mojocn/base64Captcha v1.3.6 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
@@ -69,6 +71,7 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/image v0.13.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"Gwen/http/response"
|
||||
"Gwen/model"
|
||||
"Gwen/service"
|
||||
"encoding/json"
|
||||
_ "encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
@@ -30,11 +31,6 @@ func (ct *AddressBook) Detail(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
iid, _ := strconv.Atoi(id)
|
||||
t := service.AllService.AddressBookService.InfoByRowId(uint(iid))
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
if t.RowId > 0 {
|
||||
response.Success(c, t)
|
||||
return
|
||||
@@ -66,9 +62,9 @@ func (ct *AddressBook) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
t := f.ToAddressBook()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 {
|
||||
t.UserId = u.Id
|
||||
if t.UserId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
@@ -98,7 +94,7 @@ func (ct *AddressBook) Create(c *gin.Context) {
|
||||
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/address_book/create [post]
|
||||
// @Router /admin/address_book/batchCreate [post]
|
||||
// @Security token
|
||||
func (ct *AddressBook) BatchCreate(c *gin.Context) {
|
||||
f := &admin.AddressBookForm{}
|
||||
@@ -161,10 +157,6 @@ func (ct *AddressBook) List(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
|
||||
query.UserId = int(u.Id)
|
||||
}
|
||||
res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
|
||||
return txc.Select("id,name")
|
||||
@@ -190,11 +182,6 @@ func (ct *AddressBook) List(c *gin.Context) {
|
||||
for _, ab := range res.AddressBooks {
|
||||
abCIds = append(abCIds, ab.CollectionId)
|
||||
}
|
||||
//获取地址簿名称
|
||||
//cRes := service.AllService.AddressBookService.ListCollection(1, 999, func(tx *gorm.DB) {
|
||||
// tx.Where("id in ?", abCIds)
|
||||
//})
|
||||
//
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
@@ -221,15 +208,15 @@ func (ct *AddressBook) Update(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if f.RowId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
ex := service.AllService.AddressBookService.InfoByRowId(f.RowId)
|
||||
if ex.RowId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
t := f.ToAddressBook()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
@@ -270,21 +257,12 @@ func (ct *AddressBook) Delete(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
err := service.AllService.AddressBookService.Delete(t)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
if u.Id > 0 {
|
||||
err := service.AllService.AddressBookService.Delete(t)
|
||||
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"))
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
}
|
||||
|
||||
// ShareByWebClient
|
||||
@@ -327,3 +305,47 @@ 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)
|
||||
}
|
||||
|
||||
@@ -29,11 +29,6 @@ func (abc *AddressBookCollection) Detail(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
iid, _ := strconv.Atoi(id)
|
||||
t := service.AllService.AddressBookService.CollectionInfoById(uint(iid))
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
if t.Id > 0 {
|
||||
response.Success(c, t)
|
||||
return
|
||||
@@ -64,12 +59,11 @@ func (abc *AddressBookCollection) Create(c *gin.Context) {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
//t := f.ToAddressBookCollection()
|
||||
t := f
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 {
|
||||
t.UserId = u.Id
|
||||
if f.UserId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
t := f
|
||||
err := service.AllService.AddressBookService.CreateCollection(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
@@ -98,10 +92,6 @@ func (abc *AddressBookCollection) List(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
|
||||
query.UserId = int(u.Id)
|
||||
}
|
||||
res := service.AllService.AddressBookService.ListCollection(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
if query.UserId > 0 {
|
||||
tx.Where("user_id = ?", query.UserId)
|
||||
@@ -137,11 +127,6 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
t := f //f.ToAddressBookCollection()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.AddressBookService.UpdateCollection(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
@@ -173,20 +158,15 @@ func (abc *AddressBookCollection) Delete(c *gin.Context) {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
t := service.AllService.AddressBookService.CollectionInfoById(f.Id)
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
ex := service.AllService.AddressBookService.CollectionInfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if u.Id > 0 {
|
||||
err := service.AllService.AddressBookService.DeleteCollection(t)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, err.Error())
|
||||
err := service.AllService.AddressBookService.DeleteCollection(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
}
|
||||
|
||||
@@ -35,10 +35,6 @@ func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
|
||||
query.UserId = int(u.Id)
|
||||
}
|
||||
|
||||
res := service.AllService.AddressBookService.ListRules(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
if query.UserId > 0 {
|
||||
@@ -66,17 +62,11 @@ func (abcr *AddressBookCollectionRule) Detail(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
iid, _ := strconv.Atoi(id)
|
||||
t := service.AllService.AddressBookService.RuleInfoById(uint(iid))
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
if t.Id > 0 {
|
||||
response.Success(c, t)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
|
||||
// Create 创建地址簿规则
|
||||
@@ -105,13 +95,8 @@ func (abcr *AddressBookCollectionRule) Create(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
//t := f.ToAddressBookCollection()
|
||||
t := f
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if t.UserId == 0 {
|
||||
t.UserId = u.Id
|
||||
}
|
||||
msg, res := abcr.CheckForm(u, t)
|
||||
msg, res := abcr.CheckForm(t)
|
||||
if !res {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, msg))
|
||||
return
|
||||
@@ -124,9 +109,9 @@ func (abcr *AddressBookCollectionRule) Create(c *gin.Context) {
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.AddressBookCollectionRule) (string, bool) {
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
return "NoAccess", false
|
||||
func (abcr *AddressBookCollectionRule) CheckForm(t *model.AddressBookCollectionRule) (string, bool) {
|
||||
if t.UserId == 0 {
|
||||
return "ParamsError", false
|
||||
}
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
return "ParamsError", false
|
||||
@@ -141,15 +126,7 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
|
||||
if tou.Id == 0 {
|
||||
return "ItemNotFound", false
|
||||
}
|
||||
//非管理员不能分享给非本组织用户
|
||||
if tou.GroupId != u.GroupId && !service.AllService.UserService.IsAdmin(u) {
|
||||
return "NoAccess", false
|
||||
}
|
||||
} else if t.Type == model.ShareAddressBookRuleTypeGroup {
|
||||
if t.ToId != u.GroupId && !service.AllService.UserService.IsAdmin(u) {
|
||||
return "NoAccess", false
|
||||
}
|
||||
|
||||
tog := service.AllService.GroupService.InfoById(t.ToId)
|
||||
if tog.Id == 0 {
|
||||
return "ItemNotFound", false
|
||||
@@ -194,9 +171,8 @@ func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
t := f //f.ToAddressBookCollection()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
msg, res := abcr.CheckForm(u, t)
|
||||
t := f
|
||||
msg, res := abcr.CheckForm(t)
|
||||
if !res {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, msg))
|
||||
return
|
||||
@@ -232,20 +208,15 @@ func (abcr *AddressBookCollectionRule) Delete(c *gin.Context) {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
t := service.AllService.AddressBookService.RuleInfoById(f.Id)
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
ex := service.AllService.AddressBookService.RuleInfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if t.Id > 0 {
|
||||
err := service.AllService.AddressBookService.DeleteRule(t)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, err.Error())
|
||||
err := service.AllService.AddressBookService.DeleteRule(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
}
|
||||
|
||||
@@ -11,11 +11,135 @@ import (
|
||||
"Gwen/service"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Login struct {
|
||||
}
|
||||
|
||||
// Captcha 验证码结构
|
||||
type Captcha struct {
|
||||
Id string `json:"id"` // 验证码 ID
|
||||
B64 string `json:"b64"` // base64 验证码
|
||||
Code string `json:"-"` // 验证码内容
|
||||
ExpiresAt time.Time `json:"-"` // 过期时间
|
||||
}
|
||||
type LoginLimiter struct {
|
||||
mu sync.RWMutex
|
||||
failCount map[string]int // 记录每个 IP 的失败次数
|
||||
timestamp map[string]time.Time // 记录每个 IP 的最后失败时间
|
||||
captchas map[string]Captcha // 每个 IP 的验证码
|
||||
threshold int // 失败阈值
|
||||
expiry time.Duration // 失败记录过期时间
|
||||
}
|
||||
|
||||
func NewLoginLimiter(threshold int, expiry time.Duration) *LoginLimiter {
|
||||
return &LoginLimiter{
|
||||
failCount: make(map[string]int),
|
||||
timestamp: make(map[string]time.Time),
|
||||
captchas: make(map[string]Captcha),
|
||||
threshold: threshold,
|
||||
expiry: expiry,
|
||||
}
|
||||
}
|
||||
|
||||
// RecordFailure 记录登录失败
|
||||
func (l *LoginLimiter) RecordFailure(ip string) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
// 如果该 IP 的记录已经过期,重置计数
|
||||
if lastTime, exists := l.timestamp[ip]; exists && time.Since(lastTime) > l.expiry {
|
||||
l.failCount[ip] = 0
|
||||
}
|
||||
|
||||
// 更新失败次数和时间戳
|
||||
l.failCount[ip]++
|
||||
l.timestamp[ip] = time.Now()
|
||||
}
|
||||
|
||||
// NeedsCaptcha 检查是否需要验证码
|
||||
func (l *LoginLimiter) NeedsCaptcha(ip string) bool {
|
||||
l.mu.RLock()
|
||||
defer l.mu.RUnlock()
|
||||
|
||||
// 检查记录是否存在且未过期
|
||||
if lastTime, exists := l.timestamp[ip]; exists && time.Since(lastTime) <= l.expiry {
|
||||
return l.failCount[ip] >= l.threshold
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GenerateCaptcha 为指定 IP 生成验证码
|
||||
func (l *LoginLimiter) GenerateCaptcha(ip string) Captcha {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
capd := base64Captcha.NewDriverString(50, 150, 5, 10, 4, "1234567890abcdefghijklmnopqrstuvwxyz", nil, nil, nil)
|
||||
b64cap := base64Captcha.NewCaptcha(capd, base64Captcha.DefaultMemStore)
|
||||
id, b64s, answer, err := b64cap.Generate()
|
||||
if err != nil {
|
||||
global.Logger.Error("Generate captcha failed: " + err.Error())
|
||||
return Captcha{}
|
||||
}
|
||||
// 保存验证码到对应 IP
|
||||
l.captchas[ip] = Captcha{
|
||||
Id: id,
|
||||
B64: b64s,
|
||||
Code: answer,
|
||||
ExpiresAt: time.Now().Add(5 * time.Minute),
|
||||
}
|
||||
return l.captchas[ip]
|
||||
}
|
||||
|
||||
// VerifyCaptcha 验证指定 IP 的验证码
|
||||
func (l *LoginLimiter) VerifyCaptcha(ip, code string) bool {
|
||||
l.mu.RLock()
|
||||
defer l.mu.RUnlock()
|
||||
|
||||
// 检查验证码是否存在且未过期
|
||||
if captcha, exists := l.captchas[ip]; exists && time.Now().Before(captcha.ExpiresAt) {
|
||||
return captcha.Code == code
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveCaptcha 移除指定 IP 的验证码
|
||||
func (l *LoginLimiter) RemoveCaptcha(ip string) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
delete(l.captchas, ip)
|
||||
}
|
||||
|
||||
// CleanupExpired 清理过期的记录
|
||||
func (l *LoginLimiter) CleanupExpired() {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
for ip, lastTime := range l.timestamp {
|
||||
if now.Sub(lastTime) > l.expiry {
|
||||
delete(l.failCount, ip)
|
||||
delete(l.timestamp, ip)
|
||||
delete(l.captchas, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LoginLimiter) RemoveRecord(ip string) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
delete(l.failCount, ip)
|
||||
delete(l.timestamp, ip)
|
||||
delete(l.captchas, ip)
|
||||
}
|
||||
|
||||
var loginLimiter = NewLoginLimiter(3, 5*time.Minute)
|
||||
|
||||
// Login 登录
|
||||
// @Tags 登录
|
||||
// @Summary 登录
|
||||
@@ -30,22 +154,39 @@ type Login struct {
|
||||
func (ct *Login) Login(c *gin.Context) {
|
||||
f := &admin.Login{}
|
||||
err := c.ShouldBindJSON(f)
|
||||
clientIp := c.ClientIP()
|
||||
if err != nil {
|
||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), c.ClientIP()))
|
||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), clientIp))
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), c.ClientIP()))
|
||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), clientIp))
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否需要验证码
|
||||
if loginLimiter.NeedsCaptcha(clientIp) {
|
||||
if f.Captcha == "" || !loginLimiter.VerifyCaptcha(clientIp, f.Captcha) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
||||
|
||||
if u.Id == 0 {
|
||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), c.ClientIP()))
|
||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), clientIp))
|
||||
loginLimiter.RecordFailure(clientIp)
|
||||
if loginLimiter.NeedsCaptcha(clientIp) {
|
||||
// 移除原验证码,重新生成
|
||||
loginLimiter.RemoveCaptcha(clientIp)
|
||||
response.Fail(c, 110, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||
return
|
||||
}
|
||||
@@ -54,13 +195,30 @@ func (ct *Login) Login(c *gin.Context) {
|
||||
UserId: u.Id,
|
||||
Client: model.LoginLogClientWebAdmin,
|
||||
Uuid: "", //must be empty
|
||||
Ip: c.ClientIP(),
|
||||
Ip: clientIp,
|
||||
Type: model.LoginLogTypeAccount,
|
||||
Platform: f.Platform,
|
||||
})
|
||||
|
||||
// 成功后清除记录
|
||||
loginLimiter.RemoveRecord(clientIp)
|
||||
|
||||
// 清理过期记录
|
||||
go loginLimiter.CleanupExpired()
|
||||
|
||||
responseLoginSuccess(c, u, ut.Token)
|
||||
}
|
||||
func (ct *Login) Captcha(c *gin.Context) {
|
||||
clientIp := c.ClientIP()
|
||||
if !loginLimiter.NeedsCaptcha(clientIp) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoCaptchaRequired"))
|
||||
return
|
||||
}
|
||||
captcha := loginLimiter.GenerateCaptcha(clientIp)
|
||||
response.Success(c, gin.H{
|
||||
"captcha": captcha,
|
||||
})
|
||||
}
|
||||
|
||||
// Logout 登出
|
||||
// @Tags 登录
|
||||
@@ -90,10 +248,12 @@ func (ct *Login) Logout(c *gin.Context) {
|
||||
// @Failure 500 {object} response.ErrorResponse
|
||||
// @Router /admin/login-options [post]
|
||||
func (ct *Login) LoginOptions(c *gin.Context) {
|
||||
ip := c.ClientIP()
|
||||
ops := service.AllService.OauthService.GetOauthProviders()
|
||||
response.Success(c, gin.H{
|
||||
"ops": ops,
|
||||
"register": global.Config.App.Register,
|
||||
"ops": ops,
|
||||
"register": global.Config.App.Register,
|
||||
"need_captcha": loginLimiter.NeedsCaptcha(ip),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -154,11 +314,10 @@ func (ct *Login) OidcAuthQuery(c *gin.Context) {
|
||||
responseLoginSuccess(c, u, ut.Token)
|
||||
}
|
||||
|
||||
|
||||
func responseLoginSuccess(c *gin.Context, u *model.User, token string) {
|
||||
lp := &adResp.LoginPayload{}
|
||||
lp.FromUser(u)
|
||||
lp.Token = token
|
||||
lp.RouteNames = service.AllService.UserService.RouteNames(u)
|
||||
response.Success(c, lp)
|
||||
}
|
||||
}
|
||||
|
||||
271
http/controller/admin/my/addressBook.go
Normal file
271
http/controller/admin/my/addressBook.go
Normal file
@@ -0,0 +1,271 @@
|
||||
package my
|
||||
|
||||
import (
|
||||
"Gwen/global"
|
||||
"Gwen/http/request/admin"
|
||||
"Gwen/http/response"
|
||||
"Gwen/service"
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AddressBook struct{}
|
||||
|
||||
// List 列表
|
||||
// @Tags 我的地址簿
|
||||
// @Summary 地址簿列表
|
||||
// @Description 地址簿列表
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "页大小"
|
||||
// @Param user_id query int false "用户id"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookList}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book/list [get]
|
||||
// @Security token
|
||||
func (ct *AddressBook) List(c *gin.Context) {
|
||||
query := &admin.AddressBookQuery{}
|
||||
if err := c.ShouldBindQuery(query); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
query.UserId = int(u.Id)
|
||||
res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
//预加载地址簿名称
|
||||
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
|
||||
return txc.Select("id,name")
|
||||
})
|
||||
if query.Id != "" {
|
||||
tx.Where("id like ?", "%"+query.Id+"%")
|
||||
}
|
||||
tx.Where("user_id = ?", query.UserId)
|
||||
if query.Username != "" {
|
||||
tx.Where("username like ?", "%"+query.Username+"%")
|
||||
}
|
||||
if query.Hostname != "" {
|
||||
tx.Where("hostname like ?", "%"+query.Hostname+"%")
|
||||
}
|
||||
if query.CollectionId != nil && *query.CollectionId >= 0 {
|
||||
tx.Where("collection_id = ?", query.CollectionId)
|
||||
}
|
||||
})
|
||||
|
||||
abCIds := make([]uint, 0)
|
||||
for _, ab := range res.AddressBooks {
|
||||
abCIds = append(abCIds, ab.CollectionId)
|
||||
}
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
// Create 创建地址簿
|
||||
// @Tags 我的地址簿
|
||||
// @Summary 创建地址簿
|
||||
// @Description 创建地址簿
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book/create [post]
|
||||
// @Security token
|
||||
func (ct *AddressBook) Create(c *gin.Context) {
|
||||
f := &admin.AddressBookForm{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
t := f.ToAddressBook()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
t.UserId = u.Id
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
|
||||
ex := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(t.UserId, t.Id, t.CollectionId)
|
||||
if ex.RowId > 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemExists"))
|
||||
return
|
||||
}
|
||||
|
||||
err := service.AllService.AddressBookService.Create(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// Update 编辑
|
||||
// @Tags 我的地址簿
|
||||
// @Summary 地址簿编辑
|
||||
// @Description 地址簿编辑
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book/update [post]
|
||||
// @Security token
|
||||
func (ct *AddressBook) Update(c *gin.Context) {
|
||||
f := &admin.AddressBookForm{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
if f.RowId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if f.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
|
||||
ex := service.AllService.AddressBookService.InfoByRowId(f.RowId)
|
||||
if ex.RowId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
t := f.ToAddressBook()
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.AddressBookService.UpdateAll(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
// @Tags 我的地址簿
|
||||
// @Summary 地址簿删除
|
||||
// @Description 地址簿删除
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book/delete [post]
|
||||
// @Security token
|
||||
func (ct *AddressBook) Delete(c *gin.Context) {
|
||||
f := &admin.AddressBookForm{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
id := f.RowId
|
||||
errList := global.Validator.ValidVar(c, id, "required,gt=0")
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
ex := service.AllService.AddressBookService.InfoByRowId(f.RowId)
|
||||
if ex.RowId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.AddressBookService.Delete(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
162
http/controller/admin/my/addressBookCollection.go
Normal file
162
http/controller/admin/my/addressBookCollection.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package my
|
||||
|
||||
import (
|
||||
"Gwen/global"
|
||||
"Gwen/http/request/admin"
|
||||
"Gwen/http/response"
|
||||
"Gwen/model"
|
||||
"Gwen/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AddressBookCollection struct {
|
||||
}
|
||||
|
||||
// Create 创建地址簿名称
|
||||
// @Tags 我的地址簿名称
|
||||
// @Summary 创建地址簿名称
|
||||
// @Description 创建地址簿名称
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection/create [post]
|
||||
// @Security token
|
||||
func (abc *AddressBookCollection) Create(c *gin.Context) {
|
||||
f := &model.AddressBookCollection{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
f.UserId = u.Id
|
||||
err := service.AllService.AddressBookService.CreateCollection(f)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// List 列表
|
||||
// @Tags 我的地址簿名称
|
||||
// @Summary 地址簿名称列表
|
||||
// @Description 地址簿名称列表
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "页大小"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection/list [get]
|
||||
// @Security token
|
||||
func (abc *AddressBookCollection) List(c *gin.Context) {
|
||||
query := &admin.AddressBookCollectionQuery{}
|
||||
if err := c.ShouldBindQuery(query); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
query.UserId = int(u.Id)
|
||||
res := service.AllService.AddressBookService.ListCollection(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
tx.Where("user_id = ?", query.UserId)
|
||||
})
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
// Update 编辑
|
||||
// @Tags 我的地址簿名称
|
||||
// @Summary 地址簿名称编辑
|
||||
// @Description 地址簿名称编辑
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection/update [post]
|
||||
// @Security token
|
||||
func (abc *AddressBookCollection) Update(c *gin.Context) {
|
||||
f := &model.AddressBookCollection{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
if f.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if f.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
ex := service.AllService.AddressBookService.CollectionInfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
|
||||
err := service.AllService.AddressBookService.UpdateCollection(f)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
// @Tags 我的地址簿名称
|
||||
// @Summary 地址簿名称删除
|
||||
// @Description 地址簿名称删除
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection/delete [post]
|
||||
// @Security token
|
||||
func (abc *AddressBookCollection) Delete(c *gin.Context) {
|
||||
f := &model.AddressBookCollection{}
|
||||
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
|
||||
}
|
||||
ex := service.AllService.AddressBookService.CollectionInfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.AddressBookService.DeleteCollection(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
}
|
||||
228
http/controller/admin/my/addressBookCollectionRule.go
Normal file
228
http/controller/admin/my/addressBookCollectionRule.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package my
|
||||
|
||||
import (
|
||||
"Gwen/global"
|
||||
"Gwen/http/request/admin"
|
||||
"Gwen/http/response"
|
||||
"Gwen/model"
|
||||
"Gwen/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AddressBookCollectionRule struct {
|
||||
}
|
||||
|
||||
// List 列表
|
||||
// @Tags 我的地址簿规则
|
||||
// @Summary 地址簿规则列表
|
||||
// @Description 地址簿规则列表
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "页大小"
|
||||
// @Param is_my query int false "是否是我的"
|
||||
// @Param user_id query int false "用户id"
|
||||
// @Param collection_id query int false "地址簿集合id"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection_rule/list [get]
|
||||
// @Security token
|
||||
func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
|
||||
query := &admin.AddressBookCollectionRuleQuery{}
|
||||
if err := c.ShouldBindQuery(query); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
query.UserId = int(u.Id)
|
||||
|
||||
res := service.AllService.AddressBookService.ListRules(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
tx.Where("user_id = ?", query.UserId)
|
||||
if query.CollectionId > 0 {
|
||||
tx.Where("collection_id = ?", query.CollectionId)
|
||||
}
|
||||
})
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
// Create 创建地址簿规则
|
||||
// @Tags 我的地址簿规则
|
||||
// @Summary 创建地址簿规则
|
||||
// @Description 创建地址簿规则
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection_rule/create [post]
|
||||
// @Security token
|
||||
func (abcr *AddressBookCollectionRule) Create(c *gin.Context) {
|
||||
f := &model.AddressBookCollectionRule{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
if f.Type != model.ShareAddressBookRuleTypePersonal && f.Type != model.ShareAddressBookRuleTypeGroup {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
//t := f.ToAddressBookCollection()
|
||||
t := f
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
t.UserId = u.Id
|
||||
msg, res := abcr.CheckForm(u, t)
|
||||
if !res {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, msg))
|
||||
return
|
||||
}
|
||||
err := service.AllService.AddressBookService.CreateRule(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.AddressBookCollectionRule) (string, bool) {
|
||||
if t.UserId != u.Id {
|
||||
return "NoAccess", false
|
||||
}
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
return "ParamsError", false
|
||||
}
|
||||
|
||||
//check to_id
|
||||
if t.Type == model.ShareAddressBookRuleTypePersonal {
|
||||
if t.ToId == t.UserId {
|
||||
return "ParamsError", false
|
||||
}
|
||||
tou := service.AllService.UserService.InfoById(t.ToId)
|
||||
if tou.Id == 0 {
|
||||
return "ItemNotFound", false
|
||||
}
|
||||
//非管理员不能分享给非本组织用户
|
||||
if tou.GroupId != u.GroupId {
|
||||
return "NoAccess", false
|
||||
}
|
||||
} else if t.Type == model.ShareAddressBookRuleTypeGroup {
|
||||
//非管理员不能分享给其他组
|
||||
if t.ToId != u.GroupId {
|
||||
return "NoAccess", false
|
||||
}
|
||||
|
||||
tog := service.AllService.GroupService.InfoById(t.ToId)
|
||||
if tog.Id == 0 {
|
||||
return "ItemNotFound", false
|
||||
}
|
||||
} else {
|
||||
return "ParamsError", false
|
||||
}
|
||||
// 重复检查
|
||||
ex := service.AllService.AddressBookService.RulePersonalInfoByToIdAndCid(t.ToId, t.CollectionId)
|
||||
if t.Id == 0 && ex.Id > 0 {
|
||||
return "ItemExists", false
|
||||
}
|
||||
if t.Id > 0 && ex.Id > 0 && t.Id != ex.Id {
|
||||
return "ItemExists", false
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
||||
// Update 编辑
|
||||
// @Tags 我的地址簿规则
|
||||
// @Summary 地址簿规则编辑
|
||||
// @Description 地址簿规则编辑
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection_rule/update [post]
|
||||
// @Security token
|
||||
func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
|
||||
f := &model.AddressBookCollectionRule{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
if f.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
|
||||
ex := service.AllService.AddressBookService.RuleInfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
t := f
|
||||
msg, res := abcr.CheckForm(u, t)
|
||||
if !res {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, msg))
|
||||
return
|
||||
}
|
||||
err := service.AllService.AddressBookService.UpdateRule(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
// @Tags 我的地址簿规则
|
||||
// @Summary 地址簿规则删除
|
||||
// @Description 地址簿规则删除
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/address_book_collection_rule/delete [post]
|
||||
// @Security token
|
||||
func (abcr *AddressBookCollectionRule) Delete(c *gin.Context) {
|
||||
f := &model.AddressBookCollectionRule{}
|
||||
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
|
||||
}
|
||||
ex := service.AllService.AddressBookService.RuleInfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
|
||||
err := service.AllService.AddressBookService.DeleteRule(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
}
|
||||
59
http/controller/admin/my/peer.go
Normal file
59
http/controller/admin/my/peer.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package my
|
||||
|
||||
import (
|
||||
"Gwen/http/request/admin"
|
||||
"Gwen/http/response"
|
||||
"Gwen/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Peer struct {
|
||||
}
|
||||
|
||||
// List 列表
|
||||
// @Tags 我的设备
|
||||
// @Summary 设备列表
|
||||
// @Description 设备列表
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "页大小"
|
||||
// @Param time_ago query int false "时间"
|
||||
// @Param id query string false "ID"
|
||||
// @Param hostname query string false "主机名"
|
||||
// @Param uuids query string false "uuids 用逗号分隔"
|
||||
// @Success 200 {object} response.Response{data=model.PeerList}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/peer/list [get]
|
||||
// @Security token
|
||||
func (ct *Peer) List(c *gin.Context) {
|
||||
query := &admin.PeerQuery{}
|
||||
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.PeerService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
tx.Where("user_id = ?", u.Id)
|
||||
if query.TimeAgo > 0 {
|
||||
lt := time.Now().Unix() - int64(query.TimeAgo)
|
||||
tx.Where("last_online_time < ?", lt)
|
||||
}
|
||||
if query.TimeAgo < 0 {
|
||||
lt := time.Now().Unix() + int64(query.TimeAgo)
|
||||
tx.Where("last_online_time > ?", lt)
|
||||
}
|
||||
if query.Id != "" {
|
||||
tx.Where("id like ?", "%"+query.Id+"%")
|
||||
}
|
||||
if query.Hostname != "" {
|
||||
tx.Where("hostname like ?", "%"+query.Hostname+"%")
|
||||
}
|
||||
if query.Uuids != "" {
|
||||
tx.Where("uuid in (?)", query.Uuids)
|
||||
}
|
||||
})
|
||||
response.Success(c, res)
|
||||
}
|
||||
119
http/controller/admin/my/shareRecord.go
Normal file
119
http/controller/admin/my/shareRecord.go
Normal 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)
|
||||
}
|
||||
176
http/controller/admin/my/tag.go
Normal file
176
http/controller/admin/my/tag.go
Normal file
@@ -0,0 +1,176 @@
|
||||
package my
|
||||
|
||||
import (
|
||||
"Gwen/global"
|
||||
"Gwen/http/request/admin"
|
||||
"Gwen/http/response"
|
||||
"Gwen/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Tag struct{}
|
||||
|
||||
// List 列表
|
||||
// @Tags 我的标签
|
||||
// @Summary 标签列表
|
||||
// @Description 标签列表
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "页大小"
|
||||
// @Param is_my query int false "是否是我的"
|
||||
// @Param user_id query int false "用户id"
|
||||
// @Success 200 {object} response.Response{data=model.TagList}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/tag/list [get]
|
||||
// @Security token
|
||||
func (ct *Tag) List(c *gin.Context) {
|
||||
query := &admin.TagQuery{}
|
||||
if err := c.ShouldBindQuery(query); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
query.UserId = int(u.Id)
|
||||
res := service.AllService.TagService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
|
||||
return txc.Select("id,name")
|
||||
})
|
||||
tx.Where("user_id = ?", query.UserId)
|
||||
if query.CollectionId != nil && *query.CollectionId >= 0 {
|
||||
tx.Where("collection_id = ?", query.CollectionId)
|
||||
}
|
||||
})
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
// Create 创建标签
|
||||
// @Tags 我的标签
|
||||
// @Summary 创建标签
|
||||
// @Description 创建标签
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body admin.TagForm true "标签信息"
|
||||
// @Success 200 {object} response.Response{data=model.Tag}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/tag/create [post]
|
||||
// @Security token
|
||||
func (ct *Tag) Create(c *gin.Context) {
|
||||
f := &admin.TagForm{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
t := f.ToTag()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
t.UserId = u.Id
|
||||
err := service.AllService.TagService.Create(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// Update 编辑
|
||||
// @Tags 我的标签
|
||||
// @Summary 标签编辑
|
||||
// @Description 标签编辑
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body admin.TagForm true "标签信息"
|
||||
// @Success 200 {object} response.Response{data=model.Tag}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/tag/update [post]
|
||||
// @Security token
|
||||
func (ct *Tag) Update(c *gin.Context) {
|
||||
f := &admin.TagForm{}
|
||||
if err := c.ShouldBindJSON(f); err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
errList := global.Validator.ValidStruct(c, f)
|
||||
if len(errList) > 0 {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
if f.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if f.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
ex := service.AllService.TagService.InfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
|
||||
t := f.ToTag()
|
||||
if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.TagService.Update(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
// @Tags 标签
|
||||
// @Summary 标签删除
|
||||
// @Description 标签删除
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body admin.TagForm true "标签信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/my/tag/delete [post]
|
||||
// @Security token
|
||||
func (ct *Tag) Delete(c *gin.Context) {
|
||||
f := &admin.TagForm{}
|
||||
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
|
||||
}
|
||||
ex := service.AllService.TagService.InfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if ex.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.TagService.Delete(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, err.Error())
|
||||
return
|
||||
}
|
||||
105
http/controller/admin/shareRecord.go
Normal file
105
http/controller/admin/shareRecord.go
Normal 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)
|
||||
}
|
||||
@@ -64,9 +64,9 @@ func (ct *Tag) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
t := f.ToTag()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 {
|
||||
t.UserId = u.Id
|
||||
if t.UserId == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
err := service.AllService.TagService.Create(t)
|
||||
if err != nil {
|
||||
@@ -96,10 +96,6 @@ func (ct *Tag) List(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||
return
|
||||
}
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
|
||||
query.UserId = int(u.Id)
|
||||
}
|
||||
res := service.AllService.TagService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
|
||||
return txc.Select("id,name")
|
||||
@@ -140,12 +136,12 @@ func (ct *Tag) Update(c *gin.Context) {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||
return
|
||||
}
|
||||
t := f.ToTag()
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
ex := service.AllService.TagService.InfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
t := f.ToTag()
|
||||
err := service.AllService.TagService.Update(t)
|
||||
if err != nil {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||
@@ -177,20 +173,15 @@ func (ct *Tag) Delete(c *gin.Context) {
|
||||
response.Fail(c, 101, errList[0])
|
||||
return
|
||||
}
|
||||
t := service.AllService.TagService.InfoById(f.Id)
|
||||
u := service.AllService.UserService.CurUser(c)
|
||||
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||
ex := service.AllService.TagService.InfoById(f.Id)
|
||||
if ex.Id == 0 {
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
return
|
||||
}
|
||||
if u.Id > 0 {
|
||||
err := service.AllService.TagService.Delete(t)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, err.Error())
|
||||
err := service.AllService.TagService.Delete(ex)
|
||||
if err == nil {
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||
response.Fail(c, 101, err.Error())
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
@@ -295,51 +294,6 @@ func (ct *User) MyOauth(c *gin.Context) {
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
// MyPeer 列表
|
||||
// @Tags 设备
|
||||
// @Summary 我的设备列表
|
||||
// @Description 我的设备列表
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "页大小"
|
||||
// @Param time_ago query int false "时间"
|
||||
// @Param id query string false "ID"
|
||||
// @Param hostname query string false "主机名"
|
||||
// @Param uuids query string false "uuids 用逗号分隔"
|
||||
// @Success 200 {object} response.Response{data=model.PeerList}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /admin/user/myPeer [get]
|
||||
// @Security token
|
||||
func (ct *User) MyPeer(c *gin.Context) {
|
||||
query := &admin.PeerQuery{}
|
||||
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.PeerService.ListFilterByUserId(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||
if query.TimeAgo > 0 {
|
||||
lt := time.Now().Unix() - int64(query.TimeAgo)
|
||||
tx.Where("last_online_time < ?", lt)
|
||||
}
|
||||
if query.TimeAgo < 0 {
|
||||
lt := time.Now().Unix() + int64(query.TimeAgo)
|
||||
tx.Where("last_online_time > ?", lt)
|
||||
}
|
||||
if query.Id != "" {
|
||||
tx.Where("id like ?", "%"+query.Id+"%")
|
||||
}
|
||||
if query.Hostname != "" {
|
||||
tx.Where("hostname like ?", "%"+query.Hostname+"%")
|
||||
}
|
||||
if query.Uuids != "" {
|
||||
tx.Where("uuid in (?)", query.Uuids)
|
||||
}
|
||||
}, u.Id)
|
||||
response.Success(c, res)
|
||||
}
|
||||
|
||||
// groupUsers
|
||||
func (ct *User) GroupUsers(c *gin.Context) {
|
||||
q := &admin.GroupUsersQuery{}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ type Login struct {
|
||||
Username string `json:"username" validate:"required" label:"用户名"`
|
||||
Password string `json:"password,omitempty" validate:"required" label:"密码"`
|
||||
Platform string `json:"platform" label:"平台"`
|
||||
Captcha string `json:"captcha,omitempty" label:"验证码"`
|
||||
}
|
||||
|
||||
type LoginLogQuery struct {
|
||||
|
||||
15
http/request/admin/shareRecord.go
Normal file
15
http/request/admin/shareRecord.go
Normal 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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,7 +2,9 @@ package router
|
||||
|
||||
import (
|
||||
_ "Gwen/docs/admin"
|
||||
"Gwen/global"
|
||||
"Gwen/http/controller/admin"
|
||||
"Gwen/http/controller/admin/my"
|
||||
"Gwen/http/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
@@ -13,7 +15,9 @@ func Init(g *gin.Engine) {
|
||||
|
||||
//swagger
|
||||
//g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
g.GET("/admin/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("admin")))
|
||||
if global.Config.App.ShowSwagger == 1 {
|
||||
g.GET("/admin/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("admin")))
|
||||
}
|
||||
|
||||
adg := g.Group("/api/admin")
|
||||
LoginBind(adg)
|
||||
@@ -34,17 +38,21 @@ 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"))
|
||||
}
|
||||
func LoginBind(rg *gin.RouterGroup) {
|
||||
cont := &admin.Login{}
|
||||
rg.POST("/login", cont.Login)
|
||||
rg.GET("/captcha", cont.Captcha)
|
||||
rg.POST("/logout", cont.Logout)
|
||||
rg.GET("/login-options", cont.LoginOptions)
|
||||
rg.POST("/oidc/auth", cont.OidcAuth)
|
||||
@@ -58,7 +66,7 @@ func UserBind(rg *gin.RouterGroup) {
|
||||
aR.GET("/current", cont.Current)
|
||||
aR.POST("/changeCurPwd", cont.ChangeCurPwd)
|
||||
aR.POST("/myOauth", cont.MyOauth)
|
||||
aR.GET("/myPeer", cont.MyPeer)
|
||||
//aR.GET("/myPeer", cont.MyPeer)
|
||||
aR.POST("/groupUsers", cont.GroupUsers)
|
||||
}
|
||||
aRP := rg.Group("/user").Use(middleware.AdminPrivilege())
|
||||
@@ -86,7 +94,7 @@ func GroupBind(rg *gin.RouterGroup) {
|
||||
}
|
||||
|
||||
func TagBind(rg *gin.RouterGroup) {
|
||||
aR := rg.Group("/tag")
|
||||
aR := rg.Group("/tag").Use(middleware.AdminPrivilege())
|
||||
{
|
||||
cont := &admin.Tag{}
|
||||
aR.GET("/list", cont.List)
|
||||
@@ -101,15 +109,17 @@ func AddressBookBind(rg *gin.RouterGroup) {
|
||||
aR := rg.Group("/address_book")
|
||||
{
|
||||
cont := &admin.AddressBook{}
|
||||
aR.GET("/list", cont.List)
|
||||
aR.GET("/detail/:id", cont.Detail)
|
||||
aR.POST("/create", cont.Create)
|
||||
aR.POST("/update", cont.Update)
|
||||
aR.POST("/delete", cont.Delete)
|
||||
aR.POST("/shareByWebClient", cont.ShareByWebClient)
|
||||
|
||||
arp := aR.Use(middleware.AdminPrivilege())
|
||||
arp.GET("/list", cont.List)
|
||||
//arp.GET("/detail/:id", cont.Detail)
|
||||
arp.POST("/create", cont.Create)
|
||||
arp.POST("/update", cont.Update)
|
||||
arp.POST("/delete", cont.Delete)
|
||||
arp.POST("/batchCreate", cont.BatchCreate)
|
||||
arp.POST("/batchCreateFromPeers", cont.BatchCreateFromPeers)
|
||||
|
||||
}
|
||||
}
|
||||
func PeerBind(rg *gin.RouterGroup) {
|
||||
@@ -168,7 +178,7 @@ func AuditBind(rg *gin.RouterGroup) {
|
||||
afR.POST("/batchDelete", cont.BatchFileDelete)
|
||||
}
|
||||
func AddressBookCollectionBind(rg *gin.RouterGroup) {
|
||||
aR := rg.Group("/address_book_collection")
|
||||
aR := rg.Group("/address_book_collection").Use(middleware.AdminPrivilege())
|
||||
{
|
||||
cont := &admin.AddressBookCollection{}
|
||||
aR.GET("/list", cont.List)
|
||||
@@ -180,7 +190,7 @@ func AddressBookCollectionBind(rg *gin.RouterGroup) {
|
||||
|
||||
}
|
||||
func AddressBookCollectionRuleBind(rg *gin.RouterGroup) {
|
||||
aR := rg.Group("/address_book_collection_rule")
|
||||
aR := rg.Group("/address_book_collection_rule").Use(middleware.AdminPrivilege())
|
||||
{
|
||||
cont := &admin.AddressBookCollectionRule{}
|
||||
aR.GET("/list", cont.List)
|
||||
@@ -195,6 +205,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 +227,62 @@ func FileBind(rg *gin.RouterGroup) {
|
||||
aR.POST("/upload", cont.Upload)
|
||||
}
|
||||
}*/
|
||||
|
||||
func MyBind(rg *gin.RouterGroup) {
|
||||
{
|
||||
cont := &my.ShareRecord{}
|
||||
rg.GET("/my/share_record/list", cont.List)
|
||||
rg.POST("/my/share_record/delete", cont.Delete)
|
||||
rg.POST("/my/share_record/batchDelete", cont.BatchDelete)
|
||||
}
|
||||
|
||||
{
|
||||
cont := &my.AddressBook{}
|
||||
rg.GET("/my/address_book/list", cont.List)
|
||||
rg.POST("/my/address_book/create", cont.Create)
|
||||
rg.POST("/my/address_book/update", cont.Update)
|
||||
rg.POST("/my/address_book/delete", cont.Delete)
|
||||
rg.POST("/my/address_book/batchCreateFromPeers", cont.BatchCreateFromPeers)
|
||||
rg.POST("/my/address_book/batchUpdateTags", cont.BatchUpdateTags)
|
||||
}
|
||||
|
||||
{
|
||||
cont := &my.Tag{}
|
||||
rg.GET("/my/tag/list", cont.List)
|
||||
rg.POST("/my/tag/create", cont.Create)
|
||||
rg.POST("/my/tag/update", cont.Update)
|
||||
rg.POST("/my/tag/delete", cont.Delete)
|
||||
}
|
||||
|
||||
{
|
||||
cont := &my.AddressBookCollection{}
|
||||
rg.GET("/my/address_book_collection/list", cont.List)
|
||||
rg.POST("/my/address_book_collection/create", cont.Create)
|
||||
rg.POST("/my/address_book_collection/update", cont.Update)
|
||||
rg.POST("/my/address_book_collection/delete", cont.Delete)
|
||||
}
|
||||
|
||||
{
|
||||
cont := &my.AddressBookCollectionRule{}
|
||||
rg.GET("/my/address_book_collection_rule/list", cont.List)
|
||||
rg.POST("/my/address_book_collection_rule/create", cont.Create)
|
||||
rg.POST("/my/address_book_collection_rule/update", cont.Update)
|
||||
rg.POST("/my/address_book_collection_rule/delete", cont.Delete)
|
||||
}
|
||||
{
|
||||
cont := &my.Peer{}
|
||||
rg.GET("/my/peer/list", cont.List)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ func ApiInit(g *gin.Engine) {
|
||||
|
||||
//g.Use(middleware.Cors())
|
||||
//swagger
|
||||
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("api")))
|
||||
if global.Config.App.ShowSwagger == 1 {
|
||||
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("api")))
|
||||
}
|
||||
|
||||
frg := g.Group("/api")
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -123,3 +123,13 @@ other = "Share Group"
|
||||
description = "Register closed."
|
||||
one = "Register closed."
|
||||
other = "Register closed."
|
||||
|
||||
[CaptchaRequired]
|
||||
description = "Captcha required."
|
||||
one = "Captcha required."
|
||||
other = "Captcha required."
|
||||
|
||||
[CaptchaError]
|
||||
description = "Captcha error."
|
||||
one = "Captcha error."
|
||||
other = "Captcha error."
|
||||
|
||||
@@ -132,3 +132,13 @@ other = "Grupo compartido"
|
||||
description = "Register closed."
|
||||
one = "Registro cerrado."
|
||||
other = "Registro cerrado."
|
||||
|
||||
[CaptchaRequired]
|
||||
description = "Captcha required."
|
||||
one = "Captcha requerido."
|
||||
other = "Captcha requerido."
|
||||
|
||||
[CaptchaError]
|
||||
description = "Captcha error."
|
||||
one = "Error de captcha."
|
||||
other = "Error de captcha."
|
||||
@@ -125,4 +125,14 @@ other = "공유 그룹"
|
||||
[RegisterClosed]
|
||||
description = "Register closed."
|
||||
one = "가입이 종료되었습니다."
|
||||
other = "가입이 종료되었습니다."
|
||||
other = "가입이 종료되었습니다."
|
||||
|
||||
[CaptchaRequired]
|
||||
description = "Captcha required."
|
||||
one = "Captcha가 필요합니다."
|
||||
other = "Captcha가 필요합니다."
|
||||
|
||||
[CaptchaError]
|
||||
description = "Captcha error."
|
||||
one = "Captcha 오류."
|
||||
other = "Captcha 오류."
|
||||
@@ -131,4 +131,14 @@ other = "Общая группа"
|
||||
[RegisterClosed]
|
||||
description = "Register closed."
|
||||
one = "Регистрация закрыта."
|
||||
other = "Регистрация закрыта."
|
||||
other = "Регистрация закрыта."
|
||||
|
||||
[CaptchaRequired]
|
||||
description = "Captcha required."
|
||||
one = "Требуется капча."
|
||||
other = "Требуется капча."
|
||||
|
||||
[CaptchaError]
|
||||
description = "Captcha error."
|
||||
one = "Ошибка капчи."
|
||||
other = "Ошибка капчи."
|
||||
@@ -124,4 +124,14 @@ other = "共享组"
|
||||
[RegisterClosed]
|
||||
description = "Register closed."
|
||||
one = "注册已关闭。"
|
||||
other = "注册已关闭。"
|
||||
other = "注册已关闭。"
|
||||
|
||||
[CaptchaRequired]
|
||||
description = "Captcha required."
|
||||
one = "需要验证码。"
|
||||
other = "需要验证码。"
|
||||
|
||||
[CaptchaError]
|
||||
description = "Captcha error."
|
||||
one = "验证码错误。"
|
||||
other = "验证码错误。"
|
||||
396
resources/web2/js/dist/index.js
vendored
396
resources/web2/js/dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
40
resources/web2/js/dist/lang.js
vendored
40
resources/web2/js/dist/lang.js
vendored
@@ -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
108026
resources/web2/main.dart.js
vendored
File diff suppressed because one or more lines are too long
@@ -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
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ type Service struct {
|
||||
*OauthService
|
||||
*LoginLogService
|
||||
*AuditService
|
||||
*ShareRecordService
|
||||
}
|
||||
|
||||
func New() *Service {
|
||||
|
||||
49
service/shareRecord.go
Normal file
49
service/shareRecord.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user