Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a876078a9c | ||
|
|
495f2ae3c6 | ||
|
|
4e6d11baf0 | ||
|
|
a951b982b3 | ||
|
|
a33be66504 | ||
|
|
f41b9d5887 | ||
|
|
3c608463e6 | ||
|
|
eeffbe124a | ||
|
|
d7f2d54faa | ||
|
|
7db4b03634 | ||
|
|
77760a681a | ||
|
|
f9c1447ceb | ||
|
|
fb749c1902 | ||
|
|
240c44aa07 | ||
|
|
92cd8642c8 | ||
|
|
89d90cf919 | ||
|
|
920c6b6d8b | ||
|
|
1dd4df3a1c | ||
|
|
c7d44cc253 | ||
|
|
5082ab1893 | ||
|
|
e8b2425222 | ||
|
|
09d12cefd8 | ||
|
|
5f1166965d | ||
|
|
0dbab182e9 | ||
|
|
512f3f99fd | ||
|
|
6fb4fad705 | ||
|
|
fa92529e9b | ||
|
|
d6c6051a6c | ||
|
|
ce063bd3ac | ||
|
|
4468894dfb | ||
|
|
8b00b919ad | ||
|
|
64f4a6dfac | ||
|
|
6faa5153b6 | ||
|
|
a771b1e9b0 | ||
|
|
7750f9c54d | ||
|
|
b2d24ee67b | ||
|
|
589a2a5123 | ||
|
|
184d3d357d | ||
|
|
50b3d85270 | ||
|
|
09fdd34ba3 | ||
|
|
bba10261c5 | ||
|
|
46bfe54097 | ||
|
|
503e7a307e | ||
|
|
821b0a6faf | ||
|
|
d60fdff179 | ||
|
|
fdd841e82a | ||
|
|
2d6f0a116a | ||
|
|
bd13fe4ef4 | ||
|
|
6e1b208464 | ||
|
|
76433a409e | ||
|
|
9b4fa679c2 | ||
|
|
c2ae95c4cc | ||
|
|
b2b7f60fd5 | ||
|
|
a465888b31 | ||
|
|
d368bdc84c | ||
|
|
cdc1150505 | ||
|
|
32d525c53c | ||
|
|
a89b40c607 | ||
|
|
b6bd9150d9 | ||
|
|
96e3e3bc86 | ||
|
|
41377f41bb | ||
|
|
fb744f81e2 | ||
|
|
750c3bcbcd | ||
|
|
d4015d7284 | ||
|
|
a9bf3fda73 | ||
|
|
7f467a4814 | ||
|
|
9f10b5e983 | ||
|
|
5291270e6a | ||
|
|
56bba381d8 | ||
|
|
2ff276b162 | ||
|
|
d77191ce0f | ||
|
|
f99803aef4 | ||
|
|
e09fa17013 | ||
|
|
c7e69aa8a5 | ||
|
|
9548068283 | ||
|
|
09958c78f3 | ||
|
|
aced098982 | ||
|
|
7862a34760 | ||
|
|
1384d28cac | ||
|
|
24b7338153 | ||
|
|
30d254eaef | ||
|
|
bb8a936ade | ||
|
|
61044fd30b | ||
|
|
22a4546d0f | ||
|
|
07450416ed | ||
|
|
0d6db0d2a1 | ||
|
|
ab30b3407b | ||
|
|
7a4c735803 | ||
|
|
654c764019 | ||
|
|
7101139250 | ||
|
|
793614841a | ||
|
|
94f2ac5b2a | ||
|
|
d4d39eecaa | ||
|
|
8af01c859c | ||
|
|
3af92d03e8 | ||
|
|
f17d891302 | ||
|
|
51623436b0 | ||
|
|
1b7c7eef8f | ||
|
|
15e4c7e522 | ||
|
|
120ab132a9 | ||
|
|
0b52e8faa8 | ||
|
|
60eaaf390a | ||
|
|
9101badb1c | ||
|
|
7082111b34 | ||
|
|
a156f2681e | ||
|
|
7cb823c957 | ||
|
|
817f612224 | ||
|
|
1cbaf9d6bc | ||
|
|
d353f9837f | ||
|
|
14beef72fc | ||
|
|
91a33fe7f6 | ||
|
|
7ad7a0ff41 | ||
|
|
d646469f71 | ||
|
|
4f616ffff1 | ||
|
|
64400fba61 | ||
|
|
fc15e8c63d | ||
|
|
cbba1e5317 | ||
|
|
75b997dcc4 | ||
|
|
853063c59b | ||
|
|
5c65edb8fa | ||
|
|
7707cc116f | ||
|
|
737fe749de | ||
|
|
b9c6f17e3f | ||
|
|
af6a340003 | ||
|
|
8ba3bee944 | ||
|
|
153c3566b6 | ||
|
|
97a4753f4f | ||
|
|
74c3899b55 | ||
|
|
273ac6d1a8 | ||
|
|
5edbb39a63 | ||
|
|
0c974c4113 | ||
|
|
46657a525d | ||
|
|
b36aa6f917 | ||
|
|
cddb0ebef9 | ||
|
|
788c4e3531 | ||
|
|
47f9ad8274 | ||
|
|
855beb7fa9 | ||
|
|
f57816b1b0 | ||
|
|
ff08fefc30 | ||
|
|
f792ab9055 | ||
|
|
63af103a4e | ||
|
|
0a36d44cec | ||
|
|
a1f4e1de84 | ||
|
|
05b20d47db | ||
|
|
6b746f13d1 | ||
|
|
e838d5bcd2 | ||
|
|
0dcc21260e | ||
|
|
3c30ad145c | ||
|
|
06b0a8e873 | ||
|
|
b7de2ccadd | ||
|
|
b52c5cfca1 | ||
|
|
fe910c37cf | ||
|
|
337ef330eb | ||
|
|
ffa47177aa | ||
|
|
46a76853c3 | ||
|
|
2cd7dfb2b3 | ||
|
|
fee2808bca | ||
|
|
49e5eb186a | ||
|
|
dee2865466 | ||
|
|
eb340b2615 | ||
|
|
e714549a95 | ||
|
|
a1367bcd3d | ||
|
|
642351dafd | ||
|
|
90b9b5adba | ||
|
|
5bf4bbe45f | ||
|
|
036f928fa3 | ||
|
|
94e7b31fb6 | ||
|
|
be4742382d | ||
|
|
70d2f1a055 | ||
|
|
877fe50049 | ||
|
|
7d505705ee | ||
|
|
38f81a03b5 | ||
|
|
d549d23819 | ||
|
|
934675e0f0 | ||
|
|
2be397aa38 | ||
|
|
a0a422ed45 | ||
|
|
fcce10c695 | ||
|
|
30eb14702f | ||
|
|
3679fcc874 | ||
|
|
d085b4e3c2 | ||
|
|
dc8fcdf214 | ||
|
|
8bab23b65b | ||
|
|
f64022e411 | ||
|
|
2d37302cf9 | ||
|
|
1a1856257d | ||
|
|
24f570b64f | ||
|
|
6322177b71 | ||
|
|
d2390d1cb3 | ||
|
|
6fe6f6b708 | ||
|
|
a656f4fec3 | ||
|
|
399c32da7d | ||
|
|
62167836dc | ||
|
|
caef3897a0 | ||
|
|
5ef6810e3f | ||
|
|
ae2079f583 | ||
|
|
aa65382a0f | ||
|
|
18c61a2bfc | ||
|
|
7cc1a8a58a | ||
|
|
cf9feac702 | ||
|
|
a963cd0209 | ||
|
|
6a5408f9b8 | ||
|
|
9aad62d1e4 | ||
|
|
867eab40f8 | ||
|
|
eb5c7efc4c | ||
|
|
857abc16e7 | ||
|
|
28b9866c42 | ||
|
|
a27deb0a41 | ||
|
|
8e026de20b | ||
|
|
718ecc2372 | ||
|
|
56d46722f4 | ||
|
|
b6463cd715 | ||
|
|
bd3ae0cbfe | ||
|
|
83c3aa894f | ||
|
|
1b88d26fea | ||
|
|
588287fdb4 | ||
|
|
688e544b07 | ||
|
|
3e3f812e83 | ||
|
|
b551c7abe4 | ||
|
|
6d1e7a4c05 | ||
|
|
3341a4bc8e | ||
|
|
1c84980d36 | ||
|
|
833b25881d | ||
|
|
9dbf58903c | ||
|
|
ad007f0d91 | ||
|
|
4b06973a52 | ||
|
|
159a67f15d | ||
|
|
7c03b9953b | ||
|
|
f90987de8d | ||
|
|
70e4ff7820 | ||
|
|
a99356f54b | ||
|
|
c5bc9534cc | ||
|
|
a40733424f | ||
|
|
a937efc60e | ||
|
|
6adb0e8415 | ||
|
|
ff9ffb2f12 | ||
|
|
9be4f472ae | ||
|
|
8581d74b08 | ||
|
|
dafe9bd6b6 | ||
|
|
3ae5772360 | ||
|
|
4628dbccfb | ||
|
|
572b1d4c14 | ||
|
|
bdb70e9859 | ||
|
|
38bda17271 | ||
|
|
455e1d2e5b | ||
|
|
89cd724bab | ||
|
|
b9109b4d0e | ||
|
|
945958f552 | ||
|
|
78eb0d5c06 | ||
|
|
bc6eae711e | ||
|
|
f0a4bf6164 | ||
|
|
fc3b5e3ac3 | ||
|
|
f7235ac847 | ||
|
|
231f4ddb7f | ||
|
|
3cad3994cb | ||
|
|
8c97cc8686 | ||
|
|
7ae976ee5d | ||
|
|
e91b53eb32 | ||
|
|
90311536a7 | ||
|
|
e951b7f2f9 | ||
|
|
e0f94b62cf | ||
|
|
8cb701ec85 | ||
|
|
9afd11e3b8 | ||
|
|
a1d495f2db | ||
|
|
652fa93910 | ||
|
|
ef414855f0 | ||
|
|
76cf35cdf0 | ||
|
|
9d7aa05032 | ||
|
|
62a22c697d | ||
|
|
be497a5aa7 | ||
|
|
fc3e16bc63 | ||
|
|
df35912461 | ||
|
|
0ddc66a854 | ||
|
|
716d557d66 | ||
|
|
f9edcb9d47 | ||
|
|
d4623c5bc9 | ||
|
|
02ba4a3330 | ||
|
|
a72d4eaf78 | ||
|
|
4d3abb2dc0 | ||
|
|
ad6a8d1f7a | ||
|
|
a5c8c2ac97 | ||
|
|
1237004cb1 | ||
|
|
c2bcd17df7 | ||
|
|
bb49cbdd50 | ||
|
|
6ad770a824 | ||
|
|
593eeb3ac3 | ||
|
|
6a7be3ef84 |
@@ -1,61 +0,0 @@
|
|||||||
name: Build & Push Docker Image
|
|
||||||
|
|
||||||
# Builds the Docker image and publishes it to the Gitea container registry
|
|
||||||
# at git.hackner.dev/thomas/rustdesk-api.
|
|
||||||
#
|
|
||||||
# Requires a running Gitea Actions runner (act_runner) and two repo secrets
|
|
||||||
# (Settings -> Actions -> Secrets):
|
|
||||||
# REGISTRY_USER - Gitea username (e.g. thomas)
|
|
||||||
# REGISTRY_PASSWORD - a Gitea access token with "write:package" scope
|
|
||||||
#
|
|
||||||
# (Alternatively the built-in ${{ secrets.GITHUB_TOKEN }} can be used with
|
|
||||||
# username ${{ gitea.actor }} if your Gitea grants it package write access.)
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
tags:
|
|
||||||
- 'v*.*.*'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: git.hackner.dev
|
|
||||||
IMAGE_NAME: ${{ github.repository }} # -> thomas/rustdesk-api
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
docker:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Log in to the Gitea container registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ secrets.REGISTRY_USER }}
|
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Extract metadata (tags, labels)
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=raw,value=latest,enable={{is_default_branch}}
|
|
||||||
|
|
||||||
- name: Build and push image
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile.dev
|
|
||||||
push: true
|
|
||||||
build-args: |
|
|
||||||
GO_VERSION=1.23
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
@@ -0,0 +1,433 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
BASE_IMAGE_NAMESPACE:
|
||||||
|
description: 'Base image namespace (Default: Your Github username)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
DOCKERHUB_IMAGE_NAMESPACE:
|
||||||
|
description: 'Docker Hub image namespace (Default: Your Github username)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
GHCR_IMAGE_NAMESPACE:
|
||||||
|
description: 'GitHub Container Registry image namespace (Default: Your Github username)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
SKIP_DOCKER_HUB:
|
||||||
|
description: 'Set to true to skip pushing to Docker Hub (default: false)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
SKIP_GHCR:
|
||||||
|
description: 'Set to true to skip pushing to GHCR (default: false)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
WEBCLIENT_SOURCE_LOCATION:
|
||||||
|
description: 'Web Client API Repository'
|
||||||
|
required: true
|
||||||
|
default: 'https://github.com/lejianwen/rustdesk-api-web'
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*' # 当推送带有版本号的 tag(例如 v1.0.0)时触发工作流
|
||||||
|
- 'test*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
LATEST_TAG: latest
|
||||||
|
WEBCLIENT_SOURCE_LOCATION: ${{ github.event.inputs.WEBCLIENT_SOURCE_LOCATION || 'https://github.com/lejianwen/rustdesk-api-web' }}
|
||||||
|
BASE_IMAGE_NAMESPACE: ${{ github.event.inputs.BASE_IMAGE_NAMESPACE || github.actor }}
|
||||||
|
DOCKERHUB_IMAGE_NAMESPACE: ${{ github.event.inputs.DOCKERHUB_IMAGE_NAMESPACE || github.actor }}
|
||||||
|
GHCR_IMAGE_NAMESPACE: ${{ github.event.inputs.GHCR_IMAGE_NAMESPACE || github.actor }}
|
||||||
|
SKIP_DOCKER_HUB: ${{ github.event.inputs.SKIP_DOCKER_HUB || 'false' }}
|
||||||
|
SKIP_GHCR: ${{ github.event.inputs.SKIP_GHCR || 'false' }}
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { platform: "amd64", goos: "linux", file_ext: "tar.gz" }
|
||||||
|
- { platform: "arm64", goos: "linux", file_ext: "tar.gz" }
|
||||||
|
- { platform: "armv7l", goos: "linux", file_ext: "tar.gz" }
|
||||||
|
- { platform: "amd64", goos: "windows", file_ext: "zip" }
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: lejianwen/rustdesk-api-web
|
||||||
|
path: rustdesk-api-web
|
||||||
|
ref: master
|
||||||
|
|
||||||
|
- name: Set up Go environment
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: '1.22' # 选择 Go 版本
|
||||||
|
|
||||||
|
- name: Set up npm
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: build rustdesk-api-web
|
||||||
|
working-directory: rustdesk-api-web
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
mkdir -p ../resources/admin/
|
||||||
|
cp -ar dist/* ../resources/admin/
|
||||||
|
|
||||||
|
- name: tidy
|
||||||
|
run: go mod tidy
|
||||||
|
|
||||||
|
- name: swag
|
||||||
|
run: |
|
||||||
|
go install github.com/swaggo/swag/cmd/swag@latest
|
||||||
|
swag init -g cmd/apimain.go --output docs/api --instanceName api --exclude http/controller/admin
|
||||||
|
swag init -g cmd/apimain.go --output docs/admin --instanceName admin --exclude http/controller/api
|
||||||
|
|
||||||
|
- name: Build for ${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
run: |
|
||||||
|
mkdir release -p
|
||||||
|
cp -ar resources release/
|
||||||
|
cp -ar docs release/
|
||||||
|
cp -ar conf release/
|
||||||
|
mkdir -p release/data
|
||||||
|
mkdir -p release/runtime
|
||||||
|
if [ "${{ matrix.job.goos }}" = "windows" ]; then
|
||||||
|
sudo apt-get install gcc-mingw-w64-x86-64 zip -y
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain.exe ./cmd/apimain.go
|
||||||
|
echo @echo off > release/start.bat
|
||||||
|
echo cmd /c \"%~dp0apimain.exe\" >> release/start.bat
|
||||||
|
zip -r ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
|
||||||
|
else
|
||||||
|
if [ "${{ matrix.job.platform }}" = "arm64" ]; then
|
||||||
|
wget https://musl.cc/aarch64-linux-musl-cross.tgz
|
||||||
|
tar -xf aarch64-linux-musl-cross.tgz
|
||||||
|
export PATH=$PATH:$PWD/aarch64-linux-musl-cross/bin
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=aarch64-linux-musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
|
||||||
|
elif [ "${{ matrix.job.platform }}" = "armv7l" ]; then
|
||||||
|
wget https://musl.cc/armv7l-linux-musleabihf-cross.tgz
|
||||||
|
tar -xf armv7l-linux-musleabihf-cross.tgz
|
||||||
|
export PATH=$PATH:$PWD/armv7l-linux-musleabihf-cross/bin
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=arm GOARM=7 CC=armv7l-linux-musleabihf-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
|
||||||
|
else
|
||||||
|
sudo apt-get install musl musl-dev musl-tools -y
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
|
||||||
|
fi
|
||||||
|
tar -czf ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
path: |
|
||||||
|
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
|
||||||
|
|
||||||
|
- name: Upload to GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Generate Changelog
|
||||||
|
run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
|
||||||
|
deb-package:
|
||||||
|
name: debian package - ${{ matrix.job.platform }}
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { platform: "amd64", goos: "linux", debian_platform: "amd64", crossbuild_package: ""}
|
||||||
|
- { platform: "arm64", goos: "linux", debian_platform: "arm64", crossbuild_package: "crossbuild-essential-arm64" }
|
||||||
|
- { platform: "armv7l", goos: "linux", debian_platform: "armhf", crossbuild_package: "crossbuild-essential-armhf" }
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Create packaging env
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
DEBIAN_FRONTEND=noninteractive sudo apt install -y devscripts build-essential debhelper pkg-config ${{ matrix.job.crossbuild_package }}
|
||||||
|
mkdir -p debian-build/${{ matrix.job.platform }}/bin
|
||||||
|
|
||||||
|
- name: Get tag version
|
||||||
|
id: get_tag
|
||||||
|
run: |
|
||||||
|
TAG_VERSION="${GITHUB_REF##*/}"
|
||||||
|
VERSION="${TAG_VERSION#v}"
|
||||||
|
echo "TAG_VERSION=$TAG_VERSION" >> $GITHUB_ENV
|
||||||
|
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Update changelog
|
||||||
|
run: |
|
||||||
|
DATE=$(date -R)
|
||||||
|
sed -i "1i rustdesk-api-server (${VERSION}) stable; urgency=medium\n\n * Automatically generated release for version ${VERSION}.\n\n -- GitHub Actions <actions@github.com> ${DATE}\n" debian/changelog
|
||||||
|
|
||||||
|
- name: Download binaries
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Unzip binaries
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ matrix.job.platform }}
|
||||||
|
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
|
||||||
|
|
||||||
|
- name: Build package for ${{ matrix.job.platform }} arch
|
||||||
|
run: |
|
||||||
|
mv ${{ matrix.job.platform }}/release/apimain debian-build/${{ matrix.job.platform }}/bin/rustdesk-api
|
||||||
|
chmod -v a+x debian-build/${{ matrix.job.platform }}/bin/*
|
||||||
|
mkdir -p data
|
||||||
|
cp -vr debian systemd conf data resources runtime debian-build/${{ matrix.job.platform }}/
|
||||||
|
cat debian/control.tpl | sed 's/{{ ARCH }}/${{ matrix.job.debian_platform }}/' > debian-build/${{ matrix.job.platform }}/debian/control
|
||||||
|
cd debian-build/${{ matrix.job.platform }}/
|
||||||
|
debuild -i -us -uc -b -a${{ matrix.job.debian_platform}}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.debian_platform }}
|
||||||
|
path: |
|
||||||
|
debian-build/*.deb
|
||||||
|
|
||||||
|
- name: Create Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
debian-build/rustdesk-api-server_*_${{ matrix.job.debian_platform }}.deb
|
||||||
|
|
||||||
|
docker:
|
||||||
|
name: Push Docker Image
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { platform: "amd64", goos: "linux", docker_platform: "linux/amd64" }
|
||||||
|
- { platform: "arm64", goos: "linux", docker_platform: "linux/arm64" }
|
||||||
|
- { platform: "armv7l", goos: "linux", docker_platform: "linux/arm/v7" }
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if SKIP_DOCKER_HUB is false
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
|
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "TAG=latest" >> $GITHUB_ENV # Default to 'latest' if not a tag
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api
|
||||||
|
|
||||||
|
- name: Download binaries
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
path: ./
|
||||||
|
|
||||||
|
- name: Unzip binaries
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ matrix.job.platform }}
|
||||||
|
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image to Docker Hub ${{ matrix.job.platform }}
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only run this step if SKIP_DOCKER_HUB is false
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: "."
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: ${{ matrix.job.docker_platform }}
|
||||||
|
push: true
|
||||||
|
provenance: false
|
||||||
|
build-args: |
|
||||||
|
BUILDARCH=${{ matrix.job.platform }}
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.LATEST_TAG }}-${{ matrix.job.platform }},
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Build and push Docker Full S6 image to Docker Hub ${{ matrix.job.platform }}
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only run this step if SKIP_DOCKER_HUB is false
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: "."
|
||||||
|
file: ./Dockerfile_full_s6
|
||||||
|
platforms: ${{ matrix.job.docker_platform }}
|
||||||
|
push: true
|
||||||
|
provenance: false
|
||||||
|
build-args: |
|
||||||
|
BUILDARCH=${{ matrix.job.platform }}
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-${{ matrix.job.platform }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image to GHCR ${{ matrix.job.platform }}
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only run this step if SKIP_GHCR is false
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: "."
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: ${{ matrix.job.docker_platform }}
|
||||||
|
push: true
|
||||||
|
provenance: false
|
||||||
|
build-args: |
|
||||||
|
BUILDARCH=${{ matrix.job.platform }}
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.LATEST_TAG }}-${{ matrix.job.platform }},
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Build and push Docker Full S6 image to GHCR ${{ matrix.job.platform }}
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only run this step if SKIP_GHCR is false
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: "."
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: ${{ matrix.job.docker_platform }}
|
||||||
|
push: true
|
||||||
|
provenance: false
|
||||||
|
build-args: |
|
||||||
|
BUILDARCH=${{ matrix.job.platform }}
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-${{ matrix.job.platform }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
#
|
||||||
|
docker-manifest:
|
||||||
|
name: Push Docker Manifest
|
||||||
|
needs: docker
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
|
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "TAG=latest" >> $GITHUB_ENV # Default to 'latest' if not a tag
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if Docker Hub push is enabled
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Create and push manifest Docker Hub (:version)
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
|
||||||
|
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
|
||||||
|
push: true
|
||||||
|
|
||||||
|
- name: Create and push manifest GHCR (:version)
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
|
||||||
|
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
|
||||||
|
push: true
|
||||||
|
amend: true
|
||||||
|
|
||||||
|
- name: Create and push manifest Docker Hub (:latest)
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:latest
|
||||||
|
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:latest-amd64,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:latest-armv7l,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:latest-arm64
|
||||||
|
push: true
|
||||||
|
|
||||||
|
- name: Create and push manifest GHCR (:latest)
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:latest
|
||||||
|
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:latest-amd64,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:latest-armv7l,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:latest-arm64
|
||||||
|
push: true
|
||||||
|
amend: true
|
||||||
|
|
||||||
|
- name: Create and push Full S6 manifest Docker Hub (:version)
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:full-s6
|
||||||
|
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-amd64,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-armv7l,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-arm64
|
||||||
|
push: true
|
||||||
|
amend: true
|
||||||
|
|
||||||
|
- name: Create and push Full S6 manifest GHCR (:latest)
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:full-s6
|
||||||
|
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-amd64,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-armv7l,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:full-s6-arm64
|
||||||
|
push: true
|
||||||
|
amend: true
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
name: Build Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
BASE_IMAGE_NAMESPACE:
|
||||||
|
description: 'Base image namespace (Default: Your Github username)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
DOCKERHUB_IMAGE_NAMESPACE:
|
||||||
|
description: 'Docker Hub image namespace (Default: Your Github username)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
GHCR_IMAGE_NAMESPACE:
|
||||||
|
description: 'GitHub Container Registry image namespace (Default: Your Github username)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
SKIP_DOCKER_HUB:
|
||||||
|
description: 'Set to true to skip pushing to Docker Hub (default: false)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
SKIP_GHCR:
|
||||||
|
description: 'Set to true to skip pushing to GHCR (default: false)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
WEBCLIENT_SOURCE_LOCATION:
|
||||||
|
description: 'Web Client API Repository'
|
||||||
|
required: true
|
||||||
|
default: 'https://github.com/lejianwen/rustdesk-api-web'
|
||||||
|
|
||||||
|
env:
|
||||||
|
LATEST_TAG: latest
|
||||||
|
WEBCLIENT_SOURCE_LOCATION: ${{ github.event.inputs.WEBCLIENT_SOURCE_LOCATION || 'https://github.com/lejianwen/rustdesk-api-web' }}
|
||||||
|
BASE_IMAGE_NAMESPACE: ${{ github.event.inputs.BASE_IMAGE_NAMESPACE || github.actor }}
|
||||||
|
DOCKERHUB_IMAGE_NAMESPACE: ${{ github.event.inputs.DOCKERHUB_IMAGE_NAMESPACE || github.actor }}
|
||||||
|
GHCR_IMAGE_NAMESPACE: ${{ github.event.inputs.GHCR_IMAGE_NAMESPACE || github.actor }}
|
||||||
|
SKIP_DOCKER_HUB: ${{ github.event.inputs.SKIP_DOCKER_HUB || 'false' }}
|
||||||
|
SKIP_GHCR: ${{ github.event.inputs.SKIP_GHCR || 'false' }}
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { platform: "amd64", goos: "linux", file_ext: "tar.gz" }
|
||||||
|
- { platform: "arm64", goos: "linux", file_ext: "tar.gz" }
|
||||||
|
- { platform: "armv7l", goos: "linux", file_ext: "tar.gz" }
|
||||||
|
- { platform: "amd64", goos: "windows", file_ext: "zip" }
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: lejianwen/rustdesk-api-web
|
||||||
|
path: rustdesk-api-web
|
||||||
|
ref: master
|
||||||
|
|
||||||
|
- name: Set up Go environment
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: '1.22' # 选择 Go 版本
|
||||||
|
|
||||||
|
- name: Set up npm
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: build rustdesk-api-web
|
||||||
|
working-directory: rustdesk-api-web
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
mkdir -p ../resources/admin/
|
||||||
|
cp -ar dist/* ../resources/admin/
|
||||||
|
|
||||||
|
- name: tidy
|
||||||
|
run: go mod tidy
|
||||||
|
|
||||||
|
- name: swag
|
||||||
|
run: |
|
||||||
|
go install github.com/swaggo/swag/cmd/swag@latest
|
||||||
|
swag init -g cmd/apimain.go --output docs/api --instanceName api --exclude http/controller/admin
|
||||||
|
swag init -g cmd/apimain.go --output docs/admin --instanceName admin --exclude http/controller/api
|
||||||
|
|
||||||
|
- name: Build for ${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
run: |
|
||||||
|
mkdir release -p
|
||||||
|
cp -ar resources release/
|
||||||
|
cp -ar docs release/
|
||||||
|
cp -ar conf release/
|
||||||
|
mkdir -p release/data
|
||||||
|
mkdir -p release/runtime
|
||||||
|
if [ "${{ matrix.job.goos }}" = "windows" ]; then
|
||||||
|
sudo apt-get install gcc-mingw-w64-x86-64 zip -y
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain.exe ./cmd/apimain.go
|
||||||
|
echo @echo off > release/start.bat
|
||||||
|
echo cmd /c \"%~dp0apimain.exe\" >> release/start.bat
|
||||||
|
zip -r ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
|
||||||
|
else
|
||||||
|
if [ "${{ matrix.job.platform }}" = "arm64" ]; then
|
||||||
|
wget https://musl.cc/aarch64-linux-musl-cross.tgz
|
||||||
|
tar -xf aarch64-linux-musl-cross.tgz
|
||||||
|
export PATH=$PATH:$PWD/aarch64-linux-musl-cross/bin
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=aarch64-linux-musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
|
||||||
|
elif [ "${{ matrix.job.platform }}" = "armv7l" ]; then
|
||||||
|
wget https://musl.cc/armv7l-linux-musleabihf-cross.tgz
|
||||||
|
tar -xf armv7l-linux-musleabihf-cross.tgz
|
||||||
|
export PATH=$PATH:$PWD/armv7l-linux-musleabihf-cross/bin
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=arm GOARM=7 CC=armv7l-linux-musleabihf-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
|
||||||
|
else
|
||||||
|
sudo apt-get install musl musl-dev musl-tools -y
|
||||||
|
GOOS=${{ matrix.job.goos }} GOARCH=${{ matrix.job.platform }} CC=musl-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
|
||||||
|
fi
|
||||||
|
tar -czf ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ./release
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
path: |
|
||||||
|
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
|
||||||
|
|
||||||
|
- name: Upload to GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
|
||||||
|
tag_name: test
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
deb-package:
|
||||||
|
name: debian package - ${{ matrix.job.platform }}
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { platform: "amd64", goos: "linux", debian_platform: "amd64", crossbuild_package: ""}
|
||||||
|
- { platform: "arm64", goos: "linux", debian_platform: "arm64", crossbuild_package: "crossbuild-essential-arm64" }
|
||||||
|
- { platform: "armv7l", goos: "linux", debian_platform: "armhf", crossbuild_package: "crossbuild-essential-armhf" }
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Create packaging env
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
DEBIAN_FRONTEND=noninteractive sudo apt install -y devscripts build-essential debhelper pkg-config ${{ matrix.job.crossbuild_package }}
|
||||||
|
mkdir -p debian-build/${{ matrix.job.platform }}/bin
|
||||||
|
|
||||||
|
- name: Download binaries
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Unzip binaries
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ matrix.job.platform }}
|
||||||
|
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
|
||||||
|
|
||||||
|
- name: Build package for ${{ matrix.job.platform }} arch
|
||||||
|
run: |
|
||||||
|
mv ${{ matrix.job.platform }}/release/apimain debian-build/${{ matrix.job.platform }}/bin/rustdesk-api
|
||||||
|
chmod -v a+x debian-build/${{ matrix.job.platform }}/bin/*
|
||||||
|
mkdir -p data
|
||||||
|
cp -vr debian systemd conf data resources runtime debian-build/${{ matrix.job.platform }}/
|
||||||
|
cat debian/control.tpl | sed 's/{{ ARCH }}/${{ matrix.job.debian_platform }}/' > debian-build/${{ matrix.job.platform }}/debian/control
|
||||||
|
cd debian-build/${{ matrix.job.platform }}/
|
||||||
|
debuild -i -us -uc -b -a${{ matrix.job.debian_platform}}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.debian_platform }}
|
||||||
|
path: |
|
||||||
|
debian-build/*.deb
|
||||||
|
|
||||||
|
- name: Upload to GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: test
|
||||||
|
files: |
|
||||||
|
debian-build/rustdesk-api-server_*_${{ matrix.job.debian_platform }}.deb
|
||||||
|
|
||||||
|
docker:
|
||||||
|
name: Push Docker Image
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { platform: "amd64", goos: "linux", docker_platform: "linux/amd64" }
|
||||||
|
- { platform: "arm64", goos: "linux", docker_platform: "linux/arm64" }
|
||||||
|
- { platform: "armv7l", goos: "linux", docker_platform: "linux/arm/v7" }
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if SKIP_DOCKER_HUB is false
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
|
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "TAG=test" >> $GITHUB_ENV # Default to 'test' if not a tag
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api
|
||||||
|
|
||||||
|
- name: Download binaries
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
|
||||||
|
path: ./
|
||||||
|
|
||||||
|
- name: Unzip binaries
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ matrix.job.platform }}
|
||||||
|
tar -xzf ${{ matrix.job.goos }}-${{ matrix.job.platform }}.tar.gz -C ${{ matrix.job.platform }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image to Docker Hub ${{ matrix.job.platform }}
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only run this step if SKIP_DOCKER_HUB is false
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: "."
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: ${{ matrix.job.docker_platform }}
|
||||||
|
push: true
|
||||||
|
provenance: false
|
||||||
|
build-args: |
|
||||||
|
BUILDARCH=${{ matrix.job.platform }}
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image to GHCR ${{ matrix.job.platform }}
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only run this step if SKIP_GHCR is false
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: "."
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: ${{ matrix.job.docker_platform }}
|
||||||
|
push: true
|
||||||
|
provenance: false
|
||||||
|
build-args: |
|
||||||
|
BUILDARCH=${{ matrix.job.platform }}
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-${{ matrix.job.platform }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
#
|
||||||
|
docker-manifest:
|
||||||
|
name: Push Docker Manifest
|
||||||
|
needs: docker
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||||
|
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "TAG=test" >> $GITHUB_ENV # Default to 'test' if not a tag
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }} # Only log in if Docker Hub push is enabled
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }} # Only log in if GHCR push is enabled
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Create and push manifest Docker Hub (:version)
|
||||||
|
if: ${{ env.SKIP_DOCKER_HUB == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
|
||||||
|
extra-images: ${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
|
||||||
|
${{ env.DOCKERHUB_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
|
||||||
|
push: true
|
||||||
|
|
||||||
|
- name: Create and push manifest GHCR (:version)
|
||||||
|
if: ${{ env.SKIP_GHCR == 'false' }}
|
||||||
|
uses: Noelware/docker-manifest-action@master
|
||||||
|
with:
|
||||||
|
base-image: ghcr.io/${{ env.BASE_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}
|
||||||
|
extra-images: ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-amd64,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-armv7l,
|
||||||
|
ghcr.io/${{ env.GHCR_IMAGE_NAMESPACE }}/rustdesk-api:${{ env.TAG }}-arm64
|
||||||
|
push: true
|
||||||
|
amend: true
|
||||||
+7
-2
@@ -1,8 +1,13 @@
|
|||||||
.idea
|
.idea
|
||||||
runtime/*
|
runtime/*
|
||||||
!runtime
|
!runtime
|
||||||
|
!runtime/cache
|
||||||
!runtime/cache/.gitkeep
|
!runtime/cache/.gitkeep
|
||||||
go.sum
|
go.sum
|
||||||
resources/admin
|
resources/*
|
||||||
|
!resources/public/upload/.gitignore
|
||||||
|
!resources/web
|
||||||
|
!resources/web2
|
||||||
|
!resources/i18n
|
||||||
release
|
release
|
||||||
data/rustdeskapi.db
|
data
|
||||||
+2
-2
@@ -42,11 +42,11 @@ RUN if [ "$COUNTRY" = "CN" ] ; then \
|
|||||||
fi && \
|
fi && \
|
||||||
apk update && apk add --no-cache git
|
apk update && apk add --no-cache git
|
||||||
|
|
||||||
ARG FRONTEND_GIT_REPO=https://github.com/lejianwen/rustdesk-api-web.git
|
ARG FREONTEND_GIT_REPO=https://github.com/lejianwen/rustdesk-api-web.git
|
||||||
ARG FRONTEND_GIT_BRANCH=master
|
ARG FRONTEND_GIT_BRANCH=master
|
||||||
# Clone the frontend repository
|
# Clone the frontend repository
|
||||||
|
|
||||||
RUN git clone -b $FRONTEND_GIT_BRANCH $FRONTEND_GIT_REPO .
|
RUN git clone -b $FRONTEND_GIT_BRANCH $FREONTEND_GIT_REPO .
|
||||||
|
|
||||||
# Install required tools without caching index to minimize image size
|
# Install required tools without caching index to minimize image size
|
||||||
RUN if [ "$COUNTRY" = "CN" ] ; then \
|
RUN if [ "$COUNTRY" = "CN" ] ; then \
|
||||||
|
|||||||
@@ -1,250 +1,268 @@
|
|||||||
# RustDesk API
|
# RustDesk API
|
||||||
|
|
||||||
[中文文档](README_EN.md)
|
[English Doc](README_EN.md)
|
||||||
|
|
||||||
This project implements the RustDesk API using Go, and includes both a web UI and web client. RustDesk is a remote
|
本项目使用 Go 实现了 RustDesk 的 API,并包含了 Web Admin 和 Web 客户端。RustDesk 是一个远程桌面软件,提供了自托管的解决方案。
|
||||||
desktop software that provides self-hosted solutions.
|
|
||||||
|
|
||||||
<div align=center>
|
<div align=center>
|
||||||
<img src="https://img.shields.io/badge/golang-1.22-blue"/>
|
<img src="https://img.shields.io/badge/golang-1.22-blue"/>
|
||||||
<img src="https://img.shields.io/badge/gin-v1.9.0-lightBlue"/>
|
<img src="https://img.shields.io/badge/gin-v1.9.0-lightBlue"/>
|
||||||
<img src="https://img.shields.io/badge/gorm-v1.25.7-green"/>
|
<img src="https://img.shields.io/badge/gorm-v1.25.7-green"/>
|
||||||
<img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/>
|
<img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/>
|
||||||
<img src="https://goreportcard.com/badge/github.com/lejianwen/rustdesk-api/v2"/>
|
|
||||||
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/build.yml/badge.svg"/>
|
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/build.yml/badge.svg"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Better used with [lejianwen/rustdesk-server].
|
# 特性
|
||||||
> [lejianwen/rustdesk-server] is a fork of the official RustDesk Server repository.
|
|
||||||
> 1. Solves the API connection timeout issue.
|
|
||||||
> 2. Can enforce login before initiating a connection.
|
|
||||||
> 3. Supports client websocket.
|
|
||||||
|
|
||||||
|
- PC端API
|
||||||
# Features
|
- 个人版API
|
||||||
|
- 登录
|
||||||
- PC API
|
- 地址簿
|
||||||
- Personal API
|
- 群组
|
||||||
- Login
|
- 授权登录,支持`github`, `google` 和 `OIDC` 登录,支持`web后台`授权登录
|
||||||
- Address Book
|
|
||||||
- Groups
|
|
||||||
- Authorized login,
|
|
||||||
- supports `GitHub`, `Google` and `OIDC` login,
|
|
||||||
- supports `web admin` authorized login,
|
|
||||||
- supports LDAP(test AD and openladp) if API Server config
|
|
||||||
- i18n
|
- i18n
|
||||||
- Web Admin
|
- Web Admin
|
||||||
- User Management
|
- 用户管理
|
||||||
- Device Management
|
- 设备管理
|
||||||
- Address Book Management
|
- 地址簿管理
|
||||||
- Tag Management
|
- 标签管理
|
||||||
- Group Management
|
- 群组管理
|
||||||
- OAuth Management
|
- Oauth 管理
|
||||||
- LDAP Config by config file or ENV
|
- 登录日志
|
||||||
- Login Logs
|
- 链接日志
|
||||||
- Connection Logs
|
- 文件传输日志
|
||||||
- File Transfer Logs
|
- 快速使用web client
|
||||||
- Quick access to web client
|
|
||||||
- i18n
|
- i18n
|
||||||
- Share to guest by web client
|
- 通过 web client 分享给游客
|
||||||
- Server control (some simple official commands [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
|
- server控制(一些官方的简单的指令 [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
|
||||||
- Web Client
|
- Web Client
|
||||||
- Automatically obtain API server
|
- 自动获取API server
|
||||||
- Automatically obtain ID server and KEY
|
- 自动获取ID服务器和KEY
|
||||||
- Automatically obtain address book
|
- 自动获取地址簿
|
||||||
- Visitors are remotely to the device via a temporary sharing link
|
- 游客通过临时分享链接直接远程到设备
|
||||||
|
- v2 Preview
|
||||||
- CLI
|
- CLI
|
||||||
- Reset admin password
|
- 重置管理员密码
|
||||||
|
|
||||||
## Overview
|
## 功能
|
||||||
|
|
||||||
### API Service
|
### API 服务
|
||||||
Basic implementation of the PC client's primary interfaces.Supports the Personal version api, which can be enabled by configuring the `rustdesk.personal` file or the `RUSTDESK_API_RUSTDESK_PERSONAL` environment variable.
|
基本实现了PC端基础的接口。支持Personal版本接口,可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
|
||||||
|
|
||||||
<table>
|
#### 登录
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center" colspan="2"><b>Login</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center" colspan="2"><img src="docs/en_img/pc_login.png"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center"><b>Address Book</b></td>
|
|
||||||
<td width="50%" align="center"><b>Groups</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center"><img src="docs/en_img/pc_ab.png"></td>
|
|
||||||
<td width="50%" align="center"><img src="docs/en_img/pc_gr.png"></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Web Admin
|
- 添加了`github`, `google` 以及`OIDC`授权登录,需要在后台配置好就可以用了,具体可看后台OAuth配置
|
||||||
|
- 添加了web后台授权登录,点击后直接登录后台就自动登录客户端了
|
||||||
|
|
||||||
* The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and
|

|
||||||
displaying data.Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
|
|
||||||
|
|
||||||
* Admin panel URL: `http://<your server[:port]>/_admin/`
|
#### 地址簿
|
||||||
* For the initial installation, the admin username is `admin`, and the password will be printed in the console. You can change the password via the [command line](#CLI).
|
|
||||||
|
|
||||||

|

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

|
||||||

|
|
||||||
2. Regular user interface:
|
|
||||||

|
|
||||||
|
|
||||||
3. Each user can have multiple address books, which can also be shared with other users.
|
### Web Admin:
|
||||||
4. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
|
|
||||||
5. You can directly launch the client or open the web client for convenience; you can also share it with guests, who can remotely access the device via the web client.
|
|
||||||
6. OAuth support: Currently, `GitHub`, `Google` and `OIDC` are supported. You need to create an `OAuth App` and configure it in
|
|
||||||
the admin panel.
|
|
||||||
- For `Google` and `Github`, you don't need to fill the `Issuer` and `Scpoes`
|
|
||||||
- For `OIDC`, you must set the `Issuer`. And `Scopes` is optional which default is `openid,email,profile`, please make sure this `Oauth App` can access `sub`, `email` and `preferred_username`
|
|
||||||
- Create a `GitHub OAuth App`
|
|
||||||
at `Settings` -> `Developer settings` -> `OAuth Apps` -> `New OAuth App` [here](https://github.com/settings/developers).
|
|
||||||
- Set the `Authorization callback URL` to `http://<your server[:port]>/api/oidc/callback`,
|
|
||||||
e.g., `http://127.0.0.1:21114/api/oidc/callback`.
|
|
||||||
|
|
||||||
7. Login logs
|
* 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
|
||||||
8. Connection logs
|
|
||||||
9. File transfer logs
|
|
||||||
10. Server control
|
|
||||||
- `Simple mode`, some simple commands have been GUI-ized and can be executed directly in the backend
|
|
||||||

|
|
||||||
|
|
||||||
- `Advanced mode`, commands can be executed directly in the backend
|
* 后台访问地址是`http://<your server>[:port]/_admin/`初次安装管理员为用户名密码为`admin` `admin`,请即时更改密码
|
||||||
* Official commands can be used
|
|
||||||
* Custom commands can be added
|
1. 管理员界面
|
||||||
* Custom commands can be executed
|

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

|
||||||
|
右上角可以更改密码,可以切换语言,可以切换`白天/黑夜`模式
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
3. 每个用户可以多个地址簿,也可以将地址簿共享给其他用户
|
||||||
|
4. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
|
||||||
|
5. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
|
||||||
|

|
||||||
|
6. Oauth,支持了`Github`, `Google` 以及 `OIDC`, 需要创建一个`OAuth App`,然后配置到后台
|
||||||
|

|
||||||
|
- 对于`Google` 和 `Github`, `Issuer` 和 `Scopes`不需要填写.
|
||||||
|
- 对于`OIDC`, `Issuer`是必须的。`Scopes`是可选的,默认为 `openid,profile,email`. 确保可以获取 `sub`,`email` 和`preferred_username`
|
||||||
|
- `github oauth app`在`Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App`
|
||||||
|
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
|
||||||
|
- `Authorization callback URL`填写`http://<your server[:port]>/api/oauth/callback`
|
||||||
|
,比如`http://127.0.0.1:21114/api/oauth/callback`
|
||||||
|
7. 登录日志
|
||||||
|
8. 链接日志
|
||||||
|
9. 文件传输日志
|
||||||
|
10. server控制
|
||||||
|
|
||||||
|
- `简易模式`,已经界面化了一些简单的指令,可以直接在后台执行
|
||||||
|

|
||||||
|
|
||||||
|
- `高级模式`,直接在后台执行指令
|
||||||
|
* 可以官方指令
|
||||||
|
* 可以添加自定义指令
|
||||||
|
* 可以执行自定义指令
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
11. **LDAP Support**, When you setup the LDAP(test for OpenLDAP and AD), you can login with the LDAP's user. https://github.com/lejianwen/rustdesk-api/issues/114 , if LDAP fail fallback local user
|
|
||||||
|
|
||||||
### Web Client:
|
### Web Client:
|
||||||
|
|
||||||
1. If you're already logged into the admin panel, the web client will log in automatically.
|
1. 如果已经登录了后台,web client将自动直接登录
|
||||||
2. If you're not logged in, simply click the login button in the top right corner, and the API server will be
|
2. 如果没登录后台,点击右上角登录即可,api server已经自动配置好了
|
||||||
pre-configured.
|
3. 登录后,会自动同步ID服务器和KEY
|
||||||
3. After logging in, the ID server and key will be automatically synced.
|
4. 登录后,会将地址簿自动保存到web client中,方便使用
|
||||||
4. The address book will also be automatically saved to the web client for convenient use.
|
5. 现已支持`v2 Preview`,访问路径是`/webclient2`
|
||||||
|

|
||||||
|
6. `v2 preview` 部署,参考[WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||||
|
|
||||||
### Automated Documentation : API documentation is generated using Swag, making it easier for developers to understand and use the API.
|
|
||||||
|
|
||||||
1. Admin panel docs: `<your server[:port]>/admin/swagger/index.html`
|
### 自动化文档: 使用 Swag 生成 API 文档,方便开发者理解和使用 API。
|
||||||
2. PC client docs: `<your server[:port]>/swagger/index.html`
|
|
||||||
|
1. 后台文档 `<youer server[:port]>/admin/swagger/index.html`
|
||||||
|
2. PC端文档 `<youer server[:port]>/swagger/index.html`
|
||||||

|

|
||||||
|
|
||||||
### CLI
|
### CLI
|
||||||
```bash
|
```bash
|
||||||
# help
|
# 查看帮助
|
||||||
./apimain -h
|
./apimain -h
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Reset admin password
|
#### 重置管理员密码
|
||||||
```bash
|
```bash
|
||||||
./apimain reset-admin-pwd <pwd>
|
./apimain reset-admin-pwd <pwd>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation and Setup
|
## 安装与运行
|
||||||
|
|
||||||
### Configuration
|
### 相关配置
|
||||||
|
|
||||||
* [Config File](./conf/config.yaml)
|
* 参考`conf/config.yaml`配置文件,修改相关配置。
|
||||||
* Modify the configuration in `conf/config.yaml`.
|
* 如果`gorm.type`是`sqlite`,则不需要配置mysql相关配置。
|
||||||
* If `gorm.type` is set to `sqlite`, MySQL-related configurations are not required.
|
* 语言如果不设置默认为`zh-CN`
|
||||||
* Language support: `en` and `zh-CN` are supported. The default is `zh-CN`.
|
|
||||||
|
```yaml
|
||||||
|
lang: "en"
|
||||||
|
app:
|
||||||
|
web-client: 1 # 1:启用 0:禁用
|
||||||
|
register: false #是否开启注册
|
||||||
|
show-swagger: 0 #是否显示swagger文档
|
||||||
|
gin:
|
||||||
|
api-addr: "0.0.0.0:21114"
|
||||||
|
mode: "release"
|
||||||
|
resources-path: 'resources'
|
||||||
|
trust-proxy: ""
|
||||||
|
gorm:
|
||||||
|
type: "sqlite"
|
||||||
|
max-idle-conns: 10
|
||||||
|
max-open-conns: 100
|
||||||
|
mysql:
|
||||||
|
username: "root"
|
||||||
|
password: "111111"
|
||||||
|
addr: "192.168.1.66:3308"
|
||||||
|
dbname: "rustdesk"
|
||||||
|
rustdesk:
|
||||||
|
id-server: "192.168.1.66:21116"
|
||||||
|
relay-server: "192.168.1.66:21117"
|
||||||
|
api-server: "http://192.168.1.66:21114"
|
||||||
|
key: "123456789"
|
||||||
|
personal: 1
|
||||||
|
logger:
|
||||||
|
path: "./runtime/log.txt"
|
||||||
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
|
report-caller: true
|
||||||
|
proxy:
|
||||||
|
enable: false
|
||||||
|
host: ""
|
||||||
|
jwt:
|
||||||
|
key: ""
|
||||||
|
expire-duration: 360000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 环境变量
|
||||||
|
变量名前缀是`RUSTDESK_API`,环境变量如果存在将覆盖配置文件中的配置
|
||||||
|
|
||||||
|
| 变量名 | 说明 | 示例 |
|
||||||
|
|---------------------------------------------------|---------------------------------------------------------|------------------------------|
|
||||||
|
| TZ | 时区 | Asia/Shanghai |
|
||||||
|
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
||||||
|
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
|
||||||
|
| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` |
|
||||||
|
| RUSTDESK_API_APP_SHOW_SWAGGER | 是否可见swagger文档;`1`显示,`0`不显示,默认`0`不显示 | `1` |
|
||||||
|
| -----ADMIN配置----- | ---------- | ---------- |
|
||||||
|
| RUSTDESK_API_ADMIN_TITLE | 后台标题 | `RustDesk Api Admin` |
|
||||||
|
| RUSTDESK_API_ADMIN_HELLO | 后台欢迎语,可以使用`html` | |
|
||||||
|
| RUSTDESK_API_ADMIN_HELLO_FILE | 后台欢迎语文件,如果内容多,使用文件更方便。<br>会覆盖`RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
|
||||||
|
| -----GIN配置----- | ---------- | ---------- |
|
||||||
|
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
||||||
|
| -----------GORM配置---------------- | ------------------------------------ | --------------------------- |
|
||||||
|
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
|
||||||
|
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
|
||||||
|
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API, 1:启用,0:不启用; 默认启用 | 1 |
|
||||||
|
| -----MYSQL配置----- | ---------- | ---------- |
|
||||||
|
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
|
||||||
|
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
|
||||||
|
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
|
||||||
|
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
|
||||||
|
| -----RUSTDESK配置----- | --------------- | ---------- |
|
||||||
|
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` |
|
||||||
|
| RUSTDESK_API_RUSTDESK_WEBCLIENT_MAGIC_QUERYONLINE | Web client v2 中是否启用新的在线状态查询方法; `1`:启用,`0`:不启用,默认不启用 | `0` |
|
||||||
|
| ----PROXY配置----- | --------------- | ---------- |
|
||||||
|
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
|
||||||
|
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
|
||||||
|
| ----JWT配置---- | -------- | -------- |
|
||||||
|
| RUSTDESK_API_JWT_KEY | 自定义JWT KEY,为空则不启用JWT | |
|
||||||
|
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT有效时间 | 360000 |
|
||||||
|
|
||||||
|
|
||||||
### Environment Variables
|
### 运行
|
||||||
The environment variables correspond one-to-one with the configurations in the `conf/config.yaml` file. The prefix for variable names is `RUSTDESK_API`.
|
|
||||||
The table below does not list all configurations. Please refer to the configurations in `conf/config.yaml`.
|
|
||||||
|
|
||||||
| Variable Name | Description | Example |
|
#### docker运行
|
||||||
|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|
|
|
||||||
| TZ | timezone | Asia/Shanghai |
|
|
||||||
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
|
||||||
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
|
|
||||||
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
|
|
||||||
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
|
|
||||||
| RUSTDESK_API_APP_TOKEN_EXPIRE | token expire duration | `168h` |
|
|
||||||
| RUSTDESK_API_APP_DISABLE_PWD_LOGIN | disable password login | `false` |
|
|
||||||
| RUSTDESK_API_APP_REGISTER_STATUS | register user default status ; 1 enabled , 2 disabled ; default 1 | `1` |
|
|
||||||
| RUSTDESK_API_APP_CAPTCHA_THRESHOLD | captcha threshold; -1 disabled, 0 always enable, >0 threshold ;default `3` | `3` |
|
|
||||||
| RUSTDESK_API_APP_BAN_THRESHOLD | ban ip threshold; 0 disabled, >0 threshold ; default `0` | `0` |
|
|
||||||
| ----- ADMIN Configuration----- | ---------- | ---------- |
|
|
||||||
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
|
|
||||||
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
|
|
||||||
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
|
|
||||||
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
|
||||||
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
|
||||||
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
|
||||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
|
|
||||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
|
||||||
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
|
|
||||||
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
|
||||||
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
|
||||||
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
|
||||||
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
|
||||||
| RUSTDESK_API_MYSQL_TLS | Whether to enable TLS, optional values: `true`, `false`, `skip-verify`, `custom` | `false` |
|
|
||||||
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
|
|
||||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
|
|
||||||
| RUSTDESK_API_RUSTDESK<br/>_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
|
|
||||||
| RUSTDESK_API_RUSTDESK_WS_HOST | Custom Websocket Host | `wss://192.168.1.123:1234` |
|
|
||||||
| ---- PROXY ----- | --------------- | ---------- |
|
|
||||||
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
|
|
||||||
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
|
|
||||||
| ----JWT---- | -------- | -------- |
|
|
||||||
| RUSTDESK_API_JWT_KEY | Custom JWT KEY, if empty JWT is not enabled.<br/>If `MUST_LOGIN` from `lejianwen/rustdesk-server` is not used, it is recommended to leave it empty. | |
|
|
||||||
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT expire duration | `168h` |
|
|
||||||
|
|
||||||
### Installation Steps
|
1. 直接docker运行,配置可以通过挂载配置文件`/app/conf/config.yaml`来修改,或者通过环境变量覆盖配置文件中的配置
|
||||||
|
|
||||||
#### Running via Docker
|
|
||||||
|
|
||||||
1. Run directly with Docker. Configuration can be modified by mounting the config file `/app/conf/config.yaml`, or by
|
|
||||||
using environment variables to override settings.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d --name rustdesk-api -p 21114:21114 \
|
docker run -d --name rustdesk-api -p 21114:21114 \
|
||||||
-v /data/rustdesk/api:/app/data \
|
-v /data/rustdesk/api:/app/data \
|
||||||
-e RUSTDESK_API_LANG=en \
|
-e TZ=Asia/Shanghai \
|
||||||
|
-e RUSTDESK_API_LANG=zh-CN \
|
||||||
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
||||||
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
||||||
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
||||||
-e RUSTDESK_API_RUSTDESK_KEY=abc123456 \
|
-e RUSTDESK_API_RUSTDESK_KEY=<key> \
|
||||||
lejianwen/rustdesk-api
|
lejianwen/rustdesk-api
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Using `docker-compose`,look [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
2. 使用`docker compose`,参考[WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||||
|
|
||||||
#### Running from Release
|
#### 下载release直接运行
|
||||||
|
|
||||||
Download the release from [release](https://github.com/lejianwen/rustdesk-api/releases).
|
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
|
||||||
|
|
||||||
#### Source Installation
|
#### 源码安装
|
||||||
|
|
||||||
1. Clone the repository:
|
1. 克隆仓库
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/lejianwen/rustdesk-api.git
|
git clone https://github.com/lejianwen/rustdesk-api.git
|
||||||
cd rustdesk-api
|
cd rustdesk-api
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Install dependencies:
|
2. 安装依赖
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go mod tidy
|
go mod tidy
|
||||||
# Install Swag if you need to generate documentation; otherwise, you can skip this step
|
#安装swag,如果不需要生成文档,可以不安装
|
||||||
go install github.com/swaggo/swag/cmd/swag@latest
|
go install github.com/swaggo/swag/cmd/swag@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Build the admin front-end (the front-end code is
|
3. 编译后台前端,前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)中
|
||||||
in [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)):
|
|
||||||
```bash
|
```bash
|
||||||
cd resources
|
cd resources
|
||||||
mkdir -p admin
|
mkdir -p admin
|
||||||
@@ -254,34 +272,23 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
|
|||||||
npm run build
|
npm run build
|
||||||
cp -ar dist/* ../admin/
|
cp -ar dist/* ../admin/
|
||||||
```
|
```
|
||||||
|
4. 运行
|
||||||
4. Run:
|
|
||||||
```bash
|
```bash
|
||||||
# Run directly
|
#直接运行
|
||||||
go run cmd/apimain.go
|
go run cmd/apimain.go
|
||||||
# Or generate and run the API using generate_api.go
|
#或者使用generate_api.go生成api并运行
|
||||||
go generate generate_api.go
|
go generate generate_api.go
|
||||||
```
|
```
|
||||||
> **Note:** When using `go run` or the compiled binary, the `conf` and `resources`
|
5. 编译,如果想自己编译,先cd到项目根目录,然后windows下直接运行`build.bat`,linux下运行`build.sh`,编译后会在`release`
|
||||||
> directories must exist relative to the current working directory. If you run
|
目录下生成对应的可执行文件。直接运行编译后的可执行文件即可。
|
||||||
> the program from another location, specify absolute paths with `-c` and the
|
|
||||||
> `RUSTDESK_API_GIN_RESOURCES_PATH` environment variable. Example:
|
|
||||||
> ```bash
|
|
||||||
> RUSTDESK_API_GIN_RESOURCES_PATH=/opt/rustdesk-api/resources ./apimain -c /opt/rustdesk-api/conf/config.yaml
|
|
||||||
> ```
|
|
||||||
|
|
||||||
5. To compile, change to the project root directory. For Windows, run `build.bat`, and for Linux, run `build.sh`. After
|
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
|
||||||
compiling, the corresponding executables will be generated in the `release` directory. Run the compiled executables
|
|
||||||
directly.
|
|
||||||
|
|
||||||
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
|
|
||||||
change the password promptly.
|
|
||||||
|
|
||||||
#### Running with my forked server-s6 image
|
#### 使用我fork后的server-s6镜像运行
|
||||||
|
|
||||||
- Connection timeout issue resolved
|
|
||||||
- Can enforce login before initiating a connection
|
|
||||||
- github https://github.com/lejianwen/rustdesk-server
|
- github https://github.com/lejianwen/rustdesk-server
|
||||||
|
- docker hub https://hub.docker.com/r/lejianwen/rustdesk-server-s6
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
networks:
|
networks:
|
||||||
@@ -310,28 +317,17 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
|
|||||||
- RUSTDESK_API_JWT_KEY=xxxxxx # jwt key
|
- RUSTDESK_API_JWT_KEY=xxxxxx # jwt key
|
||||||
volumes:
|
volumes:
|
||||||
- /data/rustdesk/server:/data
|
- /data/rustdesk/server:/data
|
||||||
- /data/rustdesk/api:/app/data # mount the database
|
- /data/rustdesk/api:/app/data #将数据库挂载
|
||||||
networks:
|
networks:
|
||||||
- rustdesk-net
|
- rustdesk-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
```
|
```
|
||||||
## Others
|
|
||||||
|
|
||||||
|
## 其他
|
||||||
|
|
||||||
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||||
- [Connection Timeout](https://github.com/lejianwen/rustdesk-api/issues/92)
|
- [链接超时问题](https://github.com/lejianwen/rustdesk-api/issues/92)
|
||||||
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
||||||
- [Web client source](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
- [webclient来源](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
||||||
|
|
||||||
## Acknowledgements
|
|
||||||
|
|
||||||
Thanks to everyone who contributed!
|
|
||||||
|
|
||||||
<a href="https://github.com/lejianwen/rustdesk-api/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=lejianwen/rustdesk-api" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## Thanks for your support! If you find this project useful, please give it a ⭐️. Thank you!
|
|
||||||
|
|
||||||
|
|
||||||
[lejianwen/rustdesk-server]: https://github.com/lejianwen/rustdesk-server
|
|
||||||
+214
-212
@@ -1,250 +1,271 @@
|
|||||||
# RustDesk API
|
# RustDesk API
|
||||||
|
|
||||||
[English Doc](README.md)
|
This project implements the RustDesk API using Go, and includes both a web UI and web client. RustDesk is a remote
|
||||||
|
desktop software that provides self-hosted solutions.
|
||||||
本项目使用 Go 实现了 RustDesk 的 API,并包含了 Web Admin 和 Web 客户端。
|
|
||||||
|
|
||||||
|
|
||||||
<div align=center>
|
<div align=center>
|
||||||
<img src="https://img.shields.io/badge/golang-1.22-blue"/>
|
<img src="https://img.shields.io/badge/golang-1.22-blue"/>
|
||||||
<img src="https://img.shields.io/badge/gin-v1.9.0-lightBlue"/>
|
<img src="https://img.shields.io/badge/gin-v1.9.0-lightBlue"/>
|
||||||
<img src="https://img.shields.io/badge/gorm-v1.25.7-green"/>
|
<img src="https://img.shields.io/badge/gorm-v1.25.7-green"/>
|
||||||
<img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/>
|
<img src="https://img.shields.io/badge/swag-v1.16.3-yellow"/>
|
||||||
<img src="https://goreportcard.com/badge/github.com/lejianwen/rustdesk-api/v2"/>
|
|
||||||
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/build.yml/badge.svg"/>
|
<img src="https://github.com/lejianwen/rustdesk-api/actions/workflows/build.yml/badge.svg"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 搭配[lejianwen/rustdesk-server]使用更佳。
|
# Features
|
||||||
> [lejianwen/rustdesk-server]fork自RustDesk Server官方仓库
|
|
||||||
> 1. 解决了使用API链接超时问题
|
|
||||||
> 2. 可以强制登录后才能发起链接
|
|
||||||
> 3. 支持客户端websocket
|
|
||||||
|
|
||||||
|
- PC API
|
||||||
|
- Personal API
|
||||||
# 特性
|
- Login
|
||||||
|
- Address Book
|
||||||
- PC端API
|
- Groups
|
||||||
- 个人版API
|
- Authorized login, supports `GitHub`, `Google` and `OIDC` login, supports `web admin` authorized login
|
||||||
- 登录
|
|
||||||
- 地址簿
|
|
||||||
- 群组
|
|
||||||
- 授权登录
|
|
||||||
- 支持`github`, `google` 和 `OIDC` 登录,
|
|
||||||
- 支持`web后台`授权登录
|
|
||||||
- 支持`LDAP`(AD和OpenLDAP已测试), 如果API Server配置了LDAP
|
|
||||||
- i18n
|
- i18n
|
||||||
- Web Admin
|
- Web Admin
|
||||||
- 用户管理
|
- User Management
|
||||||
- 设备管理
|
- Device Management
|
||||||
- 地址簿管理
|
- Address Book Management
|
||||||
- 标签管理
|
- Tag Management
|
||||||
- 群组管理
|
- Group Management
|
||||||
- Oauth 管理
|
- OAuth Management
|
||||||
- 配置LDAP, 配置文件或者环境变量
|
- Login Logs
|
||||||
- 登录日志
|
- Connection Logs
|
||||||
- 链接日志
|
- File Transfer Logs
|
||||||
- 文件传输日志
|
- Quick access to web client
|
||||||
- 快速使用web client
|
|
||||||
- i18n
|
- i18n
|
||||||
- 通过 web client 分享给游客
|
- Share to guest by web client
|
||||||
- server控制(一些官方的简单的指令 [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
|
- Server control (some simple official commands [WIKI](https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command))
|
||||||
- Web Client
|
- Web Client
|
||||||
- 自动获取API server
|
- Automatically obtain API server
|
||||||
- 自动获取ID服务器和KEY
|
- Automatically obtain ID server and KEY
|
||||||
- 自动获取地址簿
|
- Automatically obtain address book
|
||||||
- 游客通过临时分享链接直接远程到设备
|
- Visitors are remotely to the device via a temporary sharing link
|
||||||
- CLI
|
- CLI
|
||||||
- 重置管理员密码
|
- Reset admin password
|
||||||
|
|
||||||
## 功能
|
## Overview
|
||||||
|
|
||||||
|
### API Service
|
||||||
|
Basic implementation of the PC client's primary interfaces.Supports the Personal version api, which can be enabled by configuring the `rustdesk.personal` file or the `RUSTDESK_API_RUSTDESK_PERSONAL` environment variable.
|
||||||
|
|
||||||
|
#### Login
|
||||||
|
|
||||||
|
- Added `GitHub`, `Google` and `OIDC` login, which can be used after configuration in the admin panel. See the OAuth
|
||||||
|
configuration section for details.
|
||||||
|
- Added authorization login for the web admin panel.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### Address Book
|
||||||
|
|
||||||
|

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

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

|
||||||
|
2. Regular user interface:
|
||||||
|

|
||||||
|
In the top right corner, you can change the password, switch languages, and toggle between `day/night` mode.
|
||||||
|
|
||||||
|

|
||||||
|
3. Each user can have multiple address books, which can also be shared with other users.
|
||||||
|
4. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
|
||||||
|
5. You can directly launch the client or open the web client for convenience; you can also share it with guests, who can remotely access the device via the web client.
|
||||||
|

|
||||||
|
6. OAuth support: Currently, `GitHub`, `Google` and `OIDC` are supported. You need to create an `OAuth App` and configure it in
|
||||||
|
the admin panel.
|
||||||
|

|
||||||
|
- For `Google` and `Github`, you don't need to fill the `Issuer` and `Scpoes`
|
||||||
|
- For `OIDC`, you must set the `Issuer`. And `Scopes` is optional which default is `openid,email,profile`, please make sure this `Oauth App` can access `sub`, `email` and `preferred_username`
|
||||||
|
- Create a `GitHub OAuth App`
|
||||||
|
at `Settings` -> `Developer settings` -> `OAuth Apps` -> `New OAuth App` [here](https://github.com/settings/developers).
|
||||||
|
- Set the `Authorization callback URL` to `http://<your server[:port]>/api/oauth/callback`,
|
||||||
|
e.g., `http://127.0.0.1:21114/api/oauth/callback`.
|
||||||
|
|
||||||
|
7. Login logs
|
||||||
|
8. Connection logs
|
||||||
|
9. File transfer logs
|
||||||
|
10. Server control
|
||||||
|
|
||||||
|
- `Simple mode`, some simple commands have been GUI-ized and can be executed directly in the backend
|
||||||
|

|
||||||
|
|
||||||
|
- `Advanced mode`, commands can be executed directly in the backend
|
||||||
|
* Official commands can be used
|
||||||
|
* Custom commands can be added
|
||||||
|
* Custom commands can be executed
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
### API 服务
|
|
||||||
基本实现了PC端基础的接口。支持Personal版本接口,可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center" colspan="2"><b>登录</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center" colspan="2"><img src="docs/pc_login.png"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center"><b>地址簿</b></td>
|
|
||||||
<td width="50%" align="center"><b>群组</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" align="center"><img src="docs/pc_ab.png"></td>
|
|
||||||
<td width="50%" align="center"><img src="docs/pc_gr.png"></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Web Admin:
|
|
||||||
|
|
||||||
* 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)
|
|
||||||
|
|
||||||
* 后台访问地址是`http://<your server>[:port]/_admin/`
|
|
||||||
* 初次安装管理员为用户名为`admin`,密码将在控制台打印,可以通过[命令行](#CLI)更改密码
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
1. 管理员界面
|
|
||||||

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

|
|
||||||
|
|
||||||
3. 每个用户可以多个地址簿,也可以将地址簿共享给其他用户
|
|
||||||
4. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
|
|
||||||
5. 可以直接打开webclient,方便使用;也可以分享给游客,游客可以直接通过webclient远程到设备
|
|
||||||
6. Oauth,支持了`Github`, `Google` 以及 `OIDC`, 需要创建一个`OAuth App`,然后配置到后台
|
|
||||||
- 对于`Google` 和 `Github`, `Issuer` 和 `Scopes`不需要填写.
|
|
||||||
- 对于`OIDC`, `Issuer`是必须的。`Scopes`是可选的,默认为 `openid,profile,email`. 确保可以获取 `sub`,`email` 和`preferred_username`
|
|
||||||
- `github oauth app`在`Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App`
|
|
||||||
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
|
|
||||||
- `Authorization callback URL`填写`http://<your server[:port]>/api/oidc/callback`
|
|
||||||
,比如`http://127.0.0.1:21114/api/oidc/callback`
|
|
||||||
7. 登录日志
|
|
||||||
8. 链接日志
|
|
||||||
9. 文件传输日志
|
|
||||||
10. server控制
|
|
||||||
|
|
||||||
- `简易模式`,已经界面化了一些简单的指令,可以直接在后台执行
|
|
||||||

|
|
||||||
|
|
||||||
- `高级模式`,直接在后台执行指令
|
|
||||||
* 可以官方指令
|
|
||||||
* 可以添加自定义指令
|
|
||||||
* 可以执行自定义指令
|
|
||||||
|
|
||||||
|
|
||||||
11. **LDAP 支持**, 当在API Server上设置了LDAP(已测试AD和LDAP),可以通过LDAP中的用户信息进行登录 https://github.com/lejianwen/rustdesk-api/issues/114 ,如果LDAP验证失败,返回本地用户
|
|
||||||
|
|
||||||
### Web Client:
|
### Web Client:
|
||||||
|
|
||||||
1. 如果已经登录了后台,web client将自动直接登录
|
1. If you're already logged into the admin panel, the web client will log in automatically.
|
||||||
2. 如果没登录后台,点击右上角登录即可,api server已经自动配置好了
|
2. If you're not logged in, simply click the login button in the top right corner, and the API server will be
|
||||||
3. 登录后,会自动同步ID服务器和KEY
|
pre-configured.
|
||||||
4. 登录后,会将地址簿自动保存到web client中,方便使用
|
3. After logging in, the ID server and key will be automatically synced.
|
||||||
|
4. The address book will also be automatically saved to the web client for convenient use.
|
||||||
|
5. Now supports `v2 Preview`, accessible at `/webclient2`
|
||||||
|

|
||||||
|
6. `v2 preview` deployment, [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||||
|
|
||||||
|
### Automated Documentation : API documentation is generated using Swag, making it easier for developers to understand and use the API.
|
||||||
|
|
||||||
### 自动化文档: 使用 Swag 生成 API 文档,方便开发者理解和使用 API。
|
1. Admin panel docs: `<your server[:port]>/admin/swagger/index.html`
|
||||||
|
2. PC client docs: `<your server[:port]>/swagger/index.html`
|
||||||
1. 后台文档 `<youer server[:port]>/admin/swagger/index.html`
|
|
||||||
2. PC端文档 `<youer server[:port]>/swagger/index.html`
|
|
||||||

|

|
||||||
|
|
||||||
### CLI
|
### CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 查看帮助
|
# help
|
||||||
./apimain -h
|
./apimain -h
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 重置管理员密码
|
#### Reset admin password
|
||||||
```bash
|
```bash
|
||||||
./apimain reset-admin-pwd <pwd>
|
./apimain reset-admin-pwd <pwd>
|
||||||
```
|
```
|
||||||
|
|
||||||
## 安装与运行
|
## Installation and Setup
|
||||||
|
|
||||||
### 相关配置
|
### Configuration
|
||||||
|
|
||||||
* [配置文件](./conf/config.yaml)
|
* Modify the configuration in `conf/config.yaml`.
|
||||||
* 参考`conf/config.yaml`配置文件,修改相关配置。
|
* If `gorm.type` is set to `sqlite`, MySQL-related configurations are not required.
|
||||||
* 如果`gorm.type`是`sqlite`,则不需要配置mysql相关配置。
|
* Language support: `en` and `zh-CN` are supported. The default is `zh-CN`.
|
||||||
* 语言如果不设置默认为`zh-CN`
|
|
||||||
|
|
||||||
### 环境变量
|
```yaml
|
||||||
环境变量和配置文件`conf/config.yaml`中的配置一一对应,变量名前缀是`RUSTDESK_API`
|
lang: "en"
|
||||||
下面表格并未全部列出,可以参考`conf/config.yaml`中的配置。
|
app:
|
||||||
|
web-client: 1 # web client route 1:open 0:close
|
||||||
|
register: false #register enable
|
||||||
|
show-swagger: 0 #show swagger 1:open 0:close
|
||||||
|
gin:
|
||||||
|
api-addr: "0.0.0.0:21114"
|
||||||
|
mode: "release"
|
||||||
|
resources-path: 'resources'
|
||||||
|
trust-proxy: ""
|
||||||
|
gorm:
|
||||||
|
type: "sqlite"
|
||||||
|
max-idle-conns: 10
|
||||||
|
max-open-conns: 100
|
||||||
|
mysql:
|
||||||
|
username: "root"
|
||||||
|
password: "111111"
|
||||||
|
addr: "192.168.1.66:3308"
|
||||||
|
dbname: "rustdesk"
|
||||||
|
rustdesk:
|
||||||
|
id-server: "192.168.1.66:21116"
|
||||||
|
relay-server: "192.168.1.66:21117"
|
||||||
|
api-server: "http://192.168.1.66:21114"
|
||||||
|
key: "123456789"
|
||||||
|
personal: 1
|
||||||
|
logger:
|
||||||
|
path: "./runtime/log.txt"
|
||||||
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
|
report-caller: true
|
||||||
|
proxy:
|
||||||
|
enable: false
|
||||||
|
host: ""
|
||||||
|
jwt:
|
||||||
|
key: ""
|
||||||
|
expire-duration: 360000
|
||||||
|
```
|
||||||
|
|
||||||
| 变量名 | 说明 | 示例 |
|
### Environment Variables
|
||||||
|--------------------------------------------------------|--------------------------------------------------------------------------------|------------------------------|
|
The prefix for variable names is `RUSTDESK_API`. If environment variables exist, they will override the configurations in the configuration file.
|
||||||
| TZ | 时区 | Asia/Shanghai |
|
|
||||||
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
|
||||||
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
|
|
||||||
| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` |
|
|
||||||
| RUSTDESK_API_APP_SHOW_SWAGGER | 是否可见swagger文档;`1`显示,`0`不显示,默认`0`不显示 | `1` |
|
|
||||||
| RUSTDESK_API_APP_TOKEN_EXPIRE | token有效时长 | `168h` |
|
|
||||||
| RUSTDESK_API_APP_DISABLE_PWD_LOGIN | 是否禁用密码登录; `true`, `false` 默认`false` | `false` |
|
|
||||||
| RUSTDESK_API_APP_REGISTER_STATUS | 注册用户默认状态; 1 启用,2 禁用, 默认 1 | `1` |
|
|
||||||
| RUSTDESK_API_APP_CAPTCHA_THRESHOLD | 验证码触发次数; -1 不启用, 0 一直启用, >0 登录错误次数后启用 ;默认 `3` | `3` |
|
|
||||||
| RUSTDESK_API_APP_BAN_THRESHOLD | 封禁IP触发次数; 0 不启用, >0 登录错误次数后封禁IP; 默认 `0` | `0` |
|
|
||||||
| -----ADMIN配置----- | ---------- | ---------- |
|
|
||||||
| RUSTDESK_API_ADMIN_TITLE | 后台标题 | `RustDesk Api Admin` |
|
|
||||||
| RUSTDESK_API_ADMIN_HELLO | 后台欢迎语,可以使用`html` | |
|
|
||||||
| RUSTDESK_API_ADMIN_HELLO_FILE | 后台欢迎语文件,如果内容多,使用文件更方便。<br>会覆盖`RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
|
|
||||||
| -----GIN配置----- | ---------- | ---------- |
|
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
|
||||||
| -----GORM配置----- | ---------- | --------------------------- |
|
|
||||||
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql,默认sqlite | sqlite |
|
|
||||||
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
|
|
||||||
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API, 1:启用,0:不启用; 默认启用 | 1 |
|
|
||||||
| -----MYSQL配置----- | ---------- | ---------- |
|
|
||||||
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
|
|
||||||
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
|
|
||||||
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
|
|
||||||
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
|
|
||||||
| RUSTDESK_API_MYSQL_TLS | 是否启用TLS, 可选值: `true`, `false`, `skip-verify`, `custom` | `false` |
|
|
||||||
| -----RUSTDESK配置----- | ---------- | ---------- |
|
|
||||||
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
|
|
||||||
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` |
|
|
||||||
| RUSTDESK_API_RUSTDESK_WEBCLIENT<br/>_MAGIC_QUERYONLINE | Web client v2 中是否启用新的在线状态查询方法; `1`:启用,`0`:不启用,默认不启用 | `0` |
|
|
||||||
| RUSTDESK_API_RUSTDESK_WS_HOST | 自定义Websocket Host | `wss://192.168.1.123:1234` |
|
|
||||||
| ----PROXY配置----- | ---------- | ---------- |
|
|
||||||
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
|
|
||||||
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
|
|
||||||
| ----JWT配置---- | -------- | -------- |
|
|
||||||
| RUSTDESK_API_JWT_KEY | 自定义JWT KEY,为空则不启用JWT<br/>如果没使用`lejianwen/rustdesk-server`中的`MUST_LOGIN`,建议设置为空 | |
|
|
||||||
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT有效时间 | `168h` |
|
|
||||||
|
|
||||||
|
| Variable Name | Description | Example |
|
||||||
|
|---------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------|
|
||||||
|
| TZ | timezone | Asia/Shanghai |
|
||||||
|
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
||||||
|
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
|
||||||
|
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
|
||||||
|
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
|
||||||
|
| ----- ADMIN Configuration----- | ---------- | ---------- |
|
||||||
|
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
|
||||||
|
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
|
||||||
|
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
|
||||||
|
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
|
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
||||||
|
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
|
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
|
||||||
|
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
|
||||||
|
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
|
||||||
|
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
|
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
|
||||||
|
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
|
||||||
|
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
|
||||||
|
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
|
||||||
|
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
|
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
|
||||||
|
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
|
||||||
|
| RUSTDESK_API_RUSTDESK_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
|
||||||
|
| ---- PROXY ----- | --------------- | ---------- |
|
||||||
|
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
|
||||||
|
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
|
||||||
|
| ----JWT---- | -------- | -------- |
|
||||||
|
| RUSTDESK_API_JWT_KEY | JWT KEY. Set empty to disable jwt | |
|
||||||
|
| RUSTDESK_API_JWT_EXPIRE_DURATION | JWT expire duration | 360000 |
|
||||||
|
|
||||||
### 运行
|
### Installation Steps
|
||||||
|
|
||||||
#### docker运行
|
#### Running via Docker
|
||||||
|
|
||||||
1. 直接docker运行,配置可以通过挂载配置文件`/app/conf/config.yaml`来修改,或者通过环境变量覆盖配置文件中的配置
|
1. Run directly with Docker. Configuration can be modified by mounting the config file `/app/conf/config.yaml`, or by
|
||||||
|
using environment variables to override settings.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d --name rustdesk-api -p 21114:21114 \
|
docker run -d --name rustdesk-api -p 21114:21114 \
|
||||||
-v /data/rustdesk/api:/app/data \
|
-v /data/rustdesk/api:/app/data \
|
||||||
-e TZ=Asia/Shanghai \
|
-e RUSTDESK_API_LANG=en \
|
||||||
-e RUSTDESK_API_LANG=zh-CN \
|
|
||||||
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
-e RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116 \
|
||||||
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
-e RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117 \
|
||||||
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
-e RUSTDESK_API_RUSTDESK_API_SERVER=http://192.168.1.66:21114 \
|
||||||
-e RUSTDESK_API_RUSTDESK_KEY=<key> \
|
-e RUSTDESK_API_RUSTDESK_KEY=abc123456 \
|
||||||
lejianwen/rustdesk-api
|
lejianwen/rustdesk-api
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 使用`docker compose`,参考[WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
2. Using `docker-compose`,look [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||||
|
|
||||||
#### 下载release直接运行
|
#### Running from Release
|
||||||
|
|
||||||
[下载地址](https://github.com/lejianwen/rustdesk-api/releases)
|
Download the release from [release](https://github.com/lejianwen/rustdesk-api/releases).
|
||||||
|
|
||||||
#### 源码安装
|
#### Source Installation
|
||||||
|
|
||||||
1. 克隆仓库
|
1. Clone the repository:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/lejianwen/rustdesk-api.git
|
git clone https://github.com/lejianwen/rustdesk-api.git
|
||||||
cd rustdesk-api
|
cd rustdesk-api
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 安装依赖
|
2. Install dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go mod tidy
|
go mod tidy
|
||||||
#安装swag,如果不需要生成文档,可以不安装
|
# Install Swag if you need to generate documentation; otherwise, you can skip this step
|
||||||
go install github.com/swaggo/swag/cmd/swag@latest
|
go install github.com/swaggo/swag/cmd/swag@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 编译后台前端,前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)中
|
3. Build the admin front-end (the front-end code is
|
||||||
|
in [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)):
|
||||||
```bash
|
```bash
|
||||||
cd resources
|
cd resources
|
||||||
mkdir -p admin
|
mkdir -p admin
|
||||||
@@ -254,30 +275,26 @@
|
|||||||
npm run build
|
npm run build
|
||||||
cp -ar dist/* ../admin/
|
cp -ar dist/* ../admin/
|
||||||
```
|
```
|
||||||
4. 运行
|
|
||||||
|
4. Run:
|
||||||
```bash
|
```bash
|
||||||
#直接运行
|
# Run directly
|
||||||
go run cmd/apimain.go
|
go run cmd/apimain.go
|
||||||
#或者使用generate_api.go生成api并运行
|
# Or generate and run the API using generate_api.go
|
||||||
go generate generate_api.go
|
go generate generate_api.go
|
||||||
```
|
```
|
||||||
> 注意:使用 `go run` 或编译后的二进制时,当前目录下必须存在 `conf` 和 `resources`
|
|
||||||
> 目录。如果在其他目录运行,可通过 `-c` 和环境变量
|
|
||||||
> `RUSTDESK_API_GIN_RESOURCES_PATH` 指定绝对路径,例如:
|
|
||||||
> ```bash
|
|
||||||
> RUSTDESK_API_GIN_RESOURCES_PATH=/opt/rustdesk-api/resources ./apimain -c /opt/rustdesk-api/conf/config.yaml
|
|
||||||
> ```
|
|
||||||
5. 编译,如果想自己编译,先cd到项目根目录,然后windows下直接运行`build.bat`,linux下运行`build.sh`,编译后会在`release`
|
|
||||||
目录下生成对应的可执行文件。直接运行编译后的可执行文件即可。
|
|
||||||
|
|
||||||
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
|
5. To compile, change to the project root directory. For Windows, run `build.bat`, and for Linux, run `build.sh`. After
|
||||||
|
compiling, the corresponding executables will be generated in the `release` directory. Run the compiled executables
|
||||||
|
directly.
|
||||||
|
|
||||||
|
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
|
||||||
|
change the password promptly.
|
||||||
|
|
||||||
#### 使用`lejianwen/server-s6`镜像运行
|
#### Running with my forked server-s6 image
|
||||||
|
|
||||||
- 已解决链接超时问题
|
|
||||||
- 可以强制登录后才能发起链接
|
|
||||||
- github https://github.com/lejianwen/rustdesk-server
|
- github https://github.com/lejianwen/rustdesk-server
|
||||||
|
- docker hub https://hub.docker.com/r/lejianwen/rustdesk-server-s6
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
networks:
|
networks:
|
||||||
@@ -312,24 +329,9 @@
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
```
|
```
|
||||||
|
## Others
|
||||||
|
|
||||||
## 其他
|
|
||||||
|
|
||||||
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
- [WIKI](https://github.com/lejianwen/rustdesk-api/wiki)
|
||||||
- [链接超时问题](https://github.com/lejianwen/rustdesk-api/issues/92)
|
- [Connection Timeout](https://github.com/lejianwen/rustdesk-api/issues/92)
|
||||||
- [修改客户端ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
- [Change client ID](https://github.com/abdullah-erturk/RustDesk-ID-Changer)
|
||||||
- [webclient来源](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
- [Web client source](https://hub.docker.com/r/keyurbhole/flutter_web_desk)
|
||||||
|
|
||||||
|
|
||||||
## 鸣谢
|
|
||||||
|
|
||||||
感谢所有做过贡献的人!
|
|
||||||
|
|
||||||
<a href="https://github.com/lejianwen/rustdesk-api/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=lejianwen/rustdesk-api" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## 感谢你的支持!如果这个项目对你有帮助,请点个⭐️鼓励一下,谢谢!
|
|
||||||
|
|
||||||
[lejianwen/rustdesk-server]: https://github.com/lejianwen/rustdesk-server
|
|
||||||
+54
-115
@@ -1,33 +1,29 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/config"
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http"
|
||||||
|
"Gwen/lib/cache"
|
||||||
|
"Gwen/lib/jwt"
|
||||||
|
"Gwen/lib/lock"
|
||||||
|
"Gwen/lib/logger"
|
||||||
|
"Gwen/lib/orm"
|
||||||
|
"Gwen/lib/upload"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/config"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/cache"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/jwt"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/lock"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/logger"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/orm"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/upload"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/utils"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const DatabaseVersion = 265
|
// @title 管理系统API
|
||||||
|
|
||||||
// @title Management System API
|
|
||||||
// @version 1.0
|
// @version 1.0
|
||||||
// @description API
|
// @description 接口
|
||||||
// @basePath /api
|
// @basePath /api
|
||||||
// @securityDefinitions.apikey token
|
// @securityDefinitions.apikey token
|
||||||
// @in header
|
// @in header
|
||||||
@@ -43,7 +39,7 @@ var rootCmd = &cobra.Command{
|
|||||||
InitGlobal()
|
InitGlobal()
|
||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
global.Logger.Info("API SERVER START")
|
//gin
|
||||||
http.ApiInit()
|
http.ApiInit()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -56,16 +52,12 @@ var resetPwdCmd = &cobra.Command{
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
pwd := args[0]
|
pwd := args[0]
|
||||||
admin := service.AllService.UserService.InfoById(1)
|
admin := service.AllService.UserService.InfoById(1)
|
||||||
if admin.Id == 0 {
|
|
||||||
global.Logger.Warn("user not found! ")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err := service.AllService.UserService.UpdatePassword(admin, pwd)
|
err := service.AllService.UserService.UpdatePassword(admin, pwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("reset password fail! ", err)
|
fmt.Printf("reset password fail! %v \n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
global.Logger.Info("reset password success! ")
|
fmt.Printf("reset password success! \n")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var resetUserPwdCmd = &cobra.Command{
|
var resetUserPwdCmd = &cobra.Command{
|
||||||
@@ -78,24 +70,20 @@ var resetUserPwdCmd = &cobra.Command{
|
|||||||
pwd := args[1]
|
pwd := args[1]
|
||||||
uid, err := strconv.Atoi(userId)
|
uid, err := strconv.Atoi(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn("userId must be int!")
|
fmt.Printf("userId must be int! \n")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if uid <= 0 {
|
if uid <= 0 {
|
||||||
global.Logger.Warn("userId must be greater than 0! ")
|
fmt.Printf("userId must be greater than 0! \n")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
u := service.AllService.UserService.InfoById(uint(uid))
|
u := service.AllService.UserService.InfoById(uint(uid))
|
||||||
if u.Id == 0 {
|
|
||||||
global.Logger.Warn("user not found! ")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = service.AllService.UserService.UpdatePassword(u, pwd)
|
err = service.AllService.UserService.UpdatePassword(u, pwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Warn("reset password fail! ", err)
|
fmt.Printf("reset password fail! %v \n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
global.Logger.Info("reset password success!")
|
fmt.Printf("reset password success! \n")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,16 +93,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
func main() {
|
func main() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
global.Logger.Error(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitGlobal() {
|
func InitGlobal() {
|
||||||
// config parsing
|
//配置解析
|
||||||
global.Viper = config.Init(&global.Config, global.ConfigPath)
|
global.Viper = config.Init(&global.Config, global.ConfigPath)
|
||||||
|
|
||||||
// logging
|
//日志
|
||||||
global.Logger = logger.New(&logger.Config{
|
global.Logger = logger.New(&logger.Config{
|
||||||
Path: global.Config.Logger.Path,
|
Path: global.Config.Logger.Path,
|
||||||
Level: global.Config.Logger.Level,
|
Level: global.Config.Logger.Level,
|
||||||
@@ -144,42 +132,20 @@ func InitGlobal() {
|
|||||||
}
|
}
|
||||||
//gorm
|
//gorm
|
||||||
if global.Config.Gorm.Type == config.TypeMysql {
|
if global.Config.Gorm.Type == config.TypeMysql {
|
||||||
|
dns := global.Config.Mysql.Username + ":" + global.Config.Mysql.Password + "@(" + global.Config.Mysql.Addr + ")/" + global.Config.Mysql.Dbname + "?charset=utf8mb4&parseTime=True&loc=Local"
|
||||||
dsn := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local&tls=%s",
|
|
||||||
global.Config.Mysql.Username,
|
|
||||||
global.Config.Mysql.Password,
|
|
||||||
global.Config.Mysql.Addr,
|
|
||||||
global.Config.Mysql.Dbname,
|
|
||||||
global.Config.Mysql.Tls,
|
|
||||||
)
|
|
||||||
|
|
||||||
global.DB = orm.NewMysql(&orm.MysqlConfig{
|
global.DB = orm.NewMysql(&orm.MysqlConfig{
|
||||||
Dsn: dsn,
|
Dns: dns,
|
||||||
MaxIdleConns: global.Config.Gorm.MaxIdleConns,
|
MaxIdleConns: global.Config.Gorm.MaxIdleConns,
|
||||||
MaxOpenConns: global.Config.Gorm.MaxOpenConns,
|
MaxOpenConns: global.Config.Gorm.MaxOpenConns,
|
||||||
}, global.Logger)
|
})
|
||||||
} else if global.Config.Gorm.Type == config.TypePostgresql {
|
|
||||||
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s TimeZone=%s",
|
|
||||||
global.Config.Postgresql.Host,
|
|
||||||
global.Config.Postgresql.Port,
|
|
||||||
global.Config.Postgresql.User,
|
|
||||||
global.Config.Postgresql.Password,
|
|
||||||
global.Config.Postgresql.Dbname,
|
|
||||||
global.Config.Postgresql.Sslmode,
|
|
||||||
global.Config.Postgresql.TimeZone,
|
|
||||||
)
|
|
||||||
global.DB = orm.NewPostgresql(&orm.PostgresqlConfig{
|
|
||||||
Dsn: dsn,
|
|
||||||
MaxIdleConns: global.Config.Gorm.MaxIdleConns,
|
|
||||||
MaxOpenConns: global.Config.Gorm.MaxOpenConns,
|
|
||||||
}, global.Logger)
|
|
||||||
} else {
|
} else {
|
||||||
//sqlite
|
//sqlite
|
||||||
global.DB = orm.NewSqlite(&orm.SqliteConfig{
|
global.DB = orm.NewSqlite(&orm.SqliteConfig{
|
||||||
MaxIdleConns: global.Config.Gorm.MaxIdleConns,
|
MaxIdleConns: global.Config.Gorm.MaxIdleConns,
|
||||||
MaxOpenConns: global.Config.Gorm.MaxOpenConns,
|
MaxOpenConns: global.Config.Gorm.MaxOpenConns,
|
||||||
}, global.Logger)
|
})
|
||||||
}
|
}
|
||||||
|
DatabaseAutoUpdate()
|
||||||
|
|
||||||
//validator
|
//validator
|
||||||
global.ApiInitValidator()
|
global.ApiInitValidator()
|
||||||
@@ -196,60 +162,43 @@ func InitGlobal() {
|
|||||||
|
|
||||||
//jwt
|
//jwt
|
||||||
//fmt.Println(global.Config.Jwt.PrivateKey)
|
//fmt.Println(global.Config.Jwt.PrivateKey)
|
||||||
global.Jwt = jwt.NewJwt(global.Config.Jwt.Key, global.Config.Jwt.ExpireDuration)
|
global.Jwt = jwt.NewJwt(global.Config.Jwt.Key, global.Config.Jwt.ExpireDuration*time.Second)
|
||||||
|
|
||||||
//locker
|
//locker
|
||||||
global.Lock = lock.NewLocal()
|
global.Lock = lock.NewLocal()
|
||||||
|
|
||||||
//service
|
|
||||||
service.New(&global.Config, global.DB, global.Logger, global.Jwt, global.Lock)
|
|
||||||
|
|
||||||
global.LoginLimiter = utils.NewLoginLimiter(utils.SecurityPolicy{
|
|
||||||
CaptchaThreshold: global.Config.App.CaptchaThreshold,
|
|
||||||
BanThreshold: global.Config.App.BanThreshold,
|
|
||||||
AttemptsWindow: 10 * time.Minute,
|
|
||||||
BanDuration: 30 * time.Minute,
|
|
||||||
})
|
|
||||||
global.LoginLimiter.RegisterProvider(utils.B64StringCaptchaProvider{})
|
|
||||||
DatabaseAutoUpdate()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DatabaseAutoUpdate() {
|
func DatabaseAutoUpdate() {
|
||||||
version := DatabaseVersion
|
version := 260
|
||||||
|
|
||||||
db := global.DB
|
db := global.DB
|
||||||
|
|
||||||
if global.Config.Gorm.Type == config.TypeMysql {
|
if global.Config.Gorm.Type == config.TypeMysql {
|
||||||
// check whether the database exists; create it if not
|
//检查存不存在数据库,不存在则创建
|
||||||
dbName := db.Migrator().CurrentDatabase()
|
dbName := db.Migrator().CurrentDatabase()
|
||||||
|
fmt.Println("dbName", dbName)
|
||||||
if dbName == "" {
|
if dbName == "" {
|
||||||
dbName = global.Config.Mysql.Dbname
|
dbName = global.Config.Mysql.Dbname
|
||||||
// remove the database name from the DSN so the initial connection does not specify a database
|
// 移除 DSN 中的数据库名称,以便初始连接时不指定数据库
|
||||||
dsnWithoutDB := fmt.Sprintf("%s:%s@(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
dsnWithoutDB := global.Config.Mysql.Username + ":" + global.Config.Mysql.Password + "@(" + global.Config.Mysql.Addr + ")/?charset=utf8mb4&parseTime=True&loc=Local"
|
||||||
global.Config.Mysql.Username,
|
//新链接
|
||||||
global.Config.Mysql.Password,
|
|
||||||
global.Config.Mysql.Addr,
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
|
|
||||||
// new connection
|
|
||||||
dbWithoutDB := orm.NewMysql(&orm.MysqlConfig{
|
dbWithoutDB := orm.NewMysql(&orm.MysqlConfig{
|
||||||
Dsn: dsnWithoutDB,
|
Dns: dsnWithoutDB,
|
||||||
}, global.Logger)
|
})
|
||||||
// get the underlying *sql.DB object and ensure the connection is closed when the program exits
|
// 获取底层的 *sql.DB 对象,并确保在程序退出时关闭连接
|
||||||
sqlDBWithoutDB, err := dbWithoutDB.DB()
|
sqlDBWithoutDB, err := dbWithoutDB.DB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Errorf("failed to get underlying *sql.DB object: %v", err)
|
fmt.Printf("获取底层 *sql.DB 对象失败: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := sqlDBWithoutDB.Close(); err != nil {
|
if err := sqlDBWithoutDB.Close(); err != nil {
|
||||||
global.Logger.Errorf("failed to close connection: %v", err)
|
fmt.Printf("关闭连接失败: %v\n", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = dbWithoutDB.Exec("CREATE DATABASE IF NOT EXISTS " + dbName + " DEFAULT CHARSET utf8mb4").Error
|
err = dbWithoutDB.Exec("CREATE DATABASE IF NOT EXISTS " + dbName + " DEFAULT CHARSET utf8mb4").Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,20 +207,19 @@ func DatabaseAutoUpdate() {
|
|||||||
if !db.Migrator().HasTable(&model.Version{}) {
|
if !db.Migrator().HasTable(&model.Version{}) {
|
||||||
Migrate(uint(version))
|
Migrate(uint(version))
|
||||||
} else {
|
} else {
|
||||||
// find the last version
|
//查找最后一个version
|
||||||
var v model.Version
|
var v model.Version
|
||||||
db.Last(&v)
|
db.Last(&v)
|
||||||
if v.Version < uint(version) {
|
if v.Version < uint(version) {
|
||||||
Migrate(uint(version))
|
Migrate(uint(version))
|
||||||
}
|
}
|
||||||
|
// 245迁移
|
||||||
// 245 migration
|
|
||||||
if v.Version < 245 {
|
if v.Version < 245 {
|
||||||
// set the oauths table's oauth_type field to the same value as op
|
//oauths 表的 oauth_type 字段设置为 op同样的值
|
||||||
db.Exec("update oauths set oauth_type = op")
|
db.Exec("update oauths set oauth_type = op")
|
||||||
db.Exec("update oauths set issuer = 'https://accounts.google.com' where op = 'google'")
|
db.Exec("update oauths set issuer = 'https://accounts.google.com' where op = 'google'")
|
||||||
db.Exec("update user_thirds set oauth_type = third_type, op = third_type")
|
db.Exec("update user_thirds set oauth_type = third_type, op = third_type")
|
||||||
// migrate old google authorizations by email
|
//通过email迁移旧的google授权
|
||||||
uts := make([]model.UserThird, 0)
|
uts := make([]model.UserThird, 0)
|
||||||
db.Where("oauth_type = ?", "google").Find(&uts)
|
db.Where("oauth_type = ?", "google").Find(&uts)
|
||||||
for _, ut := range uts {
|
for _, ut := range uts {
|
||||||
@@ -287,7 +235,7 @@ func DatabaseAutoUpdate() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
func Migrate(version uint) {
|
func Migrate(version uint) {
|
||||||
global.Logger.Info("Migrating....", version)
|
fmt.Println("migrating....", version)
|
||||||
err := global.DB.AutoMigrate(
|
err := global.DB.AutoMigrate(
|
||||||
&model.Version{},
|
&model.Version{},
|
||||||
&model.User{},
|
&model.User{},
|
||||||
@@ -305,13 +253,12 @@ func Migrate(version uint) {
|
|||||||
&model.AddressBookCollection{},
|
&model.AddressBookCollection{},
|
||||||
&model.AddressBookCollectionRule{},
|
&model.AddressBookCollectionRule{},
|
||||||
&model.ServerCmd{},
|
&model.ServerCmd{},
|
||||||
&model.DeviceGroup{},
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.Logger.Error("migrate err :=>", err)
|
fmt.Println("migrate err :=>", err)
|
||||||
}
|
}
|
||||||
global.DB.Create(&model.Version{Version: version})
|
global.DB.Create(&model.Version{Version: version})
|
||||||
// if this is the first run, create a default user
|
//如果是初次则创建一个默认用户
|
||||||
var vc int64
|
var vc int64
|
||||||
global.DB.Model(&model.Version{}).Count(&vc)
|
global.DB.Model(&model.Version{}).Count(&vc)
|
||||||
if vc == 1 {
|
if vc == 1 {
|
||||||
@@ -333,7 +280,7 @@ func Migrate(version uint) {
|
|||||||
Type: model.GroupTypeShare,
|
Type: model.GroupTypeShare,
|
||||||
}
|
}
|
||||||
service.AllService.GroupService.Create(groupShare)
|
service.AllService.GroupService.Create(groupShare)
|
||||||
// is true
|
//是true
|
||||||
is_admin := true
|
is_admin := true
|
||||||
admin := &model.User{
|
admin := &model.User{
|
||||||
Username: "admin",
|
Username: "admin",
|
||||||
@@ -342,15 +289,7 @@ func Migrate(version uint) {
|
|||||||
IsAdmin: &is_admin,
|
IsAdmin: &is_admin,
|
||||||
GroupId: 1,
|
GroupId: 1,
|
||||||
}
|
}
|
||||||
|
admin.Password = service.AllService.UserService.EncryptPassword("admin")
|
||||||
// generate a random password
|
|
||||||
pwd := utils.RandomString(8)
|
|
||||||
global.Logger.Info("Admin Password Is: ", pwd)
|
|
||||||
var err error
|
|
||||||
admin.Password, err = utils.EncryptPassword(pwd)
|
|
||||||
if err != nil {
|
|
||||||
global.Logger.Fatalf("failed to generate admin password: %v", err)
|
|
||||||
}
|
|
||||||
global.DB.Create(admin)
|
global.DB.Create(admin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
### 👏👏👏 你好 ***{{username}}***, 欢迎使用 [RustDesk Api](https://github.com/lejianwen/rustdesk-api)
|
||||||
+26
-51
@@ -1,26 +1,16 @@
|
|||||||
lang: "en"
|
lang: "zh-CN"
|
||||||
app:
|
app:
|
||||||
web-client: 1 # 1:enable 0:disable
|
web-client: 1 # 1:启用 0:禁用
|
||||||
register: false #whether registration is enabled
|
register: false #是否开启注册
|
||||||
register-status: 1 # default status for registered users 1:enable 2:disable
|
show-swagger: 0 # 1:启用 0:禁用
|
||||||
captcha-threshold: 3 # <0:disabled, 0 always, >0:enabled
|
|
||||||
ban-threshold: 0 # 0:disabled, >0:enabled
|
|
||||||
show-swagger: 0 # 1:enable 0:disable
|
|
||||||
token-expire: 168h
|
|
||||||
web-sso: true #web auth sso
|
|
||||||
disable-pwd-login: false #disable password login
|
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
title: "RustDesk API Admin"
|
title: "RustDesk Api Admin"
|
||||||
hello-file: "./conf/admin/hello.html" #prefer to use a file for the welcome message
|
hello-file: "./conf/admin/hello.html" #优先使用file
|
||||||
hello: ""
|
hello: ""
|
||||||
# ID Server and Relay Server ports https://github.com/lejianwen/rustdesk-api/issues/257
|
|
||||||
id-server-port: 21116 # ID Server port (for server cmd)
|
|
||||||
relay-server-port: 21117 # ID Server port (for server cmd)
|
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release" #release,debug,test
|
mode: "release" #release,debug,test
|
||||||
resources-path: 'resources' #public static file directory
|
resources-path: 'resources' #对外静态文件目录
|
||||||
trust-proxy: ""
|
trust-proxy: ""
|
||||||
gorm:
|
gorm:
|
||||||
type: "sqlite"
|
type: "sqlite"
|
||||||
@@ -31,17 +21,6 @@ mysql:
|
|||||||
password: ""
|
password: ""
|
||||||
addr: ""
|
addr: ""
|
||||||
dbname: ""
|
dbname: ""
|
||||||
tls: "false" # true / false / skip-verify / custom
|
|
||||||
|
|
||||||
postgresql:
|
|
||||||
host: "127.0.0.1"
|
|
||||||
port: "5432"
|
|
||||||
user: ""
|
|
||||||
password: ""
|
|
||||||
dbname: "postgres"
|
|
||||||
sslmode: "disable" # disable, require, verify-ca, verify-full
|
|
||||||
time-zone: "Asia/Shanghai" # Time zone for PostgreSQL connection
|
|
||||||
|
|
||||||
rustdesk:
|
rustdesk:
|
||||||
id-server: "192.168.1.66:21116"
|
id-server: "192.168.1.66:21116"
|
||||||
relay-server: "192.168.1.66:21117"
|
relay-server: "192.168.1.66:21117"
|
||||||
@@ -50,35 +29,31 @@ rustdesk:
|
|||||||
key-file: "/data/id_ed25519.pub"
|
key-file: "/data/id_ed25519.pub"
|
||||||
personal: 1
|
personal: 1
|
||||||
webclient-magic-queryonline: 0
|
webclient-magic-queryonline: 0
|
||||||
ws-host: "" #eg: wss://192.168.1.3:4443
|
|
||||||
logger:
|
logger:
|
||||||
path: "./runtime/log.txt"
|
path: "./runtime/log.txt"
|
||||||
level: "info" #trace,debug,info,warn,error,fatal
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
report-caller: true
|
report-caller: true
|
||||||
proxy:
|
proxy:
|
||||||
enable: false
|
enable: false
|
||||||
host: "http://127.0.0.1:1080"
|
host: "http://127.0.0.1:1080"
|
||||||
jwt:
|
jwt:
|
||||||
key: ""
|
key: ""
|
||||||
expire-duration: 168h
|
expire-duration: 360000
|
||||||
ldap:
|
redis:
|
||||||
enable: false
|
addr: "127.0.0.1:6379"
|
||||||
url: "ldap://ldap.example.com:389"
|
password: ""
|
||||||
tls-ca-file: ""
|
db: 0
|
||||||
tls-verify: false
|
cache:
|
||||||
base-dn: "dc=example,dc=com"
|
type: "file"
|
||||||
bind-dn: "cn=admin,dc=example,dc=com"
|
file-dir: "./runtime/cache"
|
||||||
bind-password: "password"
|
redis-addr: "127.0.0.1:6379"
|
||||||
|
redis-pwd: ""
|
||||||
|
redis-db: 0
|
||||||
|
oss:
|
||||||
|
access-key-id: ""
|
||||||
|
access-key-secret: ""
|
||||||
|
host: ""
|
||||||
|
callback-url: ""
|
||||||
|
expire-time: 30
|
||||||
|
max-byte: 10240
|
||||||
|
|
||||||
user:
|
|
||||||
base-dn: "ou=users,dc=example,dc=com"
|
|
||||||
enable-attr: "" #The attribute name of the user for enabling, in AD it is "userAccountControl", empty means no enable attribute, all users are enabled
|
|
||||||
enable-attr-value: "" # The value of the enable attribute when the user is enabled. If you are using AD, just set random value, it will be ignored.
|
|
||||||
filter: "(cn=*)"
|
|
||||||
username: "uid" # The attribute name of the user for usernamem if you are using AD, it should be "sAMAccountName"
|
|
||||||
email: "mail"
|
|
||||||
first-name: "givenName"
|
|
||||||
last-name: "sn"
|
|
||||||
sync: false # If true, the user will be synchronized to the database when the user logs in. If false, the user will be synchronized to the database when the user be created.
|
|
||||||
admin-group: "cn=admin,dc=example,dc=com" # The group name of the admin group, if the user is in this group, the user will be an admin.
|
|
||||||
allow-group: "cn=users,dc=example,dc=com" # The group name of the users group, if the user is in this group, the user will be an login.
|
|
||||||
|
|||||||
+6
-30
@@ -2,9 +2,9 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -16,20 +16,12 @@ const (
|
|||||||
type App struct {
|
type App struct {
|
||||||
WebClient int `mapstructure:"web-client"`
|
WebClient int `mapstructure:"web-client"`
|
||||||
Register bool `mapstructure:"register"`
|
Register bool `mapstructure:"register"`
|
||||||
RegisterStatus int `mapstructure:"register-status"`
|
|
||||||
ShowSwagger int `mapstructure:"show-swagger"`
|
ShowSwagger int `mapstructure:"show-swagger"`
|
||||||
TokenExpire time.Duration `mapstructure:"token-expire"`
|
|
||||||
WebSso bool `mapstructure:"web-sso"`
|
|
||||||
DisablePwdLogin bool `mapstructure:"disable-pwd-login"`
|
|
||||||
CaptchaThreshold int `mapstructure:"captcha-threshold"`
|
|
||||||
BanThreshold int `mapstructure:"ban-threshold"`
|
|
||||||
}
|
}
|
||||||
type Admin struct {
|
type Admin struct {
|
||||||
Title string `mapstructure:"title"`
|
Title string `mapstructure:"title"`
|
||||||
Hello string `mapstructure:"hello"`
|
Hello string `mapstructure:"hello"`
|
||||||
HelloFile string `mapstructure:"hello-file"`
|
HelloFile string `mapstructure:"hello-file"`
|
||||||
IdServerPort int `mapstructure:"id-server-port"`
|
|
||||||
RelayServerPort int `mapstructure:"relay-server-port"`
|
|
||||||
}
|
}
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Lang string `mapstructure:"lang"`
|
Lang string `mapstructure:"lang"`
|
||||||
@@ -37,7 +29,6 @@ type Config struct {
|
|||||||
Admin Admin
|
Admin Admin
|
||||||
Gorm Gorm
|
Gorm Gorm
|
||||||
Mysql Mysql
|
Mysql Mysql
|
||||||
Postgresql Postgresql
|
|
||||||
Gin Gin
|
Gin Gin
|
||||||
Logger Logger
|
Logger Logger
|
||||||
Redis Redis
|
Redis Redis
|
||||||
@@ -46,19 +37,9 @@ type Config struct {
|
|||||||
Jwt Jwt
|
Jwt Jwt
|
||||||
Rustdesk Rustdesk
|
Rustdesk Rustdesk
|
||||||
Proxy Proxy
|
Proxy Proxy
|
||||||
Ldap Ldap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Admin) Init() {
|
// Init 初始化配置
|
||||||
if a.IdServerPort == 0 {
|
|
||||||
a.IdServerPort = DefaultIdServerPort
|
|
||||||
}
|
|
||||||
if a.RelayServerPort == 0 {
|
|
||||||
a.RelayServerPort = DefaultRelayServerPort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes the configuration
|
|
||||||
func Init(rowVal *Config, path string) *viper.Viper {
|
func Init(rowVal *Config, path string) *viper.Viper {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = DefaultConfig
|
path = DefaultConfig
|
||||||
@@ -73,13 +54,9 @@ func Init(rowVal *Config, path string) *viper.Viper {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
v.WatchConfig()
|
v.WatchConfig()
|
||||||
|
|
||||||
|
|
||||||
// watching for config changes is not really necessary
|
|
||||||
v.OnConfigChange(func(e fsnotify.Event) {
|
v.OnConfigChange(func(e fsnotify.Event) {
|
||||||
// watch for config file changes
|
//配置文件修改监听
|
||||||
fmt.Println("config file changed:", e.Name)
|
fmt.Println("config file changed:", e.Name)
|
||||||
if err2 := v.Unmarshal(rowVal); err2 != nil {
|
if err2 := v.Unmarshal(rowVal); err2 != nil {
|
||||||
fmt.Println(err2)
|
fmt.Println(err2)
|
||||||
@@ -87,16 +64,15 @@ func Init(rowVal *Config, path string) *viper.Viper {
|
|||||||
rowVal.Rustdesk.LoadKeyFile()
|
rowVal.Rustdesk.LoadKeyFile()
|
||||||
rowVal.Rustdesk.ParsePort()
|
rowVal.Rustdesk.ParsePort()
|
||||||
})
|
})
|
||||||
*/
|
|
||||||
if err := v.Unmarshal(rowVal); err != nil {
|
if err := v.Unmarshal(rowVal); err != nil {
|
||||||
panic(fmt.Errorf("Fatal error config: %s \n", err))
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
rowVal.Rustdesk.LoadKeyFile()
|
rowVal.Rustdesk.LoadKeyFile()
|
||||||
rowVal.Admin.Init()
|
rowVal.Rustdesk.ParsePort()
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadEnv reads environment variables
|
// ReadEnv 读取环境变量
|
||||||
func ReadEnv(rowVal interface{}) *viper.Viper {
|
func ReadEnv(rowVal interface{}) *viper.Viper {
|
||||||
v := viper.New()
|
v := viper.New()
|
||||||
v.AutomaticEnv()
|
v.AutomaticEnv()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package config
|
|||||||
const (
|
const (
|
||||||
TypeSqlite = "sqlite"
|
TypeSqlite = "sqlite"
|
||||||
TypeMysql = "mysql"
|
TypeMysql = "mysql"
|
||||||
TypePostgresql = "postgresql"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Gorm struct {
|
type Gorm struct {
|
||||||
@@ -17,15 +16,4 @@ type Mysql struct {
|
|||||||
Username string `mapstructure:"username"`
|
Username string `mapstructure:"username"`
|
||||||
Password string `mapstructure:"password"`
|
Password string `mapstructure:"password"`
|
||||||
Dbname string `mapstructure:"dbname"`
|
Dbname string `mapstructure:"dbname"`
|
||||||
Tls string `mapstructure:"tls"` // true / false / skip-verify / custom
|
|
||||||
}
|
|
||||||
|
|
||||||
type Postgresql struct {
|
|
||||||
Host string `mapstructure:"host"`
|
|
||||||
Port string `mapstructure:"port"`
|
|
||||||
User string `mapstructure:"user"`
|
|
||||||
Password string `mapstructure:"password"`
|
|
||||||
Dbname string `mapstructure:"dbname"`
|
|
||||||
Sslmode string `mapstructure:"sslmode"` // "disable", "require", "verify-ca", "verify-full"
|
|
||||||
TimeZone string `mapstructure:"time-zone"` // e.g., "Asia/Shanghai"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
type LdapUser struct {
|
|
||||||
BaseDn string `mapstructure:"base-dn"` // The base DN of the user for searching
|
|
||||||
EnableAttr string `mapstructure:"enable-attr"` // The attribute name of the user for enabling, in AD it is "userAccountControl", empty means no enable attribute, all users are enabled
|
|
||||||
EnableAttrValue string `mapstructure:"enable-attr-value"` // The value of the enable attribute when the user is enabled. If you are using AD, just leave it random str, it will be ignored.
|
|
||||||
Filter string `mapstructure:"filter"`
|
|
||||||
Username string `mapstructure:"username"`
|
|
||||||
Email string `mapstructure:"email"`
|
|
||||||
FirstName string `mapstructure:"first-name"`
|
|
||||||
LastName string `mapstructure:"last-name"`
|
|
||||||
Sync bool `mapstructure:"sync"` // Will sync the user's information to the internal database
|
|
||||||
AdminGroup string `mapstructure:"admin-group"` // Which group is the admin group
|
|
||||||
AllowGroup string `mapstructure:"allow-group"` // Which group is allowed to login
|
|
||||||
}
|
|
||||||
|
|
||||||
// type LdapGroup struct {
|
|
||||||
// BaseDn string `mapstructure:"base-dn"` // The base DN of the group for searching
|
|
||||||
// Name string `mapstructure:"name"` // The attribute name of the group
|
|
||||||
// Filter string `mapstructure:"filter"`
|
|
||||||
// Admin string `mapstructure:"admin"` // Which group is the admin group
|
|
||||||
// Member string `mapstructure:"member"` // How to get the member of the group: member, uniqueMember, or memberOf (default: member)
|
|
||||||
// Mode string `mapstructure:"mode"`
|
|
||||||
// Map map[string]string `mapstructure:"map"` // If mode is "map", map the LDAP group to the internal group
|
|
||||||
// }
|
|
||||||
|
|
||||||
type Ldap struct {
|
|
||||||
Enable bool `mapstructure:"enable"`
|
|
||||||
Url string `mapstructure:"url"`
|
|
||||||
TlsCaFile string `mapstructure:"tls-ca-file"`
|
|
||||||
TlsVerify bool `mapstructure:"tls-verify"`
|
|
||||||
BaseDn string `mapstructure:"base-dn"`
|
|
||||||
BindDn string `mapstructure:"bind-dn"`
|
|
||||||
BindPassword string `mapstructure:"bind-password"`
|
|
||||||
User LdapUser `mapstructure:"user"`
|
|
||||||
// Group LdapGroup `mapstructure:"group"`
|
|
||||||
}
|
|
||||||
+3
-5
@@ -3,20 +3,18 @@ package config
|
|||||||
type GithubOauth struct {
|
type GithubOauth struct {
|
||||||
ClientId string `mapstructure:"client-id"`
|
ClientId string `mapstructure:"client-id"`
|
||||||
ClientSecret string `mapstructure:"client-secret"`
|
ClientSecret string `mapstructure:"client-secret"`
|
||||||
|
RedirectUrl string `mapstructure:"redirect-url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GoogleOauth struct {
|
type GoogleOauth struct {
|
||||||
ClientId string `mapstructure:"client-id"`
|
ClientId string `mapstructure:"client-id"`
|
||||||
ClientSecret string `mapstructure:"client-secret"`
|
ClientSecret string `mapstructure:"client-secret"`
|
||||||
|
RedirectUrl string `mapstructure:"redirect-url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OidcOauth struct {
|
type OidcOauth struct {
|
||||||
Issuer string `mapstructure:"issuer"`
|
Issuer string `mapstructure:"issuer"`
|
||||||
ClientId string `mapstructure:"client-id"`
|
ClientId string `mapstructure:"client-id"`
|
||||||
ClientSecret string `mapstructure:"client-secret"`
|
ClientSecret string `mapstructure:"client-secret"`
|
||||||
}
|
RedirectUrl string `mapstructure:"redirect-url"`
|
||||||
|
|
||||||
type LinuxdoOauth struct {
|
|
||||||
ClientId string `mapstructure:"client-id"`
|
|
||||||
ClientSecret string `mapstructure:"client-secret"`
|
|
||||||
}
|
}
|
||||||
+18
-1
@@ -2,6 +2,8 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -20,7 +22,6 @@ type Rustdesk struct {
|
|||||||
Personal int `mapstructure:"personal"`
|
Personal int `mapstructure:"personal"`
|
||||||
//webclient-magic-queryonline
|
//webclient-magic-queryonline
|
||||||
WebclientMagicQueryonline int `mapstructure:"webclient-magic-queryonline"`
|
WebclientMagicQueryonline int `mapstructure:"webclient-magic-queryonline"`
|
||||||
WsHost string `mapstructure:"ws-host"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rd *Rustdesk) LoadKeyFile() {
|
func (rd *Rustdesk) LoadKeyFile() {
|
||||||
@@ -38,3 +39,19 @@ func (rd *Rustdesk) LoadKeyFile() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (rd *Rustdesk) ParsePort() {
|
||||||
|
// Parse port
|
||||||
|
idres := strings.Split(rd.IdServer, ":")
|
||||||
|
if len(idres) == 1 {
|
||||||
|
rd.IdServerPort = DefaultIdServerPort
|
||||||
|
} else if len(idres) == 2 {
|
||||||
|
rd.IdServerPort, _ = strconv.Atoi(idres[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
relayres := strings.Split(rd.RelayServer, ":")
|
||||||
|
if len(relayres) == 1 {
|
||||||
|
rd.RelayServerPort = DefaultRelayServerPort
|
||||||
|
} else if len(relayres) == 2 {
|
||||||
|
rd.RelayServerPort, _ = strconv.Atoi(relayres[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ services:
|
|||||||
dockerfile: Dockerfile.dev
|
dockerfile: Dockerfile.dev
|
||||||
args:
|
args:
|
||||||
COUNTRY: CN
|
COUNTRY: CN
|
||||||
FRONTEND_GIT_REPO: https://github.com/lejianwen/rustdesk-api-web.git
|
FREONTEND_GIT_REPO: https://github.com/lejianwen/rustdesk-api-web.git
|
||||||
FRONTEND_GIT_BRANCH: master
|
FRONTEND_GIT_BRANCH: master
|
||||||
# image: lejianwen/rustdesk-api
|
# image: lejianwen/rustdesk-api
|
||||||
container_name: rustdesk-api
|
container_name: rustdesk-api
|
||||||
@@ -18,7 +18,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 21114:21114
|
- 21114:21114
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/rustdesk/api:/app/data #mount the database out for easy backup
|
- ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
||||||
- ./conf:/app/conf # config
|
- ./conf:/app/conf # config
|
||||||
# - ./resources:/app/resources # static resources
|
# - ./resources:/app/resources # 静态资源
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
+1
-1
@@ -13,5 +13,5 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./data/rustdesk/api:/app/data # database
|
- ./data/rustdesk/api:/app/data # database
|
||||||
# - ./conf:/app/conf # config
|
# - ./conf:/app/conf # config
|
||||||
# - ./resources:/app/resources # static resources
|
# - ./resources:/app/resources # 静态资源
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# RustDesk full stack (server + relay + API/Web Admin) — self-contained example.
|
|
||||||
#
|
|
||||||
# Copy to docker-compose.yml and adjust the public IP / keys / secrets:
|
|
||||||
# cp docker-compose.yml.example docker-compose.yml
|
|
||||||
#
|
|
||||||
# Everything is inline (no .env). The Ed25519 key below is an EXAMPLE — generate
|
|
||||||
# your own for production. The two keys belong together:
|
|
||||||
# - hbbs/hbbr get the SECRET key via -k
|
|
||||||
# - rustdesk-api gets the matching PUBLIC key via RUSTDESK_API_RUSTDESK_KEY
|
|
||||||
# (the public key is also what clients see as their "Key").
|
|
||||||
|
|
||||||
services:
|
|
||||||
hbbs:
|
|
||||||
container_name: hbbs
|
|
||||||
image: rustdesk/rustdesk-server:latest
|
|
||||||
command: hbbs -r 194.164.204.114:21117 -k 1jqLELJaIjaRtt1Tcj6BhqJ7DhT9WszBH/XUHrqJdhdg4K98HmANQFOpUx/vPZFRWnHPTYYHyIB8uH3Xxr8PTw==
|
|
||||||
environment:
|
|
||||||
- TZ=Europe/Berlin
|
|
||||||
- ENCRYPTED_ONLY=1
|
|
||||||
- MUST_LOGIN=Y
|
|
||||||
volumes:
|
|
||||||
- ./data/server:/root
|
|
||||||
ports:
|
|
||||||
- "21115:21115"
|
|
||||||
- "21116:21116"
|
|
||||||
- "21116:21116/udp"
|
|
||||||
- "21118:21118"
|
|
||||||
depends_on:
|
|
||||||
- hbbr
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
hbbr:
|
|
||||||
container_name: hbbr
|
|
||||||
image: rustdesk/rustdesk-server:latest
|
|
||||||
command: hbbr -k 1jqLELJaIjaRtt1Tcj6BhqJ7DhT9WszBH/XUHrqJdhdg4K98HmANQFOpUx/vPZFRWnHPTYYHyIB8uH3Xxr8PTw==
|
|
||||||
environment:
|
|
||||||
- TZ=Europe/Berlin
|
|
||||||
volumes:
|
|
||||||
- ./data/server:/root
|
|
||||||
ports:
|
|
||||||
- "21117:21117"
|
|
||||||
- "21119:21119"
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
rustdesk-api:
|
|
||||||
container_name: rustdesk-api
|
|
||||||
image: git.hackner.dev/thomas/rustdesk-api:latest
|
|
||||||
command: ["./apimain"]
|
|
||||||
environment:
|
|
||||||
- TZ=Europe/Berlin
|
|
||||||
- RUSTDESK_API_LANG=en
|
|
||||||
- RUSTDESK_API_RUSTDESK_ID_SERVER=194.164.204.114:21116
|
|
||||||
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=194.164.204.114:21117
|
|
||||||
- RUSTDESK_API_RUSTDESK_API_SERVER=http://194.164.204.114:21114
|
|
||||||
- RUSTDESK_API_RUSTDESK_KEY=YOCvfB5gDUBTqVMf7z2RUVpxz02GB8iAfLh918a/D08=
|
|
||||||
- RUSTDESK_API_JWT_KEY=z5rt4z465rtzdh5sudtuzrutd66zz6
|
|
||||||
ports:
|
|
||||||
- "21114:21114"
|
|
||||||
volumes:
|
|
||||||
- ./api:/app/data
|
|
||||||
depends_on:
|
|
||||||
- hbbs
|
|
||||||
- hbbr
|
|
||||||
restart: unless-stopped
|
|
||||||
+489
-944
File diff suppressed because it is too large
Load Diff
+489
-944
File diff suppressed because it is too large
Load Diff
+452
-725
File diff suppressed because it is too large
Load Diff
+174
-255
@@ -17,7 +17,7 @@ const docTemplateapi = `{
|
|||||||
"paths": {
|
"paths": {
|
||||||
"/": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "home",
|
"description": "首页",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -25,9 +25,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"home"
|
"首页"
|
||||||
],
|
],
|
||||||
"summary": "home",
|
"summary": "首页",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -51,7 +51,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "address list",
|
"description": "地址列表",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -59,9 +59,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "address list",
|
"summary": "地址列表",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -83,7 +83,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "address update",
|
"description": "地址更新",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -91,12 +91,12 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "address update",
|
"summary": "地址更新",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "address form",
|
"description": "地址表单",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -128,7 +128,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "add address",
|
"description": "添加地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -136,9 +136,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "add address",
|
"summary": "添加地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -169,7 +169,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "delete address",
|
"description": "删除地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -177,9 +177,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "delete address",
|
"summary": "删除地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -212,7 +212,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "update address",
|
"description": "更新地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -220,9 +220,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "update address",
|
"summary": "更新地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -255,7 +255,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "address",
|
"description": "地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -263,19 +263,19 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "address list",
|
"summary": "地址列表",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "current",
|
"name": "current",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@@ -309,7 +309,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "personal address",
|
"description": "个人地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -317,9 +317,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "personal address",
|
"summary": "个人地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"description": "string valid",
|
||||||
@@ -353,7 +353,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "settings",
|
"description": "设置",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -361,9 +361,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "settings",
|
"summary": "设置",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"description": "string valid",
|
||||||
@@ -397,7 +397,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "shared",
|
"description": "共享",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -405,19 +405,19 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "shared address book",
|
"summary": "共享地址簿",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "current",
|
"name": "current",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
}
|
}
|
||||||
@@ -445,7 +445,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -453,9 +453,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "add tag",
|
"summary": "标签添加",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -488,7 +488,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -496,9 +496,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "rename tag",
|
"summary": "标签重命名",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -531,7 +531,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -539,9 +539,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "change tag color",
|
"summary": "标签修改颜色",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -574,7 +574,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -582,9 +582,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "delete tag",
|
"summary": "标签删除",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -617,7 +617,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -625,9 +625,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "tag",
|
"summary": "标签",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -653,9 +653,14 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/audit/conn": {
|
"/api": {
|
||||||
"post": {
|
"get": {
|
||||||
"description": "audit connection",
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "用户信息",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -663,12 +668,41 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"audit"
|
"用户"
|
||||||
],
|
],
|
||||||
"summary": "audit connection",
|
"summary": "用户信息",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.UserPayload"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/audit/conn": {
|
||||||
|
"post": {
|
||||||
|
"description": "审计连接",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"审计"
|
||||||
|
],
|
||||||
|
"summary": "审计连接",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "audit connection",
|
"description": "审计连接",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -695,7 +729,7 @@ const docTemplateapi = `{
|
|||||||
},
|
},
|
||||||
"/audit/file": {
|
"/audit/file": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "audit file",
|
"description": "审计文件",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -703,12 +737,12 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"audit"
|
"审计"
|
||||||
],
|
],
|
||||||
"summary": "audit file",
|
"summary": "审计文件",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "audit file",
|
"description": "审计文件",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -733,103 +767,9 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/currentUser": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"token": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "user info",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
"summary": "user info",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/api.UserPayload"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/device-group/accessible": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "machine",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"group"
|
|
||||||
],
|
|
||||||
"summary": "device",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "page number",
|
|
||||||
"name": "page",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "items per page",
|
|
||||||
"name": "pageSize",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "status",
|
|
||||||
"name": "status",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "accessible",
|
|
||||||
"name": "accessible",
|
|
||||||
"in": "query"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.DataResponse"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/heartbeat": {
|
"/heartbeat": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "heartbeat",
|
"description": "心跳",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -837,9 +777,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"home"
|
"首页"
|
||||||
],
|
],
|
||||||
"summary": "heartbeat",
|
"summary": "心跳",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
@@ -855,7 +795,7 @@ const docTemplateapi = `{
|
|||||||
},
|
},
|
||||||
"/login": {
|
"/login": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "login",
|
"description": "登录",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -863,12 +803,12 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"login"
|
"登录"
|
||||||
],
|
],
|
||||||
"summary": "login",
|
"summary": "登录",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "login form",
|
"description": "登录表单",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -895,7 +835,7 @@ const docTemplateapi = `{
|
|||||||
},
|
},
|
||||||
"/login-options": {
|
"/login-options": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "login options",
|
"description": "登录选项",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -903,9 +843,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"login"
|
"登录"
|
||||||
],
|
],
|
||||||
"summary": "login options",
|
"summary": "登录选项",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -927,7 +867,7 @@ const docTemplateapi = `{
|
|||||||
},
|
},
|
||||||
"/logout": {
|
"/logout": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "logout",
|
"description": "登出",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -935,9 +875,9 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"login"
|
"登录"
|
||||||
],
|
],
|
||||||
"summary": "logout",
|
"summary": "登出",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -954,6 +894,35 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/oauth/callback": {
|
||||||
|
"get": {
|
||||||
|
"description": "OauthCallback",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Oauth"
|
||||||
|
],
|
||||||
|
"summary": "OauthCallback",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.LoginRes"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/oidc/auth": {
|
"/oidc/auth": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "OidcAuth",
|
"description": "OidcAuth",
|
||||||
@@ -1012,35 +981,6 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/oidc/callback": {
|
|
||||||
"get": {
|
|
||||||
"description": "OauthCallback",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Oauth"
|
|
||||||
],
|
|
||||||
"summary": "OauthCallback",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/api.LoginRes"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.ErrorResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/peers": {
|
"/peers": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1048,7 +988,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "machine",
|
"description": "机器",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1056,25 +996,25 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"group"
|
"群组"
|
||||||
],
|
],
|
||||||
"summary": "machine",
|
"summary": "机器",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "page",
|
"name": "page",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "status",
|
"description": "状态",
|
||||||
"name": "status",
|
"name": "status",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@@ -1108,7 +1048,7 @@ const docTemplateapi = `{
|
|||||||
"token": []
|
"token": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "service config, provides an api-server for the webclient",
|
"description": "服务配置,给webclient提供api-server",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1118,7 +1058,7 @@ const docTemplateapi = `{
|
|||||||
"tags": [
|
"tags": [
|
||||||
"WEBCLIENT"
|
"WEBCLIENT"
|
||||||
],
|
],
|
||||||
"summary": "service config",
|
"summary": "服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -1142,7 +1082,7 @@ const docTemplateapi = `{
|
|||||||
"token": []
|
"token": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "service config, provides an api-server for the webclient",
|
"description": "服务配置,给webclient提供api-server",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1152,7 +1092,7 @@ const docTemplateapi = `{
|
|||||||
"tags": [
|
"tags": [
|
||||||
"WEBCLIENT_V2"
|
"WEBCLIENT_V2"
|
||||||
],
|
],
|
||||||
"summary": "service config",
|
"summary": "服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -1171,7 +1111,7 @@ const docTemplateapi = `{
|
|||||||
},
|
},
|
||||||
"/shared-peer": {
|
"/shared-peer": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "shared peer",
|
"description": "分享的peer",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1181,7 +1121,7 @@ const docTemplateapi = `{
|
|||||||
"tags": [
|
"tags": [
|
||||||
"WEBCLIENT"
|
"WEBCLIENT"
|
||||||
],
|
],
|
||||||
"summary": "shared peer",
|
"summary": "分享的peer",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -1200,7 +1140,7 @@ const docTemplateapi = `{
|
|||||||
},
|
},
|
||||||
"/sysinfo": {
|
"/sysinfo": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "submit system info",
|
"description": "提交系统信息",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1208,12 +1148,12 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"System"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "submit system info",
|
"summary": "提交系统信息",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "system info form",
|
"description": "系统信息表单",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -1238,9 +1178,14 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/sysinfo_ver": {
|
"/tags": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "get system version info",
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1248,14 +1193,17 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"System"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "get system version info",
|
"summary": "标签",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/model.Tag"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
@@ -1274,7 +1222,7 @@ const docTemplateapi = `{
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "user list",
|
"description": "用户列表",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1282,25 +1230,25 @@ const docTemplateapi = `{
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"group"
|
"群组"
|
||||||
],
|
],
|
||||||
"summary": "user list",
|
"summary": "用户列表",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "page",
|
"name": "page",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "status",
|
"description": "状态",
|
||||||
"name": "status",
|
"name": "status",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@@ -1341,35 +1289,6 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"/version": {
|
|
||||||
"get": {
|
|
||||||
"description": "version",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"home"
|
|
||||||
],
|
|
||||||
"summary": "version",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
@@ -1593,7 +1512,7 @@ const docTemplateapi = `{
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"color": {
|
"color": {
|
||||||
"description": "color is flutter's color value,from 0x00000000 to 0xFFFFFFFF; the first two digits represent transparency, the following 6 digits represent the color, can be converted to rgba",
|
"description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
@@ -1683,8 +1602,8 @@ var SwaggerInfoapi = &swag.Spec{
|
|||||||
Host: "",
|
Host: "",
|
||||||
BasePath: "/api",
|
BasePath: "/api",
|
||||||
Schemes: []string{},
|
Schemes: []string{},
|
||||||
Title: "management systemAPI",
|
Title: "管理系统API",
|
||||||
Description: "API",
|
Description: "接口",
|
||||||
InfoInstanceName: "api",
|
InfoInstanceName: "api",
|
||||||
SwaggerTemplate: docTemplateapi,
|
SwaggerTemplate: docTemplateapi,
|
||||||
LeftDelim: "{{",
|
LeftDelim: "{{",
|
||||||
|
|||||||
+174
-255
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"swagger": "2.0",
|
"swagger": "2.0",
|
||||||
"info": {
|
"info": {
|
||||||
"description": "API",
|
"description": "接口",
|
||||||
"title": "management systemAPI",
|
"title": "管理系统API",
|
||||||
"contact": {},
|
"contact": {},
|
||||||
"version": "1.0"
|
"version": "1.0"
|
||||||
},
|
},
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"/": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "home",
|
"description": "首页",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"home"
|
"首页"
|
||||||
],
|
],
|
||||||
"summary": "home",
|
"summary": "首页",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "address list",
|
"description": "地址列表",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -52,9 +52,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "address list",
|
"summary": "地址列表",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "address update",
|
"description": "地址更新",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -84,12 +84,12 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "address update",
|
"summary": "地址更新",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "address form",
|
"description": "地址表单",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "add address",
|
"description": "添加地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -129,9 +129,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "add address",
|
"summary": "添加地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "delete address",
|
"description": "删除地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -170,9 +170,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "delete address",
|
"summary": "删除地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "update address",
|
"description": "更新地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -213,9 +213,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "update address",
|
"summary": "更新地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "address",
|
"description": "地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -256,19 +256,19 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "address list",
|
"summary": "地址列表",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "current",
|
"name": "current",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "personal address",
|
"description": "个人地址",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -310,9 +310,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "personal address",
|
"summary": "个人地址",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"description": "string valid",
|
||||||
@@ -346,7 +346,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "settings",
|
"description": "设置",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -354,9 +354,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "settings",
|
"summary": "设置",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "string valid",
|
"description": "string valid",
|
||||||
@@ -390,7 +390,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "shared",
|
"description": "共享",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -398,19 +398,19 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "shared address book",
|
"summary": "共享地址簿",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "current",
|
"name": "current",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
}
|
}
|
||||||
@@ -438,7 +438,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -446,9 +446,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "add tag",
|
"summary": "标签添加",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -481,7 +481,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -489,9 +489,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "rename tag",
|
"summary": "标签重命名",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -524,7 +524,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -532,9 +532,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "change tag color",
|
"summary": "标签修改颜色",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -567,7 +567,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -575,9 +575,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "delete tag",
|
"summary": "标签删除",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -610,7 +610,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "tag",
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -618,9 +618,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"address[Personal]"
|
"地址[Personal]"
|
||||||
],
|
],
|
||||||
"summary": "tag",
|
"summary": "标签",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -646,9 +646,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/audit/conn": {
|
"/api": {
|
||||||
"post": {
|
"get": {
|
||||||
"description": "audit connection",
|
"security": [
|
||||||
|
{
|
||||||
|
"token": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "用户信息",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -656,12 +661,41 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"audit"
|
"用户"
|
||||||
],
|
],
|
||||||
"summary": "audit connection",
|
"summary": "用户信息",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.UserPayload"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/audit/conn": {
|
||||||
|
"post": {
|
||||||
|
"description": "审计连接",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"审计"
|
||||||
|
],
|
||||||
|
"summary": "审计连接",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "audit connection",
|
"description": "审计连接",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -688,7 +722,7 @@
|
|||||||
},
|
},
|
||||||
"/audit/file": {
|
"/audit/file": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "audit file",
|
"description": "审计文件",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -696,12 +730,12 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"audit"
|
"审计"
|
||||||
],
|
],
|
||||||
"summary": "audit file",
|
"summary": "审计文件",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "audit file",
|
"description": "审计文件",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -726,103 +760,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/currentUser": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"token": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "user info",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
"summary": "user info",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/api.UserPayload"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/device-group/accessible": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "machine",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"group"
|
|
||||||
],
|
|
||||||
"summary": "device",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "page number",
|
|
||||||
"name": "page",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "items per page",
|
|
||||||
"name": "pageSize",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "status",
|
|
||||||
"name": "status",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "accessible",
|
|
||||||
"name": "accessible",
|
|
||||||
"in": "query"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.DataResponse"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/heartbeat": {
|
"/heartbeat": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "heartbeat",
|
"description": "心跳",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -830,9 +770,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"home"
|
"首页"
|
||||||
],
|
],
|
||||||
"summary": "heartbeat",
|
"summary": "心跳",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
@@ -848,7 +788,7 @@
|
|||||||
},
|
},
|
||||||
"/login": {
|
"/login": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "login",
|
"description": "登录",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -856,12 +796,12 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"login"
|
"登录"
|
||||||
],
|
],
|
||||||
"summary": "login",
|
"summary": "登录",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "login form",
|
"description": "登录表单",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -888,7 +828,7 @@
|
|||||||
},
|
},
|
||||||
"/login-options": {
|
"/login-options": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "login options",
|
"description": "登录选项",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -896,9 +836,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"login"
|
"登录"
|
||||||
],
|
],
|
||||||
"summary": "login options",
|
"summary": "登录选项",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -920,7 +860,7 @@
|
|||||||
},
|
},
|
||||||
"/logout": {
|
"/logout": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "logout",
|
"description": "登出",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -928,9 +868,9 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"login"
|
"登录"
|
||||||
],
|
],
|
||||||
"summary": "logout",
|
"summary": "登出",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -947,6 +887,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/oauth/callback": {
|
||||||
|
"get": {
|
||||||
|
"description": "OauthCallback",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Oauth"
|
||||||
|
],
|
||||||
|
"summary": "OauthCallback",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.LoginRes"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/oidc/auth": {
|
"/oidc/auth": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "OidcAuth",
|
"description": "OidcAuth",
|
||||||
@@ -1005,35 +974,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/oidc/callback": {
|
|
||||||
"get": {
|
|
||||||
"description": "OauthCallback",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Oauth"
|
|
||||||
],
|
|
||||||
"summary": "OauthCallback",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/api.LoginRes"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.ErrorResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/peers": {
|
"/peers": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1041,7 +981,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "machine",
|
"description": "机器",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1049,25 +989,25 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"group"
|
"群组"
|
||||||
],
|
],
|
||||||
"summary": "machine",
|
"summary": "机器",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "page",
|
"name": "page",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "status",
|
"description": "状态",
|
||||||
"name": "status",
|
"name": "status",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@@ -1101,7 +1041,7 @@
|
|||||||
"token": []
|
"token": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "service config, provides an api-server for the webclient",
|
"description": "服务配置,给webclient提供api-server",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1111,7 +1051,7 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"WEBCLIENT"
|
"WEBCLIENT"
|
||||||
],
|
],
|
||||||
"summary": "service config",
|
"summary": "服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -1135,7 +1075,7 @@
|
|||||||
"token": []
|
"token": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "service config, provides an api-server for the webclient",
|
"description": "服务配置,给webclient提供api-server",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1145,7 +1085,7 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"WEBCLIENT_V2"
|
"WEBCLIENT_V2"
|
||||||
],
|
],
|
||||||
"summary": "service config",
|
"summary": "服务配置",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -1164,7 +1104,7 @@
|
|||||||
},
|
},
|
||||||
"/shared-peer": {
|
"/shared-peer": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "shared peer",
|
"description": "分享的peer",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1174,7 +1114,7 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"WEBCLIENT"
|
"WEBCLIENT"
|
||||||
],
|
],
|
||||||
"summary": "shared peer",
|
"summary": "分享的peer",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
@@ -1193,7 +1133,7 @@
|
|||||||
},
|
},
|
||||||
"/sysinfo": {
|
"/sysinfo": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "submit system info",
|
"description": "提交系统信息",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1201,12 +1141,12 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"System"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "submit system info",
|
"summary": "提交系统信息",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"description": "system info form",
|
"description": "系统信息表单",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -1231,9 +1171,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/sysinfo_ver": {
|
"/tags": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "get system version info",
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "标签",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1241,14 +1186,17 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"System"
|
"地址"
|
||||||
],
|
],
|
||||||
"summary": "get system version info",
|
"summary": "标签",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/model.Tag"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
@@ -1267,7 +1215,7 @@
|
|||||||
"BearerAuth": []
|
"BearerAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "user list",
|
"description": "用户列表",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -1275,25 +1223,25 @@
|
|||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"group"
|
"群组"
|
||||||
],
|
],
|
||||||
"summary": "user list",
|
"summary": "用户列表",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "page number",
|
"description": "页码",
|
||||||
"name": "page",
|
"name": "page",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "items per page",
|
"description": "每页数量",
|
||||||
"name": "pageSize",
|
"name": "pageSize",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "status",
|
"description": "状态",
|
||||||
"name": "status",
|
"name": "status",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@@ -1334,35 +1282,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"/version": {
|
|
||||||
"get": {
|
|
||||||
"description": "version",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"home"
|
|
||||||
],
|
|
||||||
"summary": "version",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
@@ -1586,7 +1505,7 @@
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"color": {
|
"color": {
|
||||||
"description": "color is flutter's color value,from 0x00000000 to 0xFFFFFFFF; the first two digits represent transparency, the following 6 digits represent the color, can be converted to rgba",
|
"description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
|
|||||||
+146
-199
@@ -146,8 +146,8 @@ definitions:
|
|||||||
collection_id:
|
collection_id:
|
||||||
type: integer
|
type: integer
|
||||||
color:
|
color:
|
||||||
description: color is flutter's color value,from 0x00000000 to 0xFFFFFFFF; the first two digits represent transparency, the following 6 digits represent the color,
|
description: color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色,
|
||||||
can be converted to rgba
|
可以转成rgba
|
||||||
type: integer
|
type: integer
|
||||||
created_at:
|
created_at:
|
||||||
type: string
|
type: string
|
||||||
@@ -194,15 +194,15 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
info:
|
info:
|
||||||
contact: {}
|
contact: {}
|
||||||
description: API
|
description: 接口
|
||||||
title: management systemAPI
|
title: 管理系统API
|
||||||
version: "1.0"
|
version: "1.0"
|
||||||
paths:
|
paths:
|
||||||
/:
|
/:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: home
|
description: 首页
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -214,14 +214,14 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
summary: home
|
summary: 首页
|
||||||
tags:
|
tags:
|
||||||
- home
|
- 首页
|
||||||
/ab:
|
/ab:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: address list
|
description: 地址列表
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -235,15 +235,15 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: address list
|
summary: 地址列表
|
||||||
tags:
|
tags:
|
||||||
- address
|
- 地址
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: address update
|
description: 地址更新
|
||||||
parameters:
|
parameters:
|
||||||
- description: address form
|
- description: 地址表单
|
||||||
in: body
|
in: body
|
||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
@@ -262,14 +262,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: address update
|
summary: 地址更新
|
||||||
tags:
|
tags:
|
||||||
- address
|
- 地址
|
||||||
/ab/peer/add/{guid}:
|
/ab/peer/add/{guid}:
|
||||||
delete:
|
delete:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: delete address
|
description: 删除地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -289,13 +289,13 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: delete address
|
summary: 删除地址
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: add address
|
description: 添加地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -315,14 +315,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: add address
|
summary: 添加地址
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/peer/update/{guid}:
|
/ab/peer/update/{guid}:
|
||||||
put:
|
put:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: update address
|
description: 更新地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -342,20 +342,20 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: update address
|
summary: 更新地址
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/peers:
|
/ab/peers:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: address
|
description: 地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: page number
|
- description: 页码
|
||||||
in: query
|
in: query
|
||||||
name: current
|
name: current
|
||||||
type: integer
|
type: integer
|
||||||
- description: items per page
|
- description: 每页数量
|
||||||
in: query
|
in: query
|
||||||
name: pageSize
|
name: pageSize
|
||||||
type: integer
|
type: integer
|
||||||
@@ -376,14 +376,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: address list
|
summary: 地址列表
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/personal:
|
/ab/personal:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: personal address
|
description: 个人地址
|
||||||
parameters:
|
parameters:
|
||||||
- description: string valid
|
- description: string valid
|
||||||
in: body
|
in: body
|
||||||
@@ -403,14 +403,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: personal address
|
summary: 个人地址
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/settings:
|
/ab/settings:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: settings
|
description: 设置
|
||||||
parameters:
|
parameters:
|
||||||
- description: string valid
|
- description: string valid
|
||||||
in: body
|
in: body
|
||||||
@@ -430,20 +430,20 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: settings
|
summary: 设置
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/shared/profiles:
|
/ab/shared/profiles:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: shared
|
description: 共享
|
||||||
parameters:
|
parameters:
|
||||||
- description: page number
|
- description: 页码
|
||||||
in: query
|
in: query
|
||||||
name: current
|
name: current
|
||||||
type: integer
|
type: integer
|
||||||
- description: items per page
|
- description: 每页数量
|
||||||
in: query
|
in: query
|
||||||
name: pageSize
|
name: pageSize
|
||||||
type: integer
|
type: integer
|
||||||
@@ -460,14 +460,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: shared address book
|
summary: 共享地址簿
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/tag/{guid}:
|
/ab/tag/{guid}:
|
||||||
delete:
|
delete:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: tag
|
description: 标签
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -487,14 +487,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: delete tag
|
summary: 标签删除
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/tag/add/{guid}:
|
/ab/tag/add/{guid}:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: tag
|
description: 标签
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -514,14 +514,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: add tag
|
summary: 标签添加
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/tag/rename/{guid}:
|
/ab/tag/rename/{guid}:
|
||||||
put:
|
put:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: tag
|
description: 标签
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -541,14 +541,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: rename tag
|
summary: 标签重命名
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/tag/update/{guid}:
|
/ab/tag/update/{guid}:
|
||||||
put:
|
put:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: tag
|
description: 标签
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -568,14 +568,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: change tag color
|
summary: 标签修改颜色
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
/ab/tags/{guid}:
|
/ab/tags/{guid}:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: tag
|
description: 标签
|
||||||
parameters:
|
parameters:
|
||||||
- description: guid
|
- description: guid
|
||||||
in: path
|
in: path
|
||||||
@@ -595,16 +595,37 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: tag
|
summary: 标签
|
||||||
tags:
|
tags:
|
||||||
- address[Personal]
|
- 地址[Personal]
|
||||||
|
/api:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 用户信息
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/api.UserPayload'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
security:
|
||||||
|
- token: []
|
||||||
|
summary: 用户信息
|
||||||
|
tags:
|
||||||
|
- 用户
|
||||||
/audit/conn:
|
/audit/conn:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: audit connection
|
description: 审计连接
|
||||||
parameters:
|
parameters:
|
||||||
- description: audit connection
|
- description: 审计连接
|
||||||
in: body
|
in: body
|
||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
@@ -621,16 +642,16 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
summary: audit connection
|
summary: 审计连接
|
||||||
tags:
|
tags:
|
||||||
- audit
|
- 审计
|
||||||
/audit/file:
|
/audit/file:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: audit file
|
description: 审计文件
|
||||||
parameters:
|
parameters:
|
||||||
- description: audit file
|
- description: 审计文件
|
||||||
in: body
|
in: body
|
||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
@@ -647,73 +668,14 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
summary: audit file
|
summary: 审计文件
|
||||||
tags:
|
tags:
|
||||||
- audit
|
- 审计
|
||||||
/currentUser:
|
|
||||||
get:
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
description: user info
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/api.UserPayload'
|
|
||||||
"500":
|
|
||||||
description: Internal Server Error
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.Response'
|
|
||||||
security:
|
|
||||||
- token: []
|
|
||||||
summary: user info
|
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
/device-group/accessible:
|
|
||||||
get:
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
description: machine
|
|
||||||
parameters:
|
|
||||||
- description: page number
|
|
||||||
in: query
|
|
||||||
name: page
|
|
||||||
type: integer
|
|
||||||
- description: items per page
|
|
||||||
in: query
|
|
||||||
name: pageSize
|
|
||||||
type: integer
|
|
||||||
- description: status
|
|
||||||
in: query
|
|
||||||
name: status
|
|
||||||
type: integer
|
|
||||||
- description: accessible
|
|
||||||
in: query
|
|
||||||
name: accessible
|
|
||||||
type: string
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.DataResponse'
|
|
||||||
"500":
|
|
||||||
description: Internal Server Error
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.Response'
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
summary: device
|
|
||||||
tags:
|
|
||||||
- group
|
|
||||||
/heartbeat:
|
/heartbeat:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: heartbeat
|
description: 心跳
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -723,16 +685,16 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
summary: heartbeat
|
summary: 心跳
|
||||||
tags:
|
tags:
|
||||||
- home
|
- 首页
|
||||||
/login:
|
/login:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: login
|
description: 登录
|
||||||
parameters:
|
parameters:
|
||||||
- description: login form
|
- description: 登录表单
|
||||||
in: body
|
in: body
|
||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
@@ -749,14 +711,14 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
summary: login
|
summary: 登录
|
||||||
tags:
|
tags:
|
||||||
- login
|
- 登录
|
||||||
/login-options:
|
/login-options:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: login options
|
description: 登录选项
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -770,14 +732,14 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
summary: login options
|
summary: 登录选项
|
||||||
tags:
|
tags:
|
||||||
- login
|
- 登录
|
||||||
/logout:
|
/logout:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: logout
|
description: 登出
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -789,9 +751,28 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
summary: logout
|
summary: 登出
|
||||||
tags:
|
tags:
|
||||||
- login
|
- 登录
|
||||||
|
/oauth/callback:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: OauthCallback
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/api.LoginRes'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
|
summary: OauthCallback
|
||||||
|
tags:
|
||||||
|
- Oauth
|
||||||
/oidc/auth:
|
/oidc/auth:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -830,40 +811,21 @@ paths:
|
|||||||
summary: OidcAuthQuery
|
summary: OidcAuthQuery
|
||||||
tags:
|
tags:
|
||||||
- Oauth
|
- Oauth
|
||||||
/oidc/callback:
|
|
||||||
get:
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
description: OauthCallback
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/api.LoginRes'
|
|
||||||
"500":
|
|
||||||
description: Internal Server Error
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
|
||||||
summary: OauthCallback
|
|
||||||
tags:
|
|
||||||
- Oauth
|
|
||||||
/peers:
|
/peers:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: machine
|
description: 机器
|
||||||
parameters:
|
parameters:
|
||||||
- description: page number
|
- description: 页码
|
||||||
in: query
|
in: query
|
||||||
name: page
|
name: page
|
||||||
type: integer
|
type: integer
|
||||||
- description: items per page
|
- description: 每页数量
|
||||||
in: query
|
in: query
|
||||||
name: pageSize
|
name: pageSize
|
||||||
type: integer
|
type: integer
|
||||||
- description: status
|
- description: 状态
|
||||||
in: query
|
in: query
|
||||||
name: status
|
name: status
|
||||||
type: integer
|
type: integer
|
||||||
@@ -884,14 +846,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: machine
|
summary: 机器
|
||||||
tags:
|
tags:
|
||||||
- group
|
- 群组
|
||||||
/server-config:
|
/server-config:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: service config, provides an api-server for the webclient
|
description: 服务配置,给webclient提供api-server
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -905,14 +867,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- token: []
|
- token: []
|
||||||
summary: service config
|
summary: 服务配置
|
||||||
tags:
|
tags:
|
||||||
- WEBCLIENT
|
- WEBCLIENT
|
||||||
/server-config-v2:
|
/server-config-v2:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: service config, provides an api-server for the webclient
|
description: 服务配置,给webclient提供api-server
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -926,14 +888,14 @@ paths:
|
|||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
security:
|
security:
|
||||||
- token: []
|
- token: []
|
||||||
summary: service config
|
summary: 服务配置
|
||||||
tags:
|
tags:
|
||||||
- WEBCLIENT_V2
|
- WEBCLIENT_V2
|
||||||
/shared-peer:
|
/shared-peer:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: shared peer
|
description: 分享的peer
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
@@ -945,16 +907,16 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.Response'
|
$ref: '#/definitions/response.Response'
|
||||||
summary: shared peer
|
summary: 分享的peer
|
||||||
tags:
|
tags:
|
||||||
- WEBCLIENT
|
- WEBCLIENT
|
||||||
/sysinfo:
|
/sysinfo:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: submit system info
|
description: 提交系统信息
|
||||||
parameters:
|
parameters:
|
||||||
- description: system info form
|
- description: 系统信息表单
|
||||||
in: body
|
in: body
|
||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
@@ -971,43 +933,47 @@ paths:
|
|||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
summary: submit system info
|
summary: 提交系统信息
|
||||||
tags:
|
tags:
|
||||||
- System
|
- 地址
|
||||||
/sysinfo_ver:
|
/tags:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: get system version info
|
description: 标签
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
type: string
|
items:
|
||||||
|
$ref: '#/definitions/model.Tag'
|
||||||
|
type: array
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
summary: get system version info
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
summary: 标签
|
||||||
tags:
|
tags:
|
||||||
- System
|
- 地址
|
||||||
/users:
|
/users:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: user list
|
description: 用户列表
|
||||||
parameters:
|
parameters:
|
||||||
- description: page number
|
- description: 页码
|
||||||
in: query
|
in: query
|
||||||
name: page
|
name: page
|
||||||
type: integer
|
type: integer
|
||||||
- description: items per page
|
- description: 每页数量
|
||||||
in: query
|
in: query
|
||||||
name: pageSize
|
name: pageSize
|
||||||
type: integer
|
type: integer
|
||||||
- description: status
|
- description: 状态
|
||||||
in: query
|
in: query
|
||||||
name: status
|
name: status
|
||||||
type: integer
|
type: integer
|
||||||
@@ -1035,28 +1001,9 @@ paths:
|
|||||||
$ref: '#/definitions/response.ErrorResponse'
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
summary: user list
|
summary: 用户列表
|
||||||
tags:
|
tags:
|
||||||
- group
|
- 群组
|
||||||
/version:
|
|
||||||
get:
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
description: version
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.Response'
|
|
||||||
"500":
|
|
||||||
description: Internal Server Error
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.Response'
|
|
||||||
summary: version
|
|
||||||
tags:
|
|
||||||
- home
|
|
||||||
securityDefinitions:
|
securityDefinitions:
|
||||||
BearerAuth:
|
BearerAuth:
|
||||||
in: header
|
in: header
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB |
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package Gwen
|
||||||
|
|
||||||
//go:generate swag init -g cmd/apimain.go --output docs/api --instanceName api --exclude http/controller/admin
|
//go:generate swag init -g cmd/apimain.go --output docs/api --instanceName api --exclude http/controller/admin
|
||||||
//go:generate swag init -g cmd/apimain.go --output docs/admin --instanceName admin --exclude http/controller/api
|
//go:generate swag init -g cmd/apimain.go --output docs/admin --instanceName admin --exclude http/controller/api
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package Gwen
|
||||||
|
|
||||||
//go:generate go run cmd/apimain.go
|
//go:generate go run cmd/apimain.go
|
||||||
|
|||||||
+8
-22
@@ -4,36 +4,33 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/locales/en"
|
"github.com/go-playground/locales/en"
|
||||||
"github.com/go-playground/locales/es"
|
"github.com/go-playground/locales/es"
|
||||||
"github.com/go-playground/locales/fr"
|
|
||||||
"github.com/go-playground/locales/ko"
|
"github.com/go-playground/locales/ko"
|
||||||
"github.com/go-playground/locales/ru"
|
"github.com/go-playground/locales/ru"
|
||||||
|
"github.com/go-playground/locales/fr"
|
||||||
"github.com/go-playground/locales/zh_Hans_CN"
|
"github.com/go-playground/locales/zh_Hans_CN"
|
||||||
"github.com/go-playground/locales/zh_Hant"
|
|
||||||
ut "github.com/go-playground/universal-translator"
|
ut "github.com/go-playground/universal-translator"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
en_translations "github.com/go-playground/validator/v10/translations/en"
|
en_translations "github.com/go-playground/validator/v10/translations/en"
|
||||||
es_translations "github.com/go-playground/validator/v10/translations/es"
|
es_translations "github.com/go-playground/validator/v10/translations/es"
|
||||||
fr_translations "github.com/go-playground/validator/v10/translations/fr"
|
|
||||||
ko_translations "github.com/go-playground/validator/v10/translations/ko"
|
|
||||||
ru_translations "github.com/go-playground/validator/v10/translations/ru"
|
ru_translations "github.com/go-playground/validator/v10/translations/ru"
|
||||||
zh_translations "github.com/go-playground/validator/v10/translations/zh"
|
zh_translations "github.com/go-playground/validator/v10/translations/zh"
|
||||||
zh_tw_translations "github.com/go-playground/validator/v10/translations/zh_tw"
|
fr_translations "github.com/go-playground/validator/v10/translations/fr"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ApiInitValidator() {
|
func ApiInitValidator() {
|
||||||
validate := validator.New()
|
validate := validator.New()
|
||||||
|
|
||||||
// define translations for different languages
|
// 定义不同的语言翻译
|
||||||
enT := en.New()
|
enT := en.New()
|
||||||
cn := zh_Hans_CN.New()
|
cn := zh_Hans_CN.New()
|
||||||
koT := ko.New()
|
koT := ko.New()
|
||||||
ruT := ru.New()
|
ruT := ru.New()
|
||||||
esT := es.New()
|
esT := es.New()
|
||||||
frT := fr.New()
|
frT := fr.New()
|
||||||
zhTwT := zh_Hant.New()
|
|
||||||
|
|
||||||
uni := ut.New(enT, cn, koT, ruT, esT, frT, zhTwT)
|
uni := ut.New(enT, cn, koT, ruT, esT, frT)
|
||||||
|
|
||||||
enTrans, _ := uni.GetTranslator("en")
|
enTrans, _ := uni.GetTranslator("en")
|
||||||
zhTrans, _ := uni.GetTranslator("zh_Hans_CN")
|
zhTrans, _ := uni.GetTranslator("zh_Hans_CN")
|
||||||
@@ -41,7 +38,6 @@ func ApiInitValidator() {
|
|||||||
ruTrans, _ := uni.GetTranslator("ru")
|
ruTrans, _ := uni.GetTranslator("ru")
|
||||||
esTrans, _ := uni.GetTranslator("es")
|
esTrans, _ := uni.GetTranslator("es")
|
||||||
frTrans, _ := uni.GetTranslator("fr")
|
frTrans, _ := uni.GetTranslator("fr")
|
||||||
zhTwTrans, _ := uni.GetTranslator("zh_Hant")
|
|
||||||
|
|
||||||
err := zh_translations.RegisterDefaultTranslations(validate, zhTrans)
|
err := zh_translations.RegisterDefaultTranslations(validate, zhTrans)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -52,7 +48,8 @@ func ApiInitValidator() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ko_translations.RegisterDefaultTranslations(validate, koTrans)
|
//validate没有ko的翻译,使用zh的翻译
|
||||||
|
err = zh_translations.RegisterDefaultTranslations(validate, koTrans)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -68,10 +65,6 @@ func ApiInitValidator() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = zh_tw_translations.RegisterDefaultTranslations(validate, zhTwTrans)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
|
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
|
||||||
label := field.Tag.Get("label")
|
label := field.Tag.Get("label")
|
||||||
@@ -81,7 +74,7 @@ func ApiInitValidator() {
|
|||||||
return label
|
return label
|
||||||
})
|
})
|
||||||
Validator.Validate = validate
|
Validator.Validate = validate
|
||||||
Validator.UT = uni // store the Universal Translator
|
Validator.UT = uni // 存储 Universal Translator
|
||||||
Validator.VTrans = zhTrans
|
Validator.VTrans = zhTrans
|
||||||
|
|
||||||
Validator.ValidStruct = func(ctx *gin.Context, i interface{}) []string {
|
Validator.ValidStruct = func(ctx *gin.Context, i interface{}) []string {
|
||||||
@@ -132,13 +125,6 @@ func getTranslatorForLang(lang string) ut.Translator {
|
|||||||
case "zh":
|
case "zh":
|
||||||
trans, _ := Validator.UT.GetTranslator("zh_Hans_CN")
|
trans, _ := Validator.UT.GetTranslator("zh_Hans_CN")
|
||||||
return trans
|
return trans
|
||||||
case "zh_TW":
|
|
||||||
fallthrough
|
|
||||||
case "zh-TW":
|
|
||||||
fallthrough
|
|
||||||
case "zh-tw":
|
|
||||||
trans, _ := Validator.UT.GetTranslator("zh_Hant")
|
|
||||||
return trans
|
|
||||||
case "ko":
|
case "ko":
|
||||||
trans, _ := Validator.UT.GetTranslator("ko")
|
trans, _ := Validator.UT.GetTranslator("ko")
|
||||||
return trans
|
return trans
|
||||||
|
|||||||
+5
-7
@@ -1,16 +1,15 @@
|
|||||||
package global
|
package global
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/config"
|
||||||
|
"Gwen/lib/cache"
|
||||||
|
"Gwen/lib/jwt"
|
||||||
|
"Gwen/lib/lock"
|
||||||
|
"Gwen/lib/upload"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
ut "github.com/go-playground/universal-translator"
|
ut "github.com/go-playground/universal-translator"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/config"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/cache"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/jwt"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/lock"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/upload"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/utils"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -36,5 +35,4 @@ var (
|
|||||||
Jwt *jwt.Jwt
|
Jwt *jwt.Jwt
|
||||||
Lock lock.Locker
|
Lock lock.Locker
|
||||||
Localizer func(lang string) *i18n.Localizer
|
Localizer func(lang string) *i18n.Localizer
|
||||||
LoginLimiter *utils.LoginLimiter
|
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-2
@@ -10,14 +10,15 @@ import (
|
|||||||
func InitI18n() {
|
func InitI18n() {
|
||||||
bundle := i18n.NewBundle(language.English)
|
bundle := i18n.NewBundle(language.English)
|
||||||
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
||||||
// read all language files under global.Config.Gin.ResourcesPath
|
//读取global.Config.Gin.ResourcesPath下的所有语言文件
|
||||||
dir := Config.Gin.ResourcesPath + "/i18n"
|
dir := Config.Gin.ResourcesPath + "/i18n"
|
||||||
fileInfos, err := os.ReadDir(dir)
|
fileInfos, err := os.ReadDir(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for _, fileInfo := range fileInfos {
|
for _, fileInfo := range fileInfos {
|
||||||
// if the file name does not end with .toml
|
//如果文件名不是.toml结尾
|
||||||
if fileInfo.IsDir() || fileInfo.Name()[len(fileInfo.Name())-5:] != ".toml" {
|
if fileInfo.IsDir() || fileInfo.Name()[len(fileInfo.Name())-5:] != ".toml" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,19 @@
|
|||||||
module github.com/lejianwen/rustdesk-api/v2
|
module Gwen
|
||||||
|
|
||||||
go 1.23
|
go 1.22
|
||||||
|
|
||||||
toolchain go1.23.10
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.3.2
|
github.com/BurntSushi/toml v1.3.2
|
||||||
github.com/antonfisher/nested-logrus-formatter v1.3.1
|
github.com/antonfisher/nested-logrus-formatter v1.3.1
|
||||||
github.com/coreos/go-oidc/v3 v3.12.0
|
github.com/fsnotify/fsnotify v1.5.1
|
||||||
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
|
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
|
||||||
github.com/gin-gonic/gin v1.9.0
|
github.com/gin-gonic/gin v1.9.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10
|
|
||||||
github.com/go-playground/locales v0.14.1
|
github.com/go-playground/locales v0.14.1
|
||||||
github.com/go-playground/universal-translator v0.18.1
|
github.com/go-playground/universal-translator v0.18.1
|
||||||
github.com/go-playground/validator/v10 v10.26.0
|
github.com/go-playground/validator/v10 v10.11.2
|
||||||
github.com/go-redis/redis/v8 v8.11.4
|
github.com/go-redis/redis/v8 v8.11.4
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.1.2
|
||||||
github.com/mojocn/base64Captcha v1.3.6
|
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.4.0
|
github.com/nicksnyder/go-i18n/v2 v2.4.0
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.8.1
|
||||||
@@ -25,17 +21,14 @@ require (
|
|||||||
github.com/swaggo/files v1.0.1
|
github.com/swaggo/files v1.0.1
|
||||||
github.com/swaggo/gin-swagger v1.6.0
|
github.com/swaggo/gin-swagger v1.6.0
|
||||||
github.com/swaggo/swag v1.16.3
|
github.com/swaggo/swag v1.16.3
|
||||||
golang.org/x/crypto v0.33.0
|
|
||||||
golang.org/x/oauth2 v0.23.0
|
golang.org/x/oauth2 v0.23.0
|
||||||
golang.org/x/text v0.22.0
|
golang.org/x/text v0.18.0
|
||||||
gorm.io/driver/mysql v1.5.7
|
gorm.io/driver/mysql v1.5.7
|
||||||
gorm.io/driver/postgres v1.6.0
|
|
||||||
gorm.io/driver/sqlite v1.5.6
|
gorm.io/driver/sqlite v1.5.6
|
||||||
gorm.io/gorm v1.25.10
|
gorm.io/gorm v1.25.7
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
@@ -43,11 +36,7 @@ require (
|
|||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
|
||||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||||
github.com/go-openapi/spec v0.20.4 // indirect
|
github.com/go-openapi/spec v0.20.4 // indirect
|
||||||
@@ -57,16 +46,12 @@ require (
|
|||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
|
||||||
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
|
||||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/magiconair/properties v1.8.5 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
@@ -74,9 +59,9 @@ require (
|
|||||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // 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 v1.9.4 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
|
||||||
github.com/spf13/afero v1.6.0 // indirect
|
github.com/spf13/afero v1.6.0 // indirect
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.4.1 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
@@ -85,11 +70,11 @@ require (
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // 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/image v0.13.0 // indirect
|
||||||
golang.org/x/net v0.34.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sync v0.11.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
golang.org/x/tools v0.26.0 // indirect
|
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.63.2 // indirect
|
gopkg.in/ini.v1 v1.63.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
_ "encoding/json"
|
_ "encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -15,10 +15,10 @@ import (
|
|||||||
type AddressBook struct {
|
type AddressBook struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail address book
|
// Detail 地址簿
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary address book details
|
// @Summary 地址簿详情
|
||||||
// @Description address book details
|
// @Description 地址簿详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -38,13 +38,13 @@ func (ct *AddressBook) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create address book
|
// Create 创建地址簿
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary create address book
|
// @Summary 创建地址簿
|
||||||
// @Description create address book
|
// @Description 创建地址簿
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book/create [post]
|
// @Router /admin/address_book/create [post]
|
||||||
@@ -84,13 +84,13 @@ func (ct *AddressBook) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchCreate batch create address books
|
// BatchCreate 批量创建地址簿
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary batch create address books
|
// @Summary 批量创建地址簿
|
||||||
// @Description batch create address books
|
// @Description 批量创建地址簿
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book/batchCreate [post]
|
// @Router /admin/address_book/batchCreate [post]
|
||||||
@@ -113,13 +113,13 @@ func (ct *AddressBook) BatchCreate(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ul > 1 {
|
if ul > 1 {
|
||||||
//clear tags in multi-user mode
|
//多用户置空标签
|
||||||
f.Tags = []string{}
|
f.Tags = []string{}
|
||||||
//in multi-user mode, can only create in the default address book
|
//多用户只能创建到默认地址簿
|
||||||
f.CollectionId = 0
|
f.CollectionId = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
//create tag
|
//创建标签
|
||||||
/*for _, fu := range f.UserIds {
|
/*for _, fu := range f.UserIds {
|
||||||
if fu == 0 {
|
if fu == 0 {
|
||||||
continue
|
continue
|
||||||
@@ -148,16 +148,16 @@ func (ct *AddressBook) BatchCreate(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary address book list
|
// @Summary 地址簿列表
|
||||||
// @Description address book list
|
// @Description 地址簿列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Param is_my query int false "whether it is mine"
|
// @Param is_my query int false "是否是我的"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookList}
|
// @Success 200 {object} response.Response{data=model.AddressBookList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book/list [get]
|
// @Router /admin/address_book/list [get]
|
||||||
@@ -196,13 +196,13 @@ func (ct *AddressBook) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary edit address book
|
// @Summary 地址簿编辑
|
||||||
// @Description edit address book
|
// @Description 地址簿编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book/update [post]
|
// @Router /admin/address_book/update [post]
|
||||||
@@ -240,13 +240,13 @@ func (ct *AddressBook) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary delete address book
|
// @Summary 地址簿删除
|
||||||
// @Description delete address book
|
// @Description 地址簿删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book/delete [post]
|
// @Router /admin/address_book/delete [post]
|
||||||
@@ -277,12 +277,12 @@ func (ct *AddressBook) Delete(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ShareByWebClient
|
// ShareByWebClient
|
||||||
// @Tags address book
|
// @Tags 地址簿
|
||||||
// @Summary share address book
|
// @Summary 地址簿分享
|
||||||
// @Description share address book
|
// @Description 地址簿分享
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.ShareByWebClientForm true "address book info"
|
// @Param body body admin.ShareByWebClientForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book/share [post]
|
// @Router /admin/address_book/share [post]
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
type AddressBookCollection struct {
|
type AddressBookCollection struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail address book name
|
// Detail 地址簿名称
|
||||||
// @Tags address book name
|
// @Tags 地址簿名称
|
||||||
// @Summary address book name details
|
// @Summary 地址簿名称详情
|
||||||
// @Description address book name details
|
// @Description 地址簿名称详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -37,13 +37,13 @@ func (abc *AddressBookCollection) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create address book name
|
// Create 创建地址簿名称
|
||||||
// @Tags address book name
|
// @Tags 地址簿名称
|
||||||
// @Summary create address book name
|
// @Summary 创建地址簿名称
|
||||||
// @Description create address book name
|
// @Description 创建地址簿名称
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollection true "address book name info"
|
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection/create [post]
|
// @Router /admin/address_book_collection/create [post]
|
||||||
@@ -72,16 +72,16 @@ func (abc *AddressBookCollection) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags address book name
|
// @Tags 地址簿名称
|
||||||
// @Summary address book name list
|
// @Summary 地址簿名称列表
|
||||||
// @Description address book name list
|
// @Description 地址簿名称列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param is_my query int false "whether it is mine"
|
// @Param is_my query int false "是否是我的"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection/list [get]
|
// @Router /admin/address_book_collection/list [get]
|
||||||
@@ -100,13 +100,13 @@ func (abc *AddressBookCollection) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags address book name
|
// @Tags 地址簿名称
|
||||||
// @Summary edit address book name
|
// @Summary 地址簿名称编辑
|
||||||
// @Description edit address book name
|
// @Description 地址簿名称编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollection true "address book name info"
|
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection/update [post]
|
// @Router /admin/address_book_collection/update [post]
|
||||||
@@ -135,13 +135,13 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags address book name
|
// @Tags 地址簿名称
|
||||||
// @Summary delete address book name
|
// @Summary 地址簿名称删除
|
||||||
// @Description delete address book name
|
// @Description 地址簿名称删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollection true "address book name info"
|
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection/delete [post]
|
// @Router /admin/address_book_collection/delete [post]
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -14,17 +14,17 @@ import (
|
|||||||
type AddressBookCollectionRule struct {
|
type AddressBookCollectionRule struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags address book rules
|
// @Tags 地址簿规则
|
||||||
// @Summary address book rule list
|
// @Summary 地址簿规则列表
|
||||||
// @Description address book rule list
|
// @Description 地址簿规则列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param is_my query int false "whether it is mine"
|
// @Param is_my query int false "是否是我的"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Param collection_id query int false "address book collectionid"
|
// @Param collection_id query int false "地址簿集合id"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection_rule/list [get]
|
// @Router /admin/address_book_collection_rule/list [get]
|
||||||
@@ -47,10 +47,10 @@ func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail address book rules
|
// Detail 地址簿规则
|
||||||
// @Tags address book rules
|
// @Tags 地址簿规则
|
||||||
// @Summary address book rule details
|
// @Summary 地址簿规则详情
|
||||||
// @Description address book rule details
|
// @Description 地址簿规则详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -69,13 +69,13 @@ func (abcr *AddressBookCollectionRule) Detail(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create address book rule
|
// Create 创建地址簿规则
|
||||||
// @Tags address book rules
|
// @Tags 地址簿规则
|
||||||
// @Summary create address book rule
|
// @Summary 创建地址簿规则
|
||||||
// @Description create address book rule
|
// @Description 创建地址簿规则
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollectionRule true "address book rule info"
|
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection_rule/create [post]
|
// @Router /admin/address_book_collection_rule/create [post]
|
||||||
@@ -120,7 +120,7 @@ func (abcr *AddressBookCollectionRule) CheckForm(t *model.AddressBookCollectionR
|
|||||||
//check to_id
|
//check to_id
|
||||||
if t.Type == model.ShareAddressBookRuleTypePersonal {
|
if t.Type == model.ShareAddressBookRuleTypePersonal {
|
||||||
if t.ToId == t.UserId {
|
if t.ToId == t.UserId {
|
||||||
return "CannotShareToSelf", false
|
return "ParamsError", false
|
||||||
}
|
}
|
||||||
tou := service.AllService.UserService.InfoById(t.ToId)
|
tou := service.AllService.UserService.InfoById(t.ToId)
|
||||||
if tou.Id == 0 {
|
if tou.Id == 0 {
|
||||||
@@ -134,8 +134,8 @@ func (abcr *AddressBookCollectionRule) CheckForm(t *model.AddressBookCollectionR
|
|||||||
} else {
|
} else {
|
||||||
return "ParamsError", false
|
return "ParamsError", false
|
||||||
}
|
}
|
||||||
// duplicate check
|
// 重复检查
|
||||||
ex := service.AllService.AddressBookService.RuleInfoByToIdAndCid(t.Type, t.ToId, t.CollectionId)
|
ex := service.AllService.AddressBookService.RulePersonalInfoByToIdAndCid(t.ToId, t.CollectionId)
|
||||||
if t.Id == 0 && ex.Id > 0 {
|
if t.Id == 0 && ex.Id > 0 {
|
||||||
return "ItemExists", false
|
return "ItemExists", false
|
||||||
}
|
}
|
||||||
@@ -145,13 +145,13 @@ func (abcr *AddressBookCollectionRule) CheckForm(t *model.AddressBookCollectionR
|
|||||||
return "", true
|
return "", true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags address book rules
|
// @Tags 地址簿规则
|
||||||
// @Summary edit address book rule
|
// @Summary 地址簿规则编辑
|
||||||
// @Description edit address book rule
|
// @Description 地址簿规则编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollectionRule true "address book rule info"
|
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection_rule/update [post]
|
// @Router /admin/address_book_collection_rule/update [post]
|
||||||
@@ -185,13 +185,13 @@ func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags address book rules
|
// @Tags 地址簿规则
|
||||||
// @Summary delete address book rule
|
// @Summary 地址簿规则删除
|
||||||
// @Description delete address book rule
|
// @Description 地址簿规则删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollectionRule true "address book rule info"
|
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/address_book_collection_rule/delete [post]
|
// @Router /admin/address_book_collection_rule/delete [post]
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Audit struct {
|
type Audit struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnList list
|
// ConnList 列表
|
||||||
// @Tags connection log
|
// @Tags 链接日志
|
||||||
// @Summary connection log list
|
// @Summary 链接日志列表
|
||||||
// @Description connection log list
|
// @Description 链接日志列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param peer_id query int false "target device"
|
// @Param peer_id query int false "目标设备"
|
||||||
// @Param from_peer query int false "source device"
|
// @Param from_peer query int false "来源设备"
|
||||||
// @Success 200 {object} response.Response{data=model.AuditConnList}
|
// @Success 200 {object} response.Response{data=model.AuditConnList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/audit_conn/list [get]
|
// @Router /admin/audit_conn/list [get]
|
||||||
@@ -45,13 +45,13 @@ func (a *Audit) ConnList(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnDelete delete
|
// ConnDelete 删除
|
||||||
// @Tags connection log
|
// @Tags 链接日志
|
||||||
// @Summary delete connection log
|
// @Summary 链接日志删除
|
||||||
// @Description delete connection log
|
// @Description 链接日志删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AuditConn true "connection log info"
|
// @Param body body model.AuditConn true "链接日志信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/audit_conn/delete [post]
|
// @Router /admin/audit_conn/delete [post]
|
||||||
@@ -81,13 +81,13 @@ func (a *Audit) ConnDelete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchConnDelete delete
|
// BatchConnDelete 删除
|
||||||
// @Tags connection log
|
// @Tags 链接日志
|
||||||
// @Summary batch delete connection logs
|
// @Summary 链接日志批量删除
|
||||||
// @Description batch delete connection logs
|
// @Description 链接日志批量删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AuditConnLogIds true "connection log"
|
// @Param body body admin.AuditConnLogIds true "链接日志"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/audit_conn/batchDelete [post]
|
// @Router /admin/audit_conn/batchDelete [post]
|
||||||
@@ -112,16 +112,16 @@ func (a *Audit) BatchConnDelete(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileList list
|
// FileList 列表
|
||||||
// @Tags file log
|
// @Tags 文件日志
|
||||||
// @Summary file log list
|
// @Summary 文件日志列表
|
||||||
// @Description file log list
|
// @Description 文件日志列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param peer_id query int false "target device"
|
// @Param peer_id query int false "目标设备"
|
||||||
// @Param from_peer query int false "source device"
|
// @Param from_peer query int false "来源设备"
|
||||||
// @Success 200 {object} response.Response{data=model.AuditFileList}
|
// @Success 200 {object} response.Response{data=model.AuditFileList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/audit_file/list [get]
|
// @Router /admin/audit_file/list [get]
|
||||||
@@ -144,13 +144,13 @@ func (a *Audit) FileList(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileDelete delete
|
// FileDelete 删除
|
||||||
// @Tags file log
|
// @Tags 文件日志
|
||||||
// @Summary delete file log
|
// @Summary 文件日志删除
|
||||||
// @Description delete file log
|
// @Description 文件日志删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AuditFile true "file log info"
|
// @Param body body model.AuditFile true "文件日志信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/audit_file/delete [post]
|
// @Router /admin/audit_file/delete [post]
|
||||||
@@ -180,13 +180,13 @@ func (a *Audit) FileDelete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchFileDelete delete
|
// BatchFileDelete 删除
|
||||||
// @Tags file log
|
// @Tags 文件日志
|
||||||
// @Summary batch delete file logs
|
// @Summary 文件日志批量删除
|
||||||
// @Description batch delete file logs
|
// @Description 文件日志批量删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AuditFileLogIds true "file log"
|
// @Param body body admin.AuditFileLogIds true "文件日志"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/audit_file/batchDelete [post]
|
// @Router /admin/audit_file/batchDelete [post]
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -13,10 +12,10 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig RUSTDESKservice config
|
// ServerConfig RUSTDESK服务配置
|
||||||
// @Tags ADMIN
|
// @Tags ADMIN
|
||||||
// @Summary RUSTDESKservice config
|
// @Summary RUSTDESK服务配置
|
||||||
// @Description service config, provides an api-server for the webclient
|
// @Description 服务配置,给webclient提供api-server
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -33,10 +32,10 @@ func (co *Config) ServerConfig(c *gin.Context) {
|
|||||||
response.Success(c, cf)
|
response.Success(c, cf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppConfig APPservice config
|
// AppConfig APP服务配置
|
||||||
// @Tags ADMIN
|
// @Tags ADMIN
|
||||||
// @Summary APPservice config
|
// @Summary APP服务配置
|
||||||
// @Description APPservice config
|
// @Description APP服务配置
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -49,10 +48,10 @@ func (co *Config) AppConfig(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminConfig ADMINservice config
|
// AdminConfig ADMIN服务配置
|
||||||
// @Tags ADMIN
|
// @Tags ADMIN
|
||||||
// @Summary ADMINservice config
|
// @Summary ADMIN服务配置
|
||||||
// @Description ADMINservice config
|
// @Description ADMIN服务配置
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -61,24 +60,8 @@ func (co *Config) AppConfig(c *gin.Context) {
|
|||||||
// @Security token
|
// @Security token
|
||||||
func (co *Config) AdminConfig(c *gin.Context) {
|
func (co *Config) AdminConfig(c *gin.Context) {
|
||||||
|
|
||||||
u := &model.User{}
|
u := service.AllService.UserService.CurUser(c)
|
||||||
token := c.GetHeader("api-token")
|
|
||||||
if token != "" {
|
|
||||||
u, _ = service.AllService.UserService.InfoByAccessToken(token)
|
|
||||||
if !service.AllService.UserService.CheckUserEnable(u) {
|
|
||||||
u.Id = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Id == 0 {
|
|
||||||
response.Success(c, &gin.H{
|
|
||||||
"title": global.Config.Admin.Title,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hello := global.Config.Admin.Hello
|
hello := global.Config.Admin.Hello
|
||||||
if hello == "" {
|
|
||||||
helloFile := global.Config.Admin.HelloFile
|
helloFile := global.Config.Admin.HelloFile
|
||||||
if helloFile != "" {
|
if helloFile != "" {
|
||||||
b, err := os.ReadFile(helloFile)
|
b, err := os.ReadFile(helloFile)
|
||||||
@@ -86,7 +69,6 @@ func (co *Config) AdminConfig(c *gin.Context) {
|
|||||||
hello = string(b)
|
hello = string(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//replace {{username}} to username
|
//replace {{username}} to username
|
||||||
hello = strings.Replace(hello, "{{username}}", u.Username, -1)
|
hello = strings.Replace(hello, "{{username}}", u.Username, -1)
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
package admin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeviceGroup struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detail device group
|
|
||||||
// @Tags device group
|
|
||||||
// @Summary device group details
|
|
||||||
// @Description device group details
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param id path int true "ID"
|
|
||||||
// @Success 200 {object} response.Response{data=model.Group}
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /admin/device_group/detail/{id} [get]
|
|
||||||
// @Security token
|
|
||||||
func (ct *DeviceGroup) Detail(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
iid, _ := strconv.Atoi(id)
|
|
||||||
u := service.AllService.GroupService.DeviceGroupInfoById(uint(iid))
|
|
||||||
if u.Id > 0 {
|
|
||||||
response.Success(c, u)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create create device group
|
|
||||||
// @Tags device group
|
|
||||||
// @Summary create device group
|
|
||||||
// @Description create device group
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param body body admin.DeviceGroupForm true "device group info"
|
|
||||||
// @Success 200 {object} response.Response{data=model.DeviceGroup}
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /admin/device_group/create [post]
|
|
||||||
// @Security token
|
|
||||||
func (ct *DeviceGroup) Create(c *gin.Context) {
|
|
||||||
f := &admin.DeviceGroupForm{}
|
|
||||||
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 := f.ToDeviceGroup()
|
|
||||||
err := service.AllService.GroupService.DeviceGroupCreate(u)
|
|
||||||
if err != nil {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.Success(c, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// List list
|
|
||||||
// @Tags group
|
|
||||||
// @Summary group list
|
|
||||||
// @Description group list
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param page query int false "page number"
|
|
||||||
// @Param page_size query int false "page size"
|
|
||||||
// @Success 200 {object} response.Response{data=model.GroupList}
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /admin/device_group/list [get]
|
|
||||||
// @Security token
|
|
||||||
func (ct *DeviceGroup) 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
|
|
||||||
}
|
|
||||||
res := service.AllService.GroupService.DeviceGroupList(query.Page, query.PageSize, nil)
|
|
||||||
response.Success(c, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update edit
|
|
||||||
// @Tags device group
|
|
||||||
// @Summary edit device group
|
|
||||||
// @Description edit device group
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param body body admin.DeviceGroupForm true "group info"
|
|
||||||
// @Success 200 {object} response.Response{data=model.Group}
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /admin/device_group/update [post]
|
|
||||||
// @Security token
|
|
||||||
func (ct *DeviceGroup) Update(c *gin.Context) {
|
|
||||||
f := &admin.DeviceGroupForm{}
|
|
||||||
if err := c.ShouldBindJSON(f); err != nil {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if f.Id == 0 {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errList := global.Validator.ValidStruct(c, f)
|
|
||||||
if len(errList) > 0 {
|
|
||||||
response.Fail(c, 101, errList[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
u := f.ToDeviceGroup()
|
|
||||||
err := service.AllService.GroupService.DeviceGroupUpdate(u)
|
|
||||||
if err != nil {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.Success(c, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete delete
|
|
||||||
// @Tags device group
|
|
||||||
// @Summary delete device group
|
|
||||||
// @Description delete device group
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param body body admin.DeviceGroupForm true "group info"
|
|
||||||
// @Success 200 {object} response.Response
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /admin/device_group/delete [post]
|
|
||||||
// @Security token
|
|
||||||
func (ct *DeviceGroup) Delete(c *gin.Context) {
|
|
||||||
f := &admin.DeviceGroupForm{}
|
|
||||||
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.GroupService.DeviceGroupInfoById(f.Id)
|
|
||||||
if u.Id > 0 {
|
|
||||||
err := service.AllService.GroupService.DeviceGroupDelete(u)
|
|
||||||
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"))
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/lib/upload"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/lib/upload"
|
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
type File struct {
|
type File struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OssToken file
|
// OssToken 文件
|
||||||
// @Tags file
|
// @Tags 文件
|
||||||
// @Summary getossToken
|
// @Summary 获取ossToken
|
||||||
// @Description getossToken
|
// @Description 获取ossToken
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -33,12 +33,12 @@ type FileBack struct {
|
|||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify callback after successful upload
|
// Notify 上传成功后回调
|
||||||
func (f *File) Notify(c *gin.Context) {
|
func (f *File) Notify(c *gin.Context) {
|
||||||
|
|
||||||
res := global.Oss.Verify(c.Request)
|
res := global.Oss.Verify(c.Request)
|
||||||
if !res {
|
if !res {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
response.Fail(c, 101, "权限错误")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fm := &FileBack{}
|
fm := &FileBack{}
|
||||||
@@ -50,13 +50,13 @@ func (f *File) Notify(c *gin.Context) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload upload file to local
|
// Upload 上传文件到本地
|
||||||
// @Tags file
|
// @Tags 文件
|
||||||
// @Summary upload file to local
|
// @Summary 上传文件到本地
|
||||||
// @Description upload file to local
|
// @Description 上传文件到本地
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param file formData file true "file upload example"
|
// @Param file formData file true "上传文件示例"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/file/upload [post]
|
// @Router /admin/file/upload [post]
|
||||||
@@ -71,12 +71,12 @@ func (f *File) Upload(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// upload the file to the specified directory
|
// 上传文件至指定目录
|
||||||
err = c.SaveUploadedFile(file, dst)
|
err = c.SaveUploadedFile(file, dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// return filewebaddress
|
// 返回文件web地址
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"url": webPath + file.Filename,
|
"url": webPath + file.Filename,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Group struct {
|
type Group struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail group
|
// Detail 群组
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary group details
|
// @Summary 群组详情
|
||||||
// @Description group details
|
// @Description 群组详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -35,13 +35,13 @@ func (ct *Group) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create group
|
// Create 创建群组
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary create group
|
// @Summary 创建群组
|
||||||
// @Description create group
|
// @Description 创建群组
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.GroupForm true "group info"
|
// @Param body body admin.GroupForm true "群组信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Group}
|
// @Success 200 {object} response.Response{data=model.Group}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/group/create [post]
|
// @Router /admin/group/create [post]
|
||||||
@@ -66,14 +66,14 @@ func (ct *Group) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary group list
|
// @Summary 群组列表
|
||||||
// @Description group list
|
// @Description 群组列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Success 200 {object} response.Response{data=model.GroupList}
|
// @Success 200 {object} response.Response{data=model.GroupList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/group/list [get]
|
// @Router /admin/group/list [get]
|
||||||
@@ -88,13 +88,13 @@ func (ct *Group) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary edit group
|
// @Summary 群组编辑
|
||||||
// @Description edit group
|
// @Description 群组编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.GroupForm true "group info"
|
// @Param body body admin.GroupForm true "群组信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Group}
|
// @Success 200 {object} response.Response{data=model.Group}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/group/update [post]
|
// @Router /admin/group/update [post]
|
||||||
@@ -123,13 +123,13 @@ func (ct *Group) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary delete group
|
// @Summary 群组删除
|
||||||
// @Description delete group
|
// @Description 群组删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.GroupForm true "group info"
|
// @Param body body admin.GroupForm true "群组信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/group/delete [post]
|
// @Router /admin/group/delete [post]
|
||||||
|
|||||||
+168
-87
@@ -1,48 +1,161 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/controller/api"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
apiReq "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
adResp "Gwen/http/response/admin"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
"github.com/mojocn/base64Captcha"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/controller/api"
|
"sync"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
"time"
|
||||||
apiReq "github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
adResp "github.com/lejianwen/rustdesk-api/v2/http/response/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Login struct {
|
type Login struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login login
|
// Captcha 验证码结构
|
||||||
// @Tags login
|
type Captcha struct {
|
||||||
// @Summary login
|
Id string `json:"id"` // 验证码 ID
|
||||||
// @Description login
|
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 登录
|
||||||
|
// @Description 登录
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.Login true "login info"
|
// @Param body body admin.Login true "登录信息"
|
||||||
// @Success 200 {object} response.Response{data=adResp.LoginPayload}
|
// @Success 200 {object} response.Response{data=adResp.LoginPayload}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/login [post]
|
// @Router /admin/login [post]
|
||||||
// @Security token
|
// @Security token
|
||||||
func (ct *Login) Login(c *gin.Context) {
|
func (ct *Login) Login(c *gin.Context) {
|
||||||
if global.Config.App.DisablePwdLogin {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "PwdLoginDisabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// check login limit
|
|
||||||
loginLimiter := global.LoginLimiter
|
|
||||||
clientIp := c.ClientIP()
|
|
||||||
_, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
|
|
||||||
|
|
||||||
f := &admin.Login{}
|
f := &admin.Login{}
|
||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
|
clientIp := c.ClientIP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loginLimiter.RecordFailedAttempt(clientIp)
|
|
||||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), 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())
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
@@ -50,15 +163,14 @@ func (ct *Login) Login(c *gin.Context) {
|
|||||||
|
|
||||||
errList := global.Validator.ValidStruct(c, f)
|
errList := global.Validator.ValidStruct(c, f)
|
||||||
if len(errList) > 0 {
|
if len(errList) > 0 {
|
||||||
loginLimiter.RecordFailedAttempt(clientIp)
|
|
||||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), clientIp))
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), clientIp))
|
||||||
response.Fail(c, 101, errList[0])
|
response.Fail(c, 101, errList[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether a captcha is required
|
// 检查是否需要验证码
|
||||||
if needCaptcha {
|
if loginLimiter.NeedsCaptcha(clientIp) {
|
||||||
if f.CaptchaId == "" || f.Captcha == "" || !loginLimiter.VerifyCaptcha(f.CaptchaId, f.Captcha) {
|
if f.Captcha == "" || !loginLimiter.VerifyCaptcha(clientIp, f.Captcha) {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError"))
|
response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -68,21 +180,14 @@ func (ct *Login) Login(c *gin.Context) {
|
|||||||
|
|
||||||
if u.Id == 0 {
|
if u.Id == 0 {
|
||||||
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), clientIp))
|
global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), clientIp))
|
||||||
loginLimiter.RecordFailedAttempt(clientIp)
|
loginLimiter.RecordFailure(clientIp)
|
||||||
if _, needCaptcha = loginLimiter.CheckSecurityStatus(clientIp); needCaptcha {
|
if loginLimiter.NeedsCaptcha(clientIp) {
|
||||||
|
// 移除原验证码,重新生成
|
||||||
|
loginLimiter.RemoveCaptcha(clientIp)
|
||||||
response.Fail(c, 110, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
response.Fail(c, 110, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||||
} else {
|
return
|
||||||
|
}
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !service.AllService.UserService.CheckUserEnable(u) {
|
|
||||||
if needCaptcha {
|
|
||||||
response.Fail(c, 110, response.TranslateMsg(c, "UserDisabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "UserDisabled"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,44 +200,30 @@ func (ct *Login) Login(c *gin.Context) {
|
|||||||
Platform: f.Platform,
|
Platform: f.Platform,
|
||||||
})
|
})
|
||||||
|
|
||||||
// login successful, clear the login limit
|
// 成功后清除记录
|
||||||
loginLimiter.RemoveAttempts(clientIp)
|
loginLimiter.RemoveRecord(clientIp)
|
||||||
|
|
||||||
|
// 清理过期记录
|
||||||
|
go loginLimiter.CleanupExpired()
|
||||||
|
|
||||||
responseLoginSuccess(c, u, ut.Token)
|
responseLoginSuccess(c, u, ut.Token)
|
||||||
}
|
}
|
||||||
func (ct *Login) Captcha(c *gin.Context) {
|
func (ct *Login) Captcha(c *gin.Context) {
|
||||||
loginLimiter := global.LoginLimiter
|
|
||||||
clientIp := c.ClientIP()
|
clientIp := c.ClientIP()
|
||||||
banned, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
|
if !loginLimiter.NeedsCaptcha(clientIp) {
|
||||||
if banned {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "LoginBanned"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !needCaptcha {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "NoCaptchaRequired"))
|
response.Fail(c, 101, response.TranslateMsg(c, "NoCaptchaRequired"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err, captcha := loginLimiter.RequireCaptcha()
|
captcha := loginLimiter.GenerateCaptcha(clientIp)
|
||||||
if err != nil {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError")+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err, b64 := loginLimiter.DrawCaptcha(captcha.Content)
|
|
||||||
if err != nil {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError")+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"captcha": gin.H{
|
"captcha": captcha,
|
||||||
"id": captcha.Id,
|
|
||||||
"b64": b64,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logout logout
|
// Logout 登出
|
||||||
// @Tags login
|
// @Tags 登录
|
||||||
// @Summary logout
|
// @Summary 登出
|
||||||
// @Description logout
|
// @Description 登出
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -148,29 +239,21 @@ func (ct *Login) Logout(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoginOptions
|
// LoginOptions
|
||||||
// @Tags login
|
// @Tags 登录
|
||||||
// @Summary login options
|
// @Summary 登录选项
|
||||||
// @Description login options
|
// @Description 登录选项
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} []string
|
// @Success 200 {object} []string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /admin/login-options [post]
|
// @Router /admin/login-options [post]
|
||||||
func (ct *Login) LoginOptions(c *gin.Context) {
|
func (ct *Login) LoginOptions(c *gin.Context) {
|
||||||
loginLimiter := global.LoginLimiter
|
ip := c.ClientIP()
|
||||||
clientIp := c.ClientIP()
|
|
||||||
banned, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
|
|
||||||
if banned {
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "LoginBanned"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ops := service.AllService.OauthService.GetOauthProviders()
|
ops := service.AllService.OauthService.GetOauthProviders()
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"ops": ops,
|
"ops": ops,
|
||||||
"register": global.Config.App.Register,
|
"register": global.Config.App.Register,
|
||||||
"need_captcha": needCaptcha,
|
"need_captcha": loginLimiter.NeedsCaptcha(ip),
|
||||||
"disable_pwd": global.Config.App.DisablePwdLogin,
|
|
||||||
"auto_oidc": global.Config.App.DisablePwdLogin && len(ops) == 1,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,13 +274,13 @@ func (ct *Login) OidcAuth(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(f.Op)
|
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, err.Error()))
|
response.Error(c, response.TranslateMsg(c, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
service.AllService.OauthService.SetOauthCache(state, &service.OauthCacheItem{
|
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
|
||||||
Action: service.OauthActionTypeLogin,
|
Action: service.OauthActionTypeLogin,
|
||||||
Op: f.Op,
|
Op: f.Op,
|
||||||
Id: f.Id,
|
Id: f.Id,
|
||||||
@@ -205,12 +288,10 @@ func (ct *Login) OidcAuth(c *gin.Context) {
|
|||||||
// DeviceOs: ct.Platform(c),
|
// DeviceOs: ct.Platform(c),
|
||||||
DeviceOs: f.DeviceInfo.Os,
|
DeviceOs: f.DeviceInfo.Os,
|
||||||
Uuid: f.Uuid,
|
Uuid: f.Uuid,
|
||||||
Verifier: verifier,
|
|
||||||
Nonce: nonce,
|
|
||||||
}, 5*60)
|
}, 5*60)
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"code": state,
|
"code": code,
|
||||||
"url": url,
|
"url": url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
type LoginLog struct {
|
type LoginLog struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail login log
|
// Detail 登录日志
|
||||||
// @Tags login log
|
// @Tags 登录日志
|
||||||
// @Summary login log details
|
// @Summary 登录日志详情
|
||||||
// @Description login log details
|
// @Description 登录日志详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -37,15 +37,15 @@ func (ct *LoginLog) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags login log
|
// @Tags 登录日志
|
||||||
// @Summary login log list
|
// @Summary 登录日志列表
|
||||||
// @Description login log list
|
// @Description 登录日志列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param user_id query int false "userID"
|
// @Param user_id query int false "用户ID"
|
||||||
// @Success 200 {object} response.Response{data=model.LoginLogList}
|
// @Success 200 {object} response.Response{data=model.LoginLogList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/login_log/list [get]
|
// @Router /admin/login_log/list [get]
|
||||||
@@ -65,13 +65,13 @@ func (ct *LoginLog) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags login log
|
// @Tags 登录日志
|
||||||
// @Summary delete login log
|
// @Summary 登录日志删除
|
||||||
// @Description delete login log
|
// @Description 登录日志删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.LoginLog true "login log info"
|
// @Param body body model.LoginLog true "登录日志信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/login_log/delete [post]
|
// @Router /admin/login_log/delete [post]
|
||||||
@@ -101,13 +101,13 @@ func (ct *LoginLog) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, err.Error())
|
response.Fail(c, 101, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchDelete delete
|
// BatchDelete 删除
|
||||||
// @Tags login log
|
// @Tags 登录日志
|
||||||
// @Summary batch delete login logs
|
// @Summary 登录日志批量删除
|
||||||
// @Description batch delete login logs
|
// @Description 登录日志批量删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.LoginLogIds true "login log"
|
// @Param body body admin.LoginLogIds true "登录日志"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/login_log/batchDelete [post]
|
// @Router /admin/login_log/batchDelete [post]
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressBook struct{}
|
type AddressBook struct{}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags my address book
|
// @Tags 我的地址簿
|
||||||
// @Summary address book list
|
// @Summary 地址簿列表
|
||||||
// @Description address book list
|
// @Description 地址簿列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookList}
|
// @Success 200 {object} response.Response{data=model.AddressBookList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book/list [get]
|
// @Router /admin/my/address_book/list [get]
|
||||||
@@ -34,7 +34,7 @@ func (ct *AddressBook) List(c *gin.Context) {
|
|||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
query.UserId = int(u.Id)
|
query.UserId = int(u.Id)
|
||||||
res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
|
||||||
//preload address book name
|
//预加载地址簿名称
|
||||||
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
|
tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
|
||||||
return txc.Select("id,name")
|
return txc.Select("id,name")
|
||||||
})
|
})
|
||||||
@@ -60,13 +60,13 @@ func (ct *AddressBook) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create address book
|
// Create 创建地址簿
|
||||||
// @Tags my address book
|
// @Tags 我的地址簿
|
||||||
// @Summary create address book
|
// @Summary 创建地址簿
|
||||||
// @Description create address book
|
// @Description 创建地址簿
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book/create [post]
|
// @Router /admin/my/address_book/create [post]
|
||||||
@@ -104,13 +104,13 @@ func (ct *AddressBook) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags my address book
|
// @Tags 我的地址簿
|
||||||
// @Summary edit address book
|
// @Summary 地址簿编辑
|
||||||
// @Description edit address book
|
// @Description 地址簿编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBook}
|
// @Success 200 {object} response.Response{data=model.AddressBook}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book/update [post]
|
// @Router /admin/my/address_book/update [post]
|
||||||
@@ -158,13 +158,13 @@ func (ct *AddressBook) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags my address book
|
// @Tags 我的地址簿
|
||||||
// @Summary delete address book
|
// @Summary 地址簿删除
|
||||||
// @Description delete address book
|
// @Description 地址簿删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.AddressBookForm true "address book info"
|
// @Param body body admin.AddressBookForm true "地址簿信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book/delete [post]
|
// @Router /admin/my/address_book/delete [post]
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressBookCollection struct {
|
type AddressBookCollection struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create address book name
|
// Create 创建地址簿名称
|
||||||
// @Tags my address book name
|
// @Tags 我的地址簿名称
|
||||||
// @Summary create address book name
|
// @Summary 创建地址簿名称
|
||||||
// @Description create address book name
|
// @Description 创建地址簿名称
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollection true "address book name info"
|
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection/create [post]
|
// @Router /admin/my/address_book_collection/create [post]
|
||||||
@@ -45,14 +45,14 @@ func (abc *AddressBookCollection) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags my address book name
|
// @Tags 我的地址簿名称
|
||||||
// @Summary address book name list
|
// @Summary 地址簿名称列表
|
||||||
// @Description address book name list
|
// @Description 地址簿名称列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection/list [get]
|
// @Router /admin/my/address_book_collection/list [get]
|
||||||
@@ -71,13 +71,13 @@ func (abc *AddressBookCollection) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags my address book name
|
// @Tags 我的地址簿名称
|
||||||
// @Summary edit address book name
|
// @Summary 地址簿名称编辑
|
||||||
// @Description edit address book name
|
// @Description 地址簿名称编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollection true "address book name info"
|
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection/update [post]
|
// @Router /admin/my/address_book_collection/update [post]
|
||||||
@@ -98,10 +98,10 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
//if f.UserId != u.Id {
|
if f.UserId != u.Id {
|
||||||
// response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
|
||||||
// return
|
return
|
||||||
//}
|
}
|
||||||
ex := service.AllService.AddressBookService.CollectionInfoById(f.Id)
|
ex := service.AllService.AddressBookService.CollectionInfoById(f.Id)
|
||||||
if ex.Id == 0 {
|
if ex.Id == 0 {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
@@ -120,13 +120,13 @@ func (abc *AddressBookCollection) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags my address book name
|
// @Tags 我的地址簿名称
|
||||||
// @Summary delete address book name
|
// @Summary 地址簿名称删除
|
||||||
// @Description delete address book name
|
// @Description 地址簿名称删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollection true "address book name info"
|
// @Param body body model.AddressBookCollection true "地址簿名称信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection/delete [post]
|
// @Router /admin/my/address_book_collection/delete [post]
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressBookCollectionRule struct {
|
type AddressBookCollectionRule struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags my address book rules
|
// @Tags 我的地址簿规则
|
||||||
// @Summary address book rule list
|
// @Summary 地址簿规则列表
|
||||||
// @Description address book rule list
|
// @Description 地址簿规则列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param is_my query int false "whether it is mine"
|
// @Param is_my query int false "是否是我的"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Param collection_id query int false "address book collectionid"
|
// @Param collection_id query int false "地址簿集合id"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection_rule/list [get]
|
// @Router /admin/my/address_book_collection_rule/list [get]
|
||||||
@@ -46,13 +46,13 @@ func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create address book rule
|
// Create 创建地址簿规则
|
||||||
// @Tags my address book rules
|
// @Tags 我的地址簿规则
|
||||||
// @Summary create address book rule
|
// @Summary 创建地址簿规则
|
||||||
// @Description create address book rule
|
// @Description 创建地址簿规则
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollectionRule true "address book rule info"
|
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection_rule/create [post]
|
// @Router /admin/my/address_book_collection_rule/create [post]
|
||||||
@@ -100,21 +100,21 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
|
|||||||
//check to_id
|
//check to_id
|
||||||
if t.Type == model.ShareAddressBookRuleTypePersonal {
|
if t.Type == model.ShareAddressBookRuleTypePersonal {
|
||||||
if t.ToId == t.UserId {
|
if t.ToId == t.UserId {
|
||||||
return "CannotShareToSelf", false
|
return "ParamsError", false
|
||||||
}
|
}
|
||||||
tou := service.AllService.UserService.InfoById(t.ToId)
|
tou := service.AllService.UserService.InfoById(t.ToId)
|
||||||
if tou.Id == 0 {
|
if tou.Id == 0 {
|
||||||
return "ItemNotFound", false
|
return "ItemNotFound", false
|
||||||
}
|
}
|
||||||
//non-admins cannot share with users outside their own organization
|
//非管理员不能分享给非本组织用户
|
||||||
//if tou.GroupId != u.GroupId {
|
if tou.GroupId != u.GroupId {
|
||||||
// return "NoAccess", false
|
return "NoAccess", false
|
||||||
//}
|
}
|
||||||
} else if t.Type == model.ShareAddressBookRuleTypeGroup {
|
} else if t.Type == model.ShareAddressBookRuleTypeGroup {
|
||||||
//non-admins cannot share with other groups
|
//非管理员不能分享给其他组
|
||||||
//if t.ToId != u.GroupId {
|
if t.ToId != u.GroupId {
|
||||||
// return "NoAccess", false
|
return "NoAccess", false
|
||||||
//}
|
}
|
||||||
|
|
||||||
tog := service.AllService.GroupService.InfoById(t.ToId)
|
tog := service.AllService.GroupService.InfoById(t.ToId)
|
||||||
if tog.Id == 0 {
|
if tog.Id == 0 {
|
||||||
@@ -123,8 +123,8 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
|
|||||||
} else {
|
} else {
|
||||||
return "ParamsError", false
|
return "ParamsError", false
|
||||||
}
|
}
|
||||||
// duplicate check
|
// 重复检查
|
||||||
ex := service.AllService.AddressBookService.RuleInfoByToIdAndCid(t.Type, t.ToId, t.CollectionId)
|
ex := service.AllService.AddressBookService.RulePersonalInfoByToIdAndCid(t.ToId, t.CollectionId)
|
||||||
if t.Id == 0 && ex.Id > 0 {
|
if t.Id == 0 && ex.Id > 0 {
|
||||||
return "ItemExists", false
|
return "ItemExists", false
|
||||||
}
|
}
|
||||||
@@ -134,13 +134,13 @@ func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.Address
|
|||||||
return "", true
|
return "", true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags my address book rules
|
// @Tags 我的地址簿规则
|
||||||
// @Summary edit address book rule
|
// @Summary 地址簿规则编辑
|
||||||
// @Description edit address book rule
|
// @Description 地址簿规则编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollectionRule true "address book rule info"
|
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||||
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
// @Success 200 {object} response.Response{data=model.AddressBookCollection}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection_rule/update [post]
|
// @Router /admin/my/address_book_collection_rule/update [post]
|
||||||
@@ -185,13 +185,13 @@ func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags my address book rules
|
// @Tags 我的地址簿规则
|
||||||
// @Summary delete address book rule
|
// @Summary 地址簿规则删除
|
||||||
// @Description delete address book rule
|
// @Description 地址簿规则删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.AddressBookCollectionRule true "address book rule info"
|
// @Param body body model.AddressBookCollectionRule true "地址簿规则信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/address_book_collection_rule/delete [post]
|
// @Router /admin/my/address_book_collection_rule/delete [post]
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoginLog struct {
|
type LoginLog struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags my login logs
|
// @Tags 我的登录日志
|
||||||
// @Summary login log list
|
// @Summary 登录日志列表
|
||||||
// @Description login log list
|
// @Description 登录日志列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param user_id query int false "userID"
|
// @Param user_id query int false "用户ID"
|
||||||
// @Success 200 {object} response.Response{data=model.LoginLogList}
|
// @Success 200 {object} response.Response{data=model.LoginLogList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/login_log/list [get]
|
// @Router /admin/my/login_log/list [get]
|
||||||
@@ -40,13 +40,13 @@ func (ct *LoginLog) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags my login logs
|
// @Tags 我的登录日志
|
||||||
// @Summary delete login log
|
// @Summary 登录日志删除
|
||||||
// @Description delete login log
|
// @Description 登录日志删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.LoginLog true "login log info"
|
// @Param body body model.LoginLog true "登录日志信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/login_log/delete [post]
|
// @Router /admin/my/login_log/delete [post]
|
||||||
@@ -81,13 +81,13 @@ func (ct *LoginLog) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, err.Error())
|
response.Fail(c, 101, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchDelete delete
|
// BatchDelete 删除
|
||||||
// @Tags my login logs
|
// @Tags 我的登录日志
|
||||||
// @Summary batch delete login logs
|
// @Summary 登录日志批量删除
|
||||||
// @Description batch delete login logs
|
// @Description 登录日志批量删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.LoginLogIds true "login log"
|
// @Param body body admin.LoginLogIds true "登录日志"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/login_log/batchDelete [post]
|
// @Router /admin/my/login_log/batchDelete [post]
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -12,18 +12,18 @@ import (
|
|||||||
type Peer struct {
|
type Peer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags my devices
|
// @Tags 我的设备
|
||||||
// @Summary device list
|
// @Summary 设备列表
|
||||||
// @Description device list
|
// @Description 设备列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param time_ago query int false "time"
|
// @Param time_ago query int false "时间"
|
||||||
// @Param id query string false "ID"
|
// @Param id query string false "ID"
|
||||||
// @Param hostname query string false "hostname"
|
// @Param hostname query string false "主机名"
|
||||||
// @Param uuids query string false "uuids separated by commas"
|
// @Param uuids query string false "uuids 用逗号分隔"
|
||||||
// @Success 200 {object} response.Response{data=model.PeerList}
|
// @Success 200 {object} response.Response{data=model.PeerList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/peer/list [get]
|
// @Router /admin/my/peer/list [get]
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShareRecord struct {
|
type ShareRecord struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List share record list
|
// List 分享记录列表
|
||||||
// @Tags my share records
|
// @Tags 我的分享记录
|
||||||
// @Summary share record list
|
// @Summary 分享记录列表
|
||||||
// @Description share record list
|
// @Description 分享记录列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/share_record/list [get]
|
// @Router /admin/my/share_record/list [get]
|
||||||
@@ -37,13 +37,13 @@ func (sr *ShareRecord) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete share record
|
// Delete 分享记录删除
|
||||||
// @Tags my share records
|
// @Tags 我的分享记录
|
||||||
// @Summary delete share record
|
// @Summary 分享记录删除
|
||||||
// @Description delete share record
|
// @Description 分享记录删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.ShareRecordForm true "share record info"
|
// @Param body body admin.ShareRecordForm true "分享记录信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/share_record/delete [post]
|
// @Router /admin/my/share_record/delete [post]
|
||||||
@@ -78,10 +78,10 @@ func (sr *ShareRecord) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchDelete batch delete my share records
|
// BatchDelete 批量删除我的分享记录
|
||||||
// @Tags my
|
// @Tags 我的
|
||||||
// @Summary batch delete my share records
|
// @Summary 批量删除我的分享记录
|
||||||
// @Description batch delete my share records
|
// @Description 批量删除我的分享记录
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
|
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
package my
|
package my
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Tag struct{}
|
type Tag struct{}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags my tags
|
// @Tags 我的标签
|
||||||
// @Summary tag list
|
// @Summary 标签列表
|
||||||
// @Description tag list
|
// @Description 标签列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param is_my query int false "whether it is mine"
|
// @Param is_my query int false "是否是我的"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Success 200 {object} response.Response{data=model.TagList}
|
// @Success 200 {object} response.Response{data=model.TagList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/tag/list [get]
|
// @Router /admin/my/tag/list [get]
|
||||||
@@ -45,13 +45,13 @@ func (ct *Tag) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create tag
|
// Create 创建标签
|
||||||
// @Tags my tags
|
// @Tags 我的标签
|
||||||
// @Summary create tag
|
// @Summary 创建标签
|
||||||
// @Description create tag
|
// @Description 创建标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.TagForm true "tag info"
|
// @Param body body admin.TagForm true "标签信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Tag}
|
// @Success 200 {object} response.Response{data=model.Tag}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/tag/create [post]
|
// @Router /admin/my/tag/create [post]
|
||||||
@@ -78,13 +78,13 @@ func (ct *Tag) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags my tags
|
// @Tags 我的标签
|
||||||
// @Summary edit tag
|
// @Summary 标签编辑
|
||||||
// @Description edit tag
|
// @Description 标签编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.TagForm true "tag info"
|
// @Param body body admin.TagForm true "标签信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Tag}
|
// @Success 200 {object} response.Response{data=model.Tag}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/tag/update [post]
|
// @Router /admin/my/tag/update [post]
|
||||||
@@ -133,13 +133,13 @@ func (ct *Tag) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags tag
|
// @Tags 标签
|
||||||
// @Summary delete tag
|
// @Summary 标签删除
|
||||||
// @Description delete tag
|
// @Description 标签删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.TagForm true "tag info"
|
// @Param body body admin.TagForm true "标签信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/my/tag/delete [post]
|
// @Router /admin/my/tag/delete [post]
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
adminReq "Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
"strconv"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
adminReq "github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Oauth struct {
|
type Oauth struct {
|
||||||
@@ -44,41 +43,39 @@ func (o *Oauth) ToBind(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(f.Op)
|
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, err.Error()))
|
response.Error(c, response.TranslateMsg(c, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
service.AllService.OauthService.SetOauthCache(state, &service.OauthCacheItem{
|
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
|
||||||
Action: service.OauthActionTypeBind,
|
Action: service.OauthActionTypeBind,
|
||||||
Op: f.Op,
|
Op: f.Op,
|
||||||
UserId: u.Id,
|
UserId: u.Id,
|
||||||
Verifier: verifier,
|
|
||||||
Nonce: nonce,
|
|
||||||
}, 5*60)
|
}, 5*60)
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"code": state,
|
"code": code,
|
||||||
"url": url,
|
"url": url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm confirm authorized login
|
// Confirm 确认授权登录
|
||||||
func (o *Oauth) Confirm(c *gin.Context) {
|
func (o *Oauth) Confirm(c *gin.Context) {
|
||||||
j := &adminReq.OauthConfirmForm{}
|
j := &adminReq.OauthConfirmForm{}
|
||||||
err := c.ShouldBindJSON(j)
|
err := c.ShouldBindJSON(j)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Fail(c, 101, "参数错误"+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if j.Code == "" {
|
if j.Code == "" {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
response.Fail(c, 101, "参数错误: code 不存在")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v := service.AllService.OauthService.GetOauthCache(j.Code)
|
v := service.AllService.OauthService.GetOauthCache(j.Code)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "OauthExpired"))
|
response.Fail(c, 101, "授权已过期")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
@@ -140,8 +137,8 @@ func (o *Oauth) Unbind(c *gin.Context) {
|
|||||||
|
|
||||||
// Detail Oauth
|
// Detail Oauth
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary Oauthdetails
|
// @Summary Oauth详情
|
||||||
// @Description Oauthdetails
|
// @Description Oauth详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -161,13 +158,13 @@ func (o *Oauth) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create createOauth
|
// Create 创建Oauth
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary createOauth
|
// @Summary 创建Oauth
|
||||||
// @Description createOauth
|
// @Description 创建Oauth
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.OauthForm true "Oauthinfo"
|
// @Param body body admin.OauthForm true "Oauth信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Oauth}
|
// @Success 200 {object} response.Response{data=model.Oauth}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/oauth/create [post]
|
// @Router /admin/oauth/create [post]
|
||||||
@@ -202,14 +199,14 @@ func (o *Oauth) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary Oauthlist
|
// @Summary Oauth列表
|
||||||
// @Description Oauthlist
|
// @Description Oauth列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Success 200 {object} response.Response{data=model.OauthList}
|
// @Success 200 {object} response.Response{data=model.OauthList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/oauth/list [get]
|
// @Router /admin/oauth/list [get]
|
||||||
@@ -224,13 +221,13 @@ func (o *Oauth) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary Oauthedit
|
// @Summary Oauth编辑
|
||||||
// @Description Oauthedit
|
// @Description Oauth编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.OauthForm true "Oauthinfo"
|
// @Param body body admin.OauthForm true "Oauth信息"
|
||||||
// @Success 200 {object} response.Response{data=model.OauthList}
|
// @Success 200 {object} response.Response{data=model.OauthList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/oauth/update [post]
|
// @Router /admin/oauth/update [post]
|
||||||
@@ -259,13 +256,13 @@ func (o *Oauth) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary Oauthdelete
|
// @Summary Oauth删除
|
||||||
// @Description Oauthdelete
|
// @Description Oauth删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.OauthForm true "Oauthinfo"
|
// @Param body body admin.OauthForm true "Oauth信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/oauth/delete [post]
|
// @Router /admin/oauth/delete [post]
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
type Peer struct {
|
type Peer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail device
|
// Detail 设备
|
||||||
// @Tags device
|
// @Tags 设备
|
||||||
// @Summary device details
|
// @Summary 设备详情
|
||||||
// @Description device details
|
// @Description 设备详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -37,13 +37,13 @@ func (ct *Peer) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create device
|
// Create 创建设备
|
||||||
// @Tags device
|
// @Tags 设备
|
||||||
// @Summary create device
|
// @Summary 创建设备
|
||||||
// @Description create device
|
// @Description 创建设备
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.PeerForm true "device info"
|
// @Param body body admin.PeerForm true "设备信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Peer}
|
// @Success 200 {object} response.Response{data=model.Peer}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/peer/create [post]
|
// @Router /admin/peer/create [post]
|
||||||
@@ -68,18 +68,18 @@ func (ct *Peer) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags device
|
// @Tags 设备
|
||||||
// @Summary device list
|
// @Summary 设备列表
|
||||||
// @Description device list
|
// @Description 设备列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param time_ago query int false "time"
|
// @Param time_ago query int false "时间"
|
||||||
// @Param id query string false "ID"
|
// @Param id query string false "ID"
|
||||||
// @Param hostname query string false "hostname"
|
// @Param hostname query string false "主机名"
|
||||||
// @Param uuids query string false "uuids separated by commas"
|
// @Param uuids query string false "uuids 用逗号分隔"
|
||||||
// @Success 200 {object} response.Response{data=model.PeerList}
|
// @Success 200 {object} response.Response{data=model.PeerList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/peer/list [get]
|
// @Router /admin/peer/list [get]
|
||||||
@@ -108,26 +108,17 @@ func (ct *Peer) List(c *gin.Context) {
|
|||||||
if query.Uuids != "" {
|
if query.Uuids != "" {
|
||||||
tx.Where("uuid in (?)", query.Uuids)
|
tx.Where("uuid in (?)", query.Uuids)
|
||||||
}
|
}
|
||||||
if query.Username != "" {
|
|
||||||
tx.Where("username like ?", "%"+query.Username+"%")
|
|
||||||
}
|
|
||||||
if query.Ip != "" {
|
|
||||||
tx.Where("last_online_ip like ?", "%"+query.Ip+"%")
|
|
||||||
}
|
|
||||||
if query.Alias != "" {
|
|
||||||
tx.Where("alias like ?", "%"+query.Alias+"%")
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags device
|
// @Tags 设备
|
||||||
// @Summary edit device
|
// @Summary 设备编辑
|
||||||
// @Description edit device
|
// @Description 设备编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.PeerForm true "device info"
|
// @Param body body admin.PeerForm true "设备信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Peer}
|
// @Success 200 {object} response.Response{data=model.Peer}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/peer/update [post]
|
// @Router /admin/peer/update [post]
|
||||||
@@ -156,13 +147,13 @@ func (ct *Peer) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags device
|
// @Tags 设备
|
||||||
// @Summary delete device
|
// @Summary 设备删除
|
||||||
// @Description delete device
|
// @Description 设备删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.PeerForm true "device info"
|
// @Param body body admin.PeerForm true "设备信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/peer/delete [post]
|
// @Router /admin/peer/delete [post]
|
||||||
@@ -192,13 +183,13 @@ func (ct *Peer) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchDelete batch delete
|
// BatchDelete 批量删除
|
||||||
// @Tags device
|
// @Tags 设备
|
||||||
// @Summary batch delete devices
|
// @Summary 批量设备删除
|
||||||
// @Description batch delete devices
|
// @Description 批量设备删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.PeerBatchDeleteForm true "deviceid"
|
// @Param body body admin.PeerBatchDeleteForm true "设备id"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/peer/batchDelete [post]
|
// @Router /admin/peer/batchDelete [post]
|
||||||
@@ -232,7 +223,7 @@ func (ct *Peer) SimpleData(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
res := service.AllService.PeerService.List(1, 99999, func(tx *gorm.DB) {
|
res := service.AllService.PeerService.List(1, 99999, func(tx *gorm.DB) {
|
||||||
//information that can be made public
|
//可以公开的情报
|
||||||
tx.Select("id,version")
|
tx.Select("id,version")
|
||||||
tx.Where("id in (?)", f.Ids)
|
tx.Where("id in (?)", f.Ids)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rustdesk struct {
|
type Rustdesk struct {
|
||||||
@@ -25,7 +25,7 @@ func (r *Rustdesk) CmdList(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
res := service.AllService.ServerCmdService.List(q.Page, 9999)
|
res := service.AllService.ServerCmdService.List(q.Page, 9999)
|
||||||
//add system commands before the list
|
//在列表前添加系统命令
|
||||||
list := make([]*model.ServerCmd, 0)
|
list := make([]*model.ServerCmd, 0)
|
||||||
list = append(list, model.SysIdServerCmds...)
|
list = append(list, model.SysIdServerCmds...)
|
||||||
list = append(list, model.SysRelayServerCmds...)
|
list = append(list, model.SysRelayServerCmds...)
|
||||||
@@ -119,16 +119,7 @@ func (r *Rustdesk) SendCmd(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
res, err := service.AllService.ServerCmdService.SendCmd(rc.Target, rc.Cmd, rc.Option)
|
||||||
port := 0
|
|
||||||
switch rc.Target {
|
|
||||||
case model.ServerCmdTargetIdServer:
|
|
||||||
port = global.Config.Admin.IdServerPort - 1
|
|
||||||
case model.ServerCmdTargetRelayServer:
|
|
||||||
port = global.Config.Admin.RelayServerPort
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := service.AllService.ServerCmdService.SendCmd(port, rc.Cmd, rc.Option)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Fail(c, 101, err.Error())
|
response.Fail(c, 101, err.Error())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShareRecord struct {
|
type ShareRecord struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags share record
|
// @Tags 分享记录
|
||||||
// @Summary share record list
|
// @Summary 分享记录列表
|
||||||
// @Description share record list
|
// @Description 分享记录列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param user_id query int false "userID"
|
// @Param user_id query int false "用户ID"
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/share_record/list [get]
|
// @Router /admin/share_record/list [get]
|
||||||
@@ -39,13 +39,13 @@ func (sr *ShareRecord) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags share record
|
// @Tags 分享记录
|
||||||
// @Summary delete share record
|
// @Summary 分享记录删除
|
||||||
// @Description delete share record
|
// @Description 分享记录删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.ShareRecordForm true "share record info"
|
// @Param body body admin.ShareRecordForm true "分享记录信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/share_record/delete [post]
|
// @Router /admin/share_record/delete [post]
|
||||||
@@ -75,10 +75,10 @@ func (sr *ShareRecord) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchDelete batch delete
|
// BatchDelete 批量删除
|
||||||
// @Tags share record
|
// @Tags 分享记录
|
||||||
// @Summary batch share records
|
// @Summary 批量分享记录
|
||||||
// @Description batch share records
|
// @Description 批量分享记录
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
|
// @Param body body admin.PeerShareRecordBatchDeleteForm true "id"
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
type Tag struct {
|
type Tag struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail tag
|
// Detail 标签
|
||||||
// @Tags tag
|
// @Tags 标签
|
||||||
// @Summary tag details
|
// @Summary 标签详情
|
||||||
// @Description tag details
|
// @Description 标签详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -41,13 +41,13 @@ func (ct *Tag) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create create tag
|
// Create 创建标签
|
||||||
// @Tags tag
|
// @Tags 标签
|
||||||
// @Summary create tag
|
// @Summary 创建标签
|
||||||
// @Description create tag
|
// @Description 创建标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.TagForm true "tag info"
|
// @Param body body admin.TagForm true "标签信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Tag}
|
// @Success 200 {object} response.Response{data=model.Tag}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/tag/create [post]
|
// @Router /admin/tag/create [post]
|
||||||
@@ -76,16 +76,16 @@ func (ct *Tag) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags tag
|
// @Tags 标签
|
||||||
// @Summary tag list
|
// @Summary 标签列表
|
||||||
// @Description tag list
|
// @Description 标签列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param is_my query int false "whether it is mine"
|
// @Param is_my query int false "是否是我的"
|
||||||
// @Param user_id query int false "userid"
|
// @Param user_id query int false "用户id"
|
||||||
// @Success 200 {object} response.Response{data=model.TagList}
|
// @Success 200 {object} response.Response{data=model.TagList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/tag/list [get]
|
// @Router /admin/tag/list [get]
|
||||||
@@ -110,13 +110,13 @@ func (ct *Tag) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags tag
|
// @Tags 标签
|
||||||
// @Summary edit tag
|
// @Summary 标签编辑
|
||||||
// @Description edit tag
|
// @Description 标签编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.TagForm true "tag info"
|
// @Param body body admin.TagForm true "标签信息"
|
||||||
// @Success 200 {object} response.Response{data=model.Tag}
|
// @Success 200 {object} response.Response{data=model.Tag}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/tag/update [post]
|
// @Router /admin/tag/update [post]
|
||||||
@@ -150,13 +150,13 @@ func (ct *Tag) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags tag
|
// @Tags 标签
|
||||||
// @Summary delete tag
|
// @Summary 标签删除
|
||||||
// @Description delete tag
|
// @Description 标签删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.TagForm true "tag info"
|
// @Param body body admin.TagForm true "标签信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/tag/delete [post]
|
// @Router /admin/tag/delete [post]
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
adResp "Gwen/http/response/admin"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
adResp "github.com/lejianwen/rustdesk-api/v2/http/response/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/utils"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -16,10 +15,10 @@ import (
|
|||||||
type User struct {
|
type User struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail administrator
|
// Detail 管理员
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary administrator details
|
// @Summary 管理员详情
|
||||||
// @Description administrator details
|
// @Description 管理员详情
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "ID"
|
// @Param id path int true "ID"
|
||||||
@@ -39,13 +38,13 @@ func (ct *User) Detail(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create administrator
|
// Create 管理员
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary create administrator
|
// @Summary 创建管理员
|
||||||
// @Description create administrator
|
// @Description 创建管理员
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.UserForm true "administrator info"
|
// @Param body body admin.UserForm true "管理员信息"
|
||||||
// @Success 200 {object} response.Response{data=model.User}
|
// @Success 200 {object} response.Response{data=model.User}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user/create [post]
|
// @Router /admin/user/create [post]
|
||||||
@@ -70,15 +69,15 @@ func (ct *User) Create(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary administrator list
|
// @Summary 管理员列表
|
||||||
// @Description administrator list
|
// @Description 管理员列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param username query int false "account"
|
// @Param username query int false "账户"
|
||||||
// @Success 200 {object} response.Response{data=model.UserList}
|
// @Success 200 {object} response.Response{data=model.UserList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user/list [get]
|
// @Router /admin/user/list [get]
|
||||||
@@ -97,13 +96,13 @@ func (ct *User) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edit
|
// Update 编辑
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary edit administrator
|
// @Summary 管理员编辑
|
||||||
// @Description edit administrator
|
// @Description 管理员编辑
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.UserForm true "user info"
|
// @Param body body admin.UserForm true "用户信息"
|
||||||
// @Success 200 {object} response.Response{data=model.User}
|
// @Success 200 {object} response.Response{data=model.User}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user/update [post]
|
// @Router /admin/user/update [post]
|
||||||
@@ -132,13 +131,13 @@ func (ct *User) Update(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary delete administrator
|
// @Summary 管理员删除
|
||||||
// @Description delete administrator
|
// @Description 管理员编删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.UserForm true "user info"
|
// @Param body body admin.UserForm true "用户信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user/delete [post]
|
// @Router /admin/user/delete [post]
|
||||||
@@ -168,13 +167,13 @@ func (ct *User) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePassword change password
|
// UpdatePassword 修改密码
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary change password
|
// @Summary 修改密码
|
||||||
// @Description change password
|
// @Description 修改密码
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.UserPasswordForm true "user info"
|
// @Param body body admin.UserPasswordForm true "用户信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user/updatePassword [post]
|
// @Router /admin/user/updatePassword [post]
|
||||||
@@ -203,10 +202,10 @@ func (ct *User) UpdatePassword(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current current user
|
// Current 当前用户
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary current user
|
// @Summary 当前用户
|
||||||
// @Description current user
|
// @Description 当前用户
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response{data=adResp.LoginPayload}
|
// @Success 200 {object} response.Response{data=adResp.LoginPayload}
|
||||||
@@ -220,13 +219,13 @@ func (ct *User) Current(c *gin.Context) {
|
|||||||
responseLoginSuccess(c, u, t)
|
responseLoginSuccess(c, u, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeCurPwd change the current user's password
|
// ChangeCurPwd 修改当前用户密码
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary change the current user's password
|
// @Summary 修改当前用户密码
|
||||||
// @Description change the current user's password
|
// @Description 修改当前用户密码
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.ChangeCurPasswordForm true "user info"
|
// @Param body body admin.ChangeCurPasswordForm true "用户信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user/changeCurPwd [post]
|
// @Router /admin/user/changeCurPwd [post]
|
||||||
@@ -244,10 +243,11 @@ func (ct *User) ChangeCurPwd(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
// Verify the old password only when the account already has one set
|
// If the password is not empty, the old password is verified
|
||||||
|
// otherwise, the old password is not verified
|
||||||
if !service.AllService.UserService.IsPasswordEmptyByUser(u) {
|
if !service.AllService.UserService.IsPasswordEmptyByUser(u) {
|
||||||
ok, _, err := utils.VerifyPassword(u.Password, f.OldPassword)
|
oldPwd := service.AllService.UserService.EncryptPassword(f.OldPassword)
|
||||||
if err != nil || !ok {
|
if u.Password != oldPwd {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "OldPasswordError"))
|
response.Fail(c, 101, response.TranslateMsg(c, "OldPasswordError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -261,9 +261,9 @@ func (ct *User) ChangeCurPwd(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MyOauth
|
// MyOauth
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary my authorizations
|
// @Summary 我的授权
|
||||||
// @Description my authorizations
|
// @Description 我的授权
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response{data=[]adResp.UserOauthItem}
|
// @Success 200 {object} response.Response{data=[]adResp.UserOauthItem}
|
||||||
@@ -296,12 +296,32 @@ func (ct *User) MyOauth(c *gin.Context) {
|
|||||||
|
|
||||||
// groupUsers
|
// groupUsers
|
||||||
func (ct *User) GroupUsers(c *gin.Context) {
|
func (ct *User) GroupUsers(c *gin.Context) {
|
||||||
aG := service.AllService.GroupService.List(1, 999, nil)
|
q := &admin.GroupUsersQuery{}
|
||||||
aU := service.AllService.UserService.List(1, 9999, nil)
|
if err := c.ShouldBindJSON(q); err != nil {
|
||||||
response.Success(c, gin.H{
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
"groups": aG.Groups,
|
return
|
||||||
"users": aU.Users,
|
}
|
||||||
|
u := service.AllService.UserService.CurUser(c)
|
||||||
|
gid := u.GroupId
|
||||||
|
uid := u.Id
|
||||||
|
if service.AllService.UserService.IsAdmin(u) && q.UserId > 0 {
|
||||||
|
nu := service.AllService.UserService.InfoById(q.UserId)
|
||||||
|
gid = nu.GroupId
|
||||||
|
uid = q.UserId
|
||||||
|
}
|
||||||
|
res := service.AllService.UserService.List(1, 999, func(tx *gorm.DB) {
|
||||||
|
tx.Where("group_id = ?", gid)
|
||||||
})
|
})
|
||||||
|
var data []*adResp.GroupUsersPayload
|
||||||
|
for _, _u := range res.Users {
|
||||||
|
gup := &adResp.GroupUsersPayload{}
|
||||||
|
gup.FromUser(_u)
|
||||||
|
if _u.Id == uid {
|
||||||
|
gup.Status = 0
|
||||||
|
}
|
||||||
|
data = append(data, gup)
|
||||||
|
}
|
||||||
|
response.Success(c, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register
|
// Register
|
||||||
@@ -320,23 +340,12 @@ func (ct *User) Register(c *gin.Context) {
|
|||||||
response.Fail(c, 101, errList[0])
|
response.Fail(c, 101, errList[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
regStatus := model.StatusCode(global.Config.App.RegisterStatus)
|
u := service.AllService.UserService.Register(f.Username, f.Email, f.Password)
|
||||||
// the registration status may not be configured; enabled by default
|
|
||||||
if regStatus != model.COMMON_STATUS_DISABLED && regStatus != model.COMMON_STATUS_ENABLE {
|
|
||||||
regStatus = model.COMMON_STATUS_ENABLE
|
|
||||||
}
|
|
||||||
|
|
||||||
u := service.AllService.UserService.Register(f.Username, f.Email, f.Password, regStatus)
|
|
||||||
if u == nil || u.Id == 0 {
|
if u == nil || u.Id == 0 {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed"))
|
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if regStatus == model.COMMON_STATUS_DISABLED {
|
// 注册成功后自动登录
|
||||||
// requires administrator approval
|
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "RegisterSuccessWaitAdminConfirm"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// automatically log in after successful registration
|
|
||||||
ut := service.AllService.UserService.Login(u, &model.LoginLog{
|
ut := service.AllService.UserService.Login(u, &model.LoginLog{
|
||||||
UserId: u.Id,
|
UserId: u.Id,
|
||||||
Client: model.LoginLogClientWebAdmin,
|
Client: model.LoginLogClientWebAdmin,
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/admin"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserToken struct {
|
type UserToken struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List list
|
// List 列表
|
||||||
// @Tags login credential
|
// @Tags 登录凭证
|
||||||
// @Summary login credential list
|
// @Summary 登录凭证列表
|
||||||
// @Description login credential list
|
// @Description 登录凭证列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param page_size query int false "page size"
|
// @Param page_size query int false "页大小"
|
||||||
// @Param user_id query int false "userID"
|
// @Param user_id query int false "用户ID"
|
||||||
// @Success 200 {object} response.Response{data=model.UserTokenList}
|
// @Success 200 {object} response.Response{data=model.UserTokenList}
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user_token/list [get]
|
// @Router /admin/user_token/list [get]
|
||||||
@@ -41,13 +41,13 @@ func (ct *UserToken) List(c *gin.Context) {
|
|||||||
response.Success(c, res)
|
response.Success(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete
|
// Delete 删除
|
||||||
// @Tags login credential
|
// @Tags 登录凭证
|
||||||
// @Summary delete login credential
|
// @Summary 登录凭证删除
|
||||||
// @Description delete login credential
|
// @Description 登录凭证删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body model.UserToken true "login credential info"
|
// @Param body body model.UserToken true "登录凭证信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user_token/delete [post]
|
// @Router /admin/user_token/delete [post]
|
||||||
@@ -82,13 +82,13 @@ func (ct *UserToken) Delete(c *gin.Context) {
|
|||||||
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchDelete batch delete
|
// BatchDelete 批量删除
|
||||||
// @Tags login credential
|
// @Tags 登录凭证
|
||||||
// @Summary batch delete login credentials
|
// @Summary 登录凭证批量删除
|
||||||
// @Description batch delete login credentials
|
// @Description 登录凭证批量删除
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body admin.UserTokenBatchDeleteForm true "login credential info"
|
// @Param body body admin.UserTokenBatchDeleteForm true "登录凭证信息"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /admin/user_token/batchDelete [post]
|
// @Router /admin/user_token/batchDelete [post]
|
||||||
|
|||||||
+65
-65
@@ -1,16 +1,16 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
requstform "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/http/response/api"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
|
"Gwen/utils"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
requstform "github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/utils"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -20,9 +20,9 @@ type Ab struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ab
|
// Ab
|
||||||
// @Tags address
|
// @Tags 地址
|
||||||
// @Summary address list
|
// @Summary 地址列表
|
||||||
// @Description address list
|
// @Description 地址列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -36,7 +36,7 @@ func (a *Ab) Ab(c *gin.Context) {
|
|||||||
tags := service.AllService.TagService.ListByUserIdAndCollectionId(user.Id, 0)
|
tags := service.AllService.TagService.ListByUserIdAndCollectionId(user.Id, 0)
|
||||||
|
|
||||||
tagColors := map[string]uint{}
|
tagColors := map[string]uint{}
|
||||||
// convert the name in tags into a comma-separated string
|
//将tags中的name转成一个以逗号分割的字符串
|
||||||
var tagNames []string
|
var tagNames []string
|
||||||
for _, tag := range tags.Tags {
|
for _, tag := range tags.Tags {
|
||||||
tagNames = append(tagNames, tag.Name)
|
tagNames = append(tagNames, tag.Name)
|
||||||
@@ -56,12 +56,12 @@ func (a *Ab) Ab(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpAb
|
// UpAb
|
||||||
// @Tags address
|
// @Tags 地址
|
||||||
// @Summary address update
|
// @Summary 地址更新
|
||||||
// @Description address update
|
// @Description 地址更新
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body requstform.AddressBookForm true "address form"
|
// @Param body body requstform.AddressBookForm true "地址表单"
|
||||||
// @Success 200 {string} string "null"
|
// @Success 200 {string} string "null"
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /ab [post]
|
// @Router /ab [post]
|
||||||
@@ -99,9 +99,9 @@ func (a *Ab) UpAb(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PTags
|
// PTags
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary tag
|
// @Summary 标签
|
||||||
// @Description tag
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -128,9 +128,9 @@ func (a *Ab) PTags(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TagAdd
|
// TagAdd
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary add tag
|
// @Summary 标签添加
|
||||||
// @Description tag
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -177,9 +177,9 @@ func (a *Ab) TagAdd(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TagRename
|
// TagRename
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary rename tag
|
// @Summary 标签重命名
|
||||||
// @Description tag
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -229,9 +229,9 @@ func (a *Ab) TagRename(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TagUpdate
|
// TagUpdate
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary change tag color
|
// @Summary 标签修改颜色
|
||||||
// @Description tag
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -275,9 +275,9 @@ func (a *Ab) TagUpdate(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TagDel
|
// TagDel
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary delete tag
|
// @Summary 标签删除
|
||||||
// @Description tag
|
// @Description 标签
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -324,9 +324,9 @@ func (a *Ab) TagDel(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Personal
|
// Personal
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary personal address
|
// @Summary 个人地址
|
||||||
// @Description personal address
|
// @Description 个人地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param string body string false "string valid"
|
// @Param string body string false "string valid"
|
||||||
@@ -345,7 +345,7 @@ func (a *Ab) Personal(c *gin.Context) {
|
|||||||
*/
|
*/
|
||||||
if global.Config.Rustdesk.Personal == 1 {
|
if global.Config.Rustdesk.Personal == 1 {
|
||||||
guid := a.ComposeGuid(user.GroupId, user.Id, 0)
|
guid := a.ComposeGuid(user.GroupId, user.Id, 0)
|
||||||
//if it returns guid, subsequent requests will change
|
//如果返回了guid,后面的请求会有变化
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"guid": guid,
|
"guid": guid,
|
||||||
"name": user.Username,
|
"name": user.Username,
|
||||||
@@ -358,9 +358,9 @@ func (a *Ab) Personal(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary settings
|
// @Summary 设置
|
||||||
// @Description settings
|
// @Description 设置
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param string body string false "string valid"
|
// @Param string body string false "string valid"
|
||||||
@@ -370,18 +370,18 @@ func (a *Ab) Personal(c *gin.Context) {
|
|||||||
// @Security BearerAuth
|
// @Security BearerAuth
|
||||||
func (a *Ab) Settings(c *gin.Context) {
|
func (a *Ab) Settings(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"max_peer_one_ab": 0, //max peer count, 0 means no limit
|
"max_peer_one_ab": 0, //最大peer数,0表示不限制
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SharedProfiles
|
// SharedProfiles
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary shared address book
|
// @Summary 共享地址簿
|
||||||
// @Description shared
|
// @Description 共享
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param current query int false "page number"
|
// @Param current query int false "页码"
|
||||||
// @Param pageSize query int false "items per page"
|
// @Param pageSize query int false "每页数量"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /ab/shared/profiles [post]
|
// @Router /ab/shared/profiles [post]
|
||||||
@@ -401,14 +401,14 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
allAbIds := make(map[uint]int) //use map to deduplicate and keep the maximum Rule
|
allAbIds := make(map[uint]int) //用map去重,并保留最大Rule
|
||||||
allUserIds := make(map[uint]*model.User)
|
allUserIds := make(map[uint]*model.User)
|
||||||
rules := service.AllService.AddressBookService.CollectionReadRules(user)
|
rules := service.AllService.AddressBookService.CollectionReadRules(user)
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
//first check whether it exists
|
//先判断是否存在
|
||||||
r, ok := allAbIds[rule.CollectionId]
|
r, ok := allAbIds[rule.CollectionId]
|
||||||
if ok {
|
if ok {
|
||||||
//then check the permission level
|
//再判断权限大小
|
||||||
if r < rule.Rule {
|
if r < rule.Rule {
|
||||||
allAbIds[rule.CollectionId] = rule.Rule
|
allAbIds[rule.CollectionId] = rule.Rule
|
||||||
}
|
}
|
||||||
@@ -448,7 +448,7 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
|
|||||||
|
|
||||||
// ParseGuid
|
// ParseGuid
|
||||||
func (a *Ab) ParseGuid(guid string) (gid, uid, cid uint) {
|
func (a *Ab) ParseGuid(guid string) (gid, uid, cid uint) {
|
||||||
// split guid by -
|
//用-切割 guid
|
||||||
guids := strings.Split(guid, "-")
|
guids := strings.Split(guid, "-")
|
||||||
if len(guids) < 2 {
|
if len(guids) < 2 {
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
@@ -521,13 +521,13 @@ func (a *Ab) CheckGuid(cu *model.User, guid string) (gid, uid, cid uint, err err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Peers
|
// Peers
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary address list
|
// @Summary 地址列表
|
||||||
// @Description address
|
// @Description 地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param current query int false "page number"
|
// @Param current query int false "页码"
|
||||||
// @Param pageSize query int false "items per page"
|
// @Param pageSize query int false "每页数量"
|
||||||
// @Param ab query string false "guid"
|
// @Param ab query string false "guid"
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
@@ -557,9 +557,9 @@ func (a *Ab) Peers(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerAdd
|
// PeerAdd
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary add address
|
// @Summary 添加地址
|
||||||
// @Description add address
|
// @Description 添加地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -568,7 +568,7 @@ func (a *Ab) Peers(c *gin.Context) {
|
|||||||
// @Router /ab/peer/add/{guid} [post]
|
// @Router /ab/peer/add/{guid} [post]
|
||||||
// @Security BearerAuth
|
// @Security BearerAuth
|
||||||
func (a *Ab) PeerAdd(c *gin.Context) {
|
func (a *Ab) PeerAdd(c *gin.Context) {
|
||||||
// forceAlwaysRelay is always the string "false"
|
// forceAlwaysRelay永远是字符串"false"
|
||||||
//f := &gin.H{}
|
//f := &gin.H{}
|
||||||
f := &requstform.PersonalAddressBookForm{}
|
f := &requstform.PersonalAddressBookForm{}
|
||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
@@ -613,9 +613,9 @@ func (a *Ab) PeerAdd(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerDel
|
// PeerDel
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary delete address
|
// @Summary 删除地址
|
||||||
// @Description delete address
|
// @Description 删除地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -661,9 +661,9 @@ func (a *Ab) PeerDel(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerUpdate
|
// PeerUpdate
|
||||||
// @Tags address[Personal]
|
// @Tags 地址[Personal]
|
||||||
// @Summary update address
|
// @Summary 更新地址
|
||||||
// @Description update address
|
// @Description 更新地址
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param guid path string true "guid"
|
// @Param guid path string true "guid"
|
||||||
@@ -693,7 +693,7 @@ func (a *Ab) PeerUpdate(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//fmt.Println(f)
|
//fmt.Println(f)
|
||||||
// determine whether f["Id"] exists
|
//判断f["Id"]是否存在
|
||||||
fid, ok := f["id"]
|
fid, ok := f["id"]
|
||||||
if !ok {
|
if !ok {
|
||||||
response.Error(c, response.TranslateMsg(c, "ParamsError"))
|
response.Error(c, response.TranslateMsg(c, "ParamsError"))
|
||||||
@@ -706,9 +706,9 @@ func (a *Ab) PeerUpdate(c *gin.Context) {
|
|||||||
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
|
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//allowed fields
|
//允许的字段
|
||||||
allowUp := []string{"password", "hash", "tags", "alias"}
|
allowUp := []string{"password", "hash", "tags", "alias"}
|
||||||
// if a field in f is not in allowUp, delete it
|
//f中的字段如果不在allowUp中,就删除
|
||||||
for k := range f {
|
for k := range f {
|
||||||
if !utils.InArray(k, allowUp) {
|
if !utils.InArray(k, allowUp) {
|
||||||
delete(f, k)
|
delete(f, k)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
request "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
request "github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,12 +14,12 @@ type Audit struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AuditConn
|
// AuditConn
|
||||||
// @Tags audit
|
// @Tags 审计
|
||||||
// @Summary audit connection
|
// @Summary 审计连接
|
||||||
// @Description audit connection
|
// @Description 审计连接
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body request.AuditConnForm true "audit connection"
|
// @Param body body request.AuditConnForm true "审计连接"
|
||||||
// @Success 200 {string} string ""
|
// @Success 200 {string} string ""
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /audit/conn [post]
|
// @Router /audit/conn [post]
|
||||||
@@ -59,12 +59,12 @@ func (a *Audit) AuditConn(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AuditFile
|
// AuditFile
|
||||||
// @Tags audit
|
// @Tags 审计
|
||||||
// @Summary audit file
|
// @Summary 审计文件
|
||||||
// @Description audit file
|
// @Description 审计文件
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body request.AuditFileForm true "audit file"
|
// @Param body body request.AuditFileForm true "审计文件"
|
||||||
// @Success 200 {string} string ""
|
// @Success 200 {string} string ""
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /audit/file [post]
|
// @Router /audit/file [post]
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
apiReq "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
apiResp "Gwen/http/response/api"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
apiReq "github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
apiResp "github.com/lejianwen/rustdesk-api/v2/http/response/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Group struct {
|
type Group struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Users user list
|
// Users 用户列表
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary user list
|
// @Summary 用户列表
|
||||||
// @Description user list
|
// @Description 用户列表
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param pageSize query int false "items per page"
|
// @Param pageSize query int false "每页数量"
|
||||||
// @Param status query int false "status"
|
// @Param status query int false "状态"
|
||||||
// @Param accessible query string false "accessible"
|
// @Param accessible query string false "accessible"
|
||||||
// @Success 200 {object} response.DataResponse{data=[]apiResp.UserPayload}
|
// @Success 200 {object} response.DataResponse{data=[]apiResp.UserPayload}
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
@@ -38,14 +38,14 @@ func (g *Group) Users(c *gin.Context) {
|
|||||||
gr := service.AllService.GroupService.InfoById(u.GroupId)
|
gr := service.AllService.GroupService.InfoById(u.GroupId)
|
||||||
userList := &model.UserList{}
|
userList := &model.UserList{}
|
||||||
if !*u.IsAdmin && gr.Type != model.GroupTypeShare {
|
if !*u.IsAdmin && gr.Type != model.GroupTypeShare {
|
||||||
//can only retrieve one's own
|
//仅能获取到自己
|
||||||
userList.Users = append(userList.Users, u)
|
userList.Users = append(userList.Users, u)
|
||||||
userList.Total = 1
|
userList.Total = 1
|
||||||
} else {
|
} else {
|
||||||
userList = service.AllService.UserService.ListByGroupId(u.GroupId, q.Page, q.PageSize)
|
userList = service.AllService.UserService.ListByGroupId(u.GroupId, q.Page, q.PageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]*apiResp.UserPayload, 0, len(userList.Users))
|
var data []*apiResp.UserPayload
|
||||||
for _, user := range userList.Users {
|
for _, user := range userList.Users {
|
||||||
up := &apiResp.UserPayload{}
|
up := &apiResp.UserPayload{}
|
||||||
up.FromUser(user)
|
up.FromUser(user)
|
||||||
@@ -58,14 +58,14 @@ func (g *Group) Users(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Peers
|
// Peers
|
||||||
// @Tags group
|
// @Tags 群组
|
||||||
// @Summary machine
|
// @Summary 机器
|
||||||
// @Description machine
|
// @Description 机器
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "page number"
|
// @Param page query int false "页码"
|
||||||
// @Param pageSize query int false "items per page"
|
// @Param pageSize query int false "每页数量"
|
||||||
// @Param status query int false "status"
|
// @Param status query int false "状态"
|
||||||
// @Param accessible query string false "accessible"
|
// @Param accessible query string false "accessible"
|
||||||
// @Success 200 {object} response.DataResponse
|
// @Success 200 {object} response.DataResponse
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
@@ -82,36 +82,27 @@ func (g *Group) Peers(c *gin.Context) {
|
|||||||
gr := service.AllService.GroupService.InfoById(u.GroupId)
|
gr := service.AllService.GroupService.InfoById(u.GroupId)
|
||||||
users := make([]*model.User, 0, 1)
|
users := make([]*model.User, 0, 1)
|
||||||
if !*u.IsAdmin && gr.Type != model.GroupTypeShare {
|
if !*u.IsAdmin && gr.Type != model.GroupTypeShare {
|
||||||
//can only retrieve one's own
|
//仅能获取到自己
|
||||||
users = append(users, u)
|
users = append(users, u)
|
||||||
} else {
|
} else {
|
||||||
users = service.AllService.UserService.ListIdAndNameByGroupId(u.GroupId)
|
users = service.AllService.UserService.ListIdAndNameByGroupId(u.GroupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
namesById := make(map[uint]string, len(users))
|
namesById := make(map[uint]string)
|
||||||
userIds := make([]uint, 0, len(users))
|
userIds := make([]uint, 0)
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
namesById[user.Id] = user.Username
|
namesById[user.Id] = user.Username
|
||||||
userIds = append(userIds, user.Id)
|
userIds = append(userIds, user.Id)
|
||||||
}
|
}
|
||||||
dGroupNameById := make(map[uint]string)
|
|
||||||
allGroup := service.AllService.GroupService.DeviceGroupList(1, 999, nil)
|
|
||||||
for _, group := range allGroup.DeviceGroups {
|
|
||||||
dGroupNameById[group.Id] = group.Name
|
|
||||||
}
|
|
||||||
peerList := service.AllService.PeerService.ListByUserIds(userIds, q.Page, q.PageSize)
|
peerList := service.AllService.PeerService.ListByUserIds(userIds, q.Page, q.PageSize)
|
||||||
data := make([]*apiResp.GroupPeerPayload, 0, len(peerList.Peers))
|
var data []*apiResp.GroupPeerPayload
|
||||||
for _, peer := range peerList.Peers {
|
for _, peer := range peerList.Peers {
|
||||||
uname, ok := namesById[peer.UserId]
|
uname, ok := namesById[peer.UserId]
|
||||||
if !ok {
|
if !ok {
|
||||||
uname = ""
|
uname = ""
|
||||||
}
|
}
|
||||||
dGroupName, ok2 := dGroupNameById[peer.GroupId]
|
|
||||||
if !ok2 {
|
|
||||||
dGroupName = ""
|
|
||||||
}
|
|
||||||
pp := &apiResp.GroupPeerPayload{}
|
pp := &apiResp.GroupPeerPayload{}
|
||||||
pp.FromPeer(peer, uname, dGroupName)
|
pp.FromPeer(peer, uname)
|
||||||
data = append(data, pp)
|
data = append(data, pp)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -120,31 +111,3 @@ func (g *Group) Peers(c *gin.Context) {
|
|||||||
Data: data,
|
Data: data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device
|
|
||||||
// @Tags group
|
|
||||||
// @Summary device
|
|
||||||
// @Description machine
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param page query int false "page number"
|
|
||||||
// @Param pageSize query int false "items per page"
|
|
||||||
// @Param status query int false "status"
|
|
||||||
// @Param accessible query string false "accessible"
|
|
||||||
// @Success 200 {object} response.DataResponse
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /device-group/accessible [get]
|
|
||||||
// @Security BearerAuth
|
|
||||||
func (g *Group) Device(c *gin.Context) {
|
|
||||||
u := service.AllService.UserService.CurUser(c)
|
|
||||||
if !service.AllService.UserService.IsAdmin(u) {
|
|
||||||
response.Error(c, "Permission denied")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
allGroup := service.AllService.GroupService.DeviceGroupList(1, 999, nil)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, response.DataResponse{
|
|
||||||
Total: 0,
|
|
||||||
Data: allGroup.DeviceGroups,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
requstform "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
requstform "github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
type Index struct {
|
type Index struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index home
|
// Index 首页
|
||||||
// @Tags home
|
// @Tags 首页
|
||||||
// @Summary home
|
// @Summary 首页
|
||||||
// @Description home
|
// @Description 首页
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -29,10 +29,10 @@ func (i *Index) Index(c *gin.Context) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Heartbeat heartbeat
|
// Heartbeat 心跳
|
||||||
// @Tags home
|
// @Tags 首页
|
||||||
// @Summary heartbeat
|
// @Summary 心跳
|
||||||
// @Description heartbeat
|
// @Description 心跳
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} nil
|
// @Success 200 {object} nil
|
||||||
@@ -49,33 +49,15 @@ func (i *Index) Heartbeat(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, gin.H{})
|
c.JSON(http.StatusOK, gin.H{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
peer := service.AllService.PeerService.FindById(info.Id)
|
peer := service.AllService.PeerService.FindByUuid(info.Uuid)
|
||||||
if peer == nil || peer.RowId == 0 {
|
if peer == nil || peer.RowId == 0 {
|
||||||
c.JSON(http.StatusOK, gin.H{})
|
c.JSON(http.StatusOK, gin.H{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// do not update if within 40s
|
//如果在40s以内则不更新
|
||||||
if time.Now().Unix()-peer.LastOnlineTime >= 30 {
|
if time.Now().Unix()-peer.LastOnlineTime > 40 {
|
||||||
upp := &model.Peer{RowId: peer.RowId, LastOnlineTime: time.Now().Unix(), LastOnlineIp: c.ClientIP()}
|
upp := &model.Peer{RowId: peer.RowId, LastOnlineTime: time.Now().Unix(), LastOnlineIp: c.ClientIP()}
|
||||||
service.AllService.PeerService.Update(upp)
|
service.AllService.PeerService.Update(upp)
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{})
|
c.JSON(http.StatusOK, gin.H{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version version
|
|
||||||
// @Tags home
|
|
||||||
// @Summary version
|
|
||||||
// @Description version
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200 {object} response.Response
|
|
||||||
// @Failure 500 {object} response.Response
|
|
||||||
// @Router /version [get]
|
|
||||||
func (i *Index) Version(c *gin.Context) {
|
|
||||||
// read the resources/version file
|
|
||||||
v := service.AllService.AppService.GetAppVersion()
|
|
||||||
response.Success(
|
|
||||||
c,
|
|
||||||
v,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,46 +1,36 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
apiResp "Gwen/http/response/api"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
apiResp "github.com/lejianwen/rustdesk-api/v2/http/response/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Login struct {
|
type Login struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login login
|
// Login 登录
|
||||||
// @Tags login
|
// @Tags 登录
|
||||||
// @Summary login
|
// @Summary 登录
|
||||||
// @Description login
|
// @Description 登录
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body api.LoginForm true "login form"
|
// @Param body body api.LoginForm true "登录表单"
|
||||||
// @Success 200 {object} apiResp.LoginRes
|
// @Success 200 {object} apiResp.LoginRes
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /login [post]
|
// @Router /login [post]
|
||||||
func (l *Login) Login(c *gin.Context) {
|
func (l *Login) Login(c *gin.Context) {
|
||||||
if global.Config.App.DisablePwdLogin {
|
|
||||||
response.Error(c, response.TranslateMsg(c, "PwdLoginDisabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// check login limit
|
|
||||||
loginLimiter := global.LoginLimiter
|
|
||||||
clientIp := c.ClientIP()
|
|
||||||
|
|
||||||
f := &api.LoginForm{}
|
f := &api.LoginForm{}
|
||||||
err := c.ShouldBindJSON(f)
|
err := c.ShouldBindJSON(f)
|
||||||
//fmt.Println(f)
|
//fmt.Println(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loginLimiter.RecordFailedAttempt(clientIp)
|
|
||||||
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(), c.ClientIP()))
|
||||||
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
@@ -48,7 +38,6 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
|
|
||||||
errList := global.Validator.ValidStruct(c, f)
|
errList := global.Validator.ValidStruct(c, f)
|
||||||
if len(errList) > 0 {
|
if len(errList) > 0 {
|
||||||
loginLimiter.RecordFailedAttempt(clientIp)
|
|
||||||
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(), c.ClientIP()))
|
||||||
response.Error(c, errList[0])
|
response.Error(c, errList[0])
|
||||||
return
|
return
|
||||||
@@ -57,18 +46,12 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
|
||||||
|
|
||||||
if u.Id == 0 {
|
if u.Id == 0 {
|
||||||
loginLimiter.RecordFailedAttempt(clientIp)
|
|
||||||
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(), c.ClientIP()))
|
||||||
response.Error(c, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
response.Error(c, response.TranslateMsg(c, "UsernameOrPasswordError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !service.AllService.UserService.CheckUserEnable(u) {
|
//根据refer判断是webclient还是app
|
||||||
response.Error(c, response.TranslateMsg(c, "UserDisabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine whether it is webclient or app based on refer
|
|
||||||
ref := c.GetHeader("referer")
|
ref := c.GetHeader("referer")
|
||||||
if ref != "" {
|
if ref != "" {
|
||||||
f.DeviceInfo.Type = model.LoginLogClientWeb
|
f.DeviceInfo.Type = model.LoginLogClientWeb
|
||||||
@@ -92,9 +75,9 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoginOptions
|
// LoginOptions
|
||||||
// @Tags login
|
// @Tags 登录
|
||||||
// @Summary login options
|
// @Summary 登录选项
|
||||||
// @Description login options
|
// @Description 登录选项
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} []string
|
// @Success 200 {object} []string
|
||||||
@@ -102,9 +85,7 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
// @Router /login-options [get]
|
// @Router /login-options [get]
|
||||||
func (l *Login) LoginOptions(c *gin.Context) {
|
func (l *Login) LoginOptions(c *gin.Context) {
|
||||||
ops := service.AllService.OauthService.GetOauthProviders()
|
ops := service.AllService.OauthService.GetOauthProviders()
|
||||||
if global.Config.App.WebSso {
|
|
||||||
ops = append(ops, model.OauthTypeWebauth)
|
ops = append(ops, model.OauthTypeWebauth)
|
||||||
}
|
|
||||||
var oidcItems []map[string]string
|
var oidcItems []map[string]string
|
||||||
for _, v := range ops {
|
for _, v := range ops {
|
||||||
oidcItems = append(oidcItems, map[string]string{"name": v})
|
oidcItems = append(oidcItems, map[string]string{"name": v})
|
||||||
@@ -123,9 +104,9 @@ func (l *Login) LoginOptions(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
// @Tags login
|
// @Tags 登录
|
||||||
// @Summary logout
|
// @Summary 登出
|
||||||
// @Description logout
|
// @Description 登出
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {string} string
|
// @Success 200 {string} string
|
||||||
|
|||||||
+47
-112
@@ -1,17 +1,14 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"Gwen/global"
|
||||||
|
"Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
apiResp "Gwen/http/response/api"
|
||||||
|
"Gwen/model"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
"net/http"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
apiResp "github.com/lejianwen/rustdesk-api/v2/http/response/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/utils"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Oauth struct {
|
type Oauth struct {
|
||||||
@@ -35,14 +32,15 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oauthService := service.AllService.OauthService
|
oauthService := service.AllService.OauthService
|
||||||
|
var code string
|
||||||
err, state, verifier, nonce, url := oauthService.BeginAuth(f.Op)
|
var url string
|
||||||
|
err, code, url = oauthService.BeginAuth(f.Op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, err.Error()))
|
response.Error(c, response.TranslateMsg(c, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
service.AllService.OauthService.SetOauthCache(state, &service.OauthCacheItem{
|
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
|
||||||
Action: service.OauthActionTypeLogin,
|
Action: service.OauthActionTypeLogin,
|
||||||
Id: f.Id,
|
Id: f.Id,
|
||||||
Op: f.Op,
|
Op: f.Op,
|
||||||
@@ -50,12 +48,10 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
|
|||||||
DeviceName: f.DeviceInfo.Name,
|
DeviceName: f.DeviceInfo.Name,
|
||||||
DeviceOs: f.DeviceInfo.Os,
|
DeviceOs: f.DeviceInfo.Os,
|
||||||
DeviceType: f.DeviceInfo.Type,
|
DeviceType: f.DeviceInfo.Type,
|
||||||
Verifier: verifier,
|
|
||||||
Nonce: nonce,
|
|
||||||
}, 5*60)
|
}, 5*60)
|
||||||
//fmt.Println("code url", code, url)
|
//fmt.Println("code url", code, url)
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"code": state,
|
"code": code,
|
||||||
"url": url,
|
"url": url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -65,37 +61,36 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
|
|||||||
var ut *model.UserToken
|
var ut *model.UserToken
|
||||||
q := &api.OidcAuthQuery{}
|
q := &api.OidcAuthQuery{}
|
||||||
|
|
||||||
// parse query parameters and handle errors
|
// 解析查询参数并处理错误
|
||||||
if err := c.ShouldBindQuery(q); err != nil {
|
if err := c.ShouldBindQuery(q); err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, "ParamsError")+": "+err.Error())
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+": "+err.Error())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get OAuth cache
|
// 获取 OAuth 缓存
|
||||||
v := service.AllService.OauthService.GetOauthCache(q.Code)
|
v := service.AllService.OauthService.GetOauthCache(q.Code)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
response.Error(c, response.TranslateMsg(c, "OauthExpired"))
|
response.Error(c, response.TranslateMsg(c, "OauthExpired"))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if UserId is 0, authorization is still in progress
|
// 如果 UserId 为 0,说明还在授权中
|
||||||
if v.UserId == 0 {
|
if v.UserId == 0 {
|
||||||
//fix: 1.4.2 webclient oidc
|
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind"})
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind", "error": "No authed oidc is found"})
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get user info
|
// 获取用户信息
|
||||||
u = service.AllService.UserService.InfoById(v.UserId)
|
u = service.AllService.UserService.InfoById(v.UserId)
|
||||||
if u == nil {
|
if u == nil {
|
||||||
response.Error(c, response.TranslateMsg(c, "UserNotFound"))
|
response.Error(c, response.TranslateMsg(c, "UserNotFound"))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete OAuth cache
|
// 删除 OAuth 缓存
|
||||||
service.AllService.OauthService.DeleteOauthCache(q.Code)
|
service.AllService.OauthService.DeleteOauthCache(q.Code)
|
||||||
|
|
||||||
// create a login log and generate a user token
|
// 创建登录日志并生成用户令牌
|
||||||
ut = service.AllService.UserService.Login(u, &model.LoginLog{
|
ut = service.AllService.UserService.Login(u, &model.LoginLog{
|
||||||
UserId: u.Id,
|
UserId: u.Id,
|
||||||
Client: v.DeviceType,
|
Client: v.DeviceType,
|
||||||
@@ -111,7 +106,7 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// return user token
|
// 返回用户令牌
|
||||||
return u, ut
|
return u, ut
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +131,7 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// OauthCallback callback
|
// OauthCallback 回调
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary OauthCallback
|
// @Summary OauthCallback
|
||||||
// @Description OauthCallback
|
// @Description OauthCallback
|
||||||
@@ -144,39 +139,29 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} apiResp.LoginRes
|
// @Success 200 {object} apiResp.LoginRes
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /oidc/callback [get]
|
// @Router /oauth/callback [get]
|
||||||
func (o *Oauth) OauthCallback(c *gin.Context) {
|
func (o *Oauth) OauthCallback(c *gin.Context) {
|
||||||
state := c.Query("state")
|
state := c.Query("state")
|
||||||
if state == "" {
|
if state == "" {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateParamMsg(c, "ParamIsEmpty", "state"))
|
||||||
"message": "ParamIsEmpty",
|
|
||||||
"sub_message": "state",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cacheKey := state
|
cacheKey := state
|
||||||
oauthService := service.AllService.OauthService
|
oauthService := service.AllService.OauthService
|
||||||
//get from cache
|
//从缓存中获取
|
||||||
oauthCache := oauthService.GetOauthCache(cacheKey)
|
oauthCache := oauthService.GetOauthCache(cacheKey)
|
||||||
if oauthCache == nil {
|
if oauthCache == nil {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthExpired"))
|
||||||
"message": "OauthExpired",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nonce := oauthCache.Nonce
|
|
||||||
op := oauthCache.Op
|
op := oauthCache.Op
|
||||||
action := oauthCache.Action
|
action := oauthCache.Action
|
||||||
verifier := oauthCache.Verifier
|
|
||||||
var user *model.User
|
var user *model.User
|
||||||
// get user info
|
// 获取用户信息
|
||||||
code := c.Query("code")
|
code := c.Query("code")
|
||||||
err, oauthUser := oauthService.Callback(code, verifier, op, nonce)
|
err, oauthUser := oauthService.Callback(code, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||||||
"message": "OauthFailed",
|
|
||||||
"sub_message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userId := oauthCache.UserId
|
userId := oauthCache.UserId
|
||||||
@@ -184,65 +169,54 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
if action == service.OauthActionTypeBind {
|
if action == service.OauthActionTypeBind {
|
||||||
|
|
||||||
//fmt.Println("bind", ty, userData)
|
//fmt.Println("bind", ty, userData)
|
||||||
// check whether this openid has already been bound
|
// 检查此openid是否已经绑定过
|
||||||
utr := oauthService.UserThirdInfo(op, openid)
|
utr := oauthService.UserThirdInfo(op, openid)
|
||||||
if utr.UserId > 0 {
|
if utr.UserId > 0 {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
|
||||||
"message": "OauthHasBindOtherUser",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//bind
|
//绑定
|
||||||
user = service.AllService.UserService.InfoById(userId)
|
user = service.AllService.UserService.InfoById(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
"message": "ItemNotFound",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//bind
|
//绑定
|
||||||
err := oauthService.BindOauthUser(userId, oauthUser, op)
|
err := oauthService.BindOauthUser(userId, oauthUser, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
|
||||||
"message": "BindFail",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, "oauth_success.html", gin.H{
|
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
|
||||||
"message": "BindSuccess",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
|
|
||||||
} else if action == service.OauthActionTypeLogin {
|
} else if action == service.OauthActionTypeLogin {
|
||||||
//login
|
//登录
|
||||||
if userId != 0 {
|
if userId != 0 {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
|
||||||
"message": "OauthHasBeenSuccess",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user = service.AllService.UserService.InfoByOauthId(op, openid)
|
user = service.AllService.UserService.InfoByOauthId(op, openid)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
oauthConfig := oauthService.InfoByOp(op)
|
oauthConfig := oauthService.InfoByOp(op)
|
||||||
if !*oauthConfig.AutoRegister {
|
if !*oauthConfig.AutoRegister {
|
||||||
//c.String(http.StatusInternalServerError, "not yet bound to a user, please bind first")
|
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
||||||
oauthCache.UpdateFromOauthUser(oauthUser)
|
oauthCache.UpdateFromOauthUser(oauthUser)
|
||||||
c.Redirect(http.StatusFound, "/_admin/#/oauth/bind/"+cacheKey)
|
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
||||||
|
c.Redirect(http.StatusFound, url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//auto register
|
//自动注册
|
||||||
err, user = service.AllService.UserService.RegisterByOauth(oauthUser, op)
|
err, user = service.AllService.UserService.RegisterByOauth(oauthUser, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, err.Error()))
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oauthCache.UserId = user.Id
|
oauthCache.UserId = user.Id
|
||||||
oauthService.SetOauthCache(cacheKey, oauthCache, 0)
|
oauthService.SetOauthCache(cacheKey, oauthCache, 0)
|
||||||
// if it is webadmin, after successful login redirect to webadmin
|
// 如果是webadmin,登录成功后跳转到webadmin
|
||||||
if oauthCache.DeviceType == model.LoginLogClientWebAdmin {
|
if oauthCache.DeviceType == model.LoginLogClientWebAdmin {
|
||||||
/*service.AllService.UserService.Login(u, &model.LoginLog{
|
/*service.AllService.UserService.Login(u, &model.LoginLog{
|
||||||
UserId: u.Id,
|
UserId: u.Id,
|
||||||
@@ -252,54 +226,15 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
Type: model.LoginLogTypeOauth,
|
Type: model.LoginLogTypeOauth,
|
||||||
Platform: oauthService.DeviceOs,
|
Platform: oauthService.DeviceOs,
|
||||||
})*/
|
})*/
|
||||||
c.Redirect(http.StatusFound, "/_admin/#/")
|
url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
|
||||||
|
c.Redirect(http.StatusFound, url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, "oauth_success.html", gin.H{
|
c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
||||||
"message": "OauthSuccess",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
c.HTML(http.StatusOK, "oauth_fail.html", gin.H{
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
|
||||||
"message": "ParamsError",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageParams struct {
|
|
||||||
Lang string `json:"lang" form:"lang"`
|
|
||||||
Title string `json:"title" form:"title"`
|
|
||||||
Msg string `json:"msg" form:"msg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Oauth) Message(c *gin.Context) {
|
|
||||||
mp := &MessageParams{}
|
|
||||||
if err := c.ShouldBindQuery(mp); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
localizer := global.Localizer(mp.Lang)
|
|
||||||
res := ""
|
|
||||||
if mp.Title != "" {
|
|
||||||
title, err := localizer.LocalizeMessage(&i18n.Message{
|
|
||||||
ID: mp.Title,
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
res = utils.StringConcat(";title='", title, "';")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if mp.Msg != "" {
|
|
||||||
msg, err := localizer.LocalizeMessage(&i18n.Message{
|
|
||||||
ID: mp.Msg,
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
res = utils.StringConcat(res, "msg = '", msg, "';")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//returnjscontent
|
|
||||||
c.Header("Content-Type", "application/javascript")
|
|
||||||
c.String(http.StatusOK, res)
|
|
||||||
}
|
|
||||||
|
|||||||
+12
-30
@@ -1,12 +1,11 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
requstform "Gwen/http/request/api"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
requstform "github.com/lejianwen/rustdesk-api/v2/http/request/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,12 +13,12 @@ type Peer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SysInfo
|
// SysInfo
|
||||||
// @Tags System
|
// @Tags 地址
|
||||||
// @Summary submit system info
|
// @Summary 提交系统信息
|
||||||
// @Description submit system info
|
// @Description 提交系统信息
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body requstform.PeerForm true "system info form"
|
// @Param body body requstform.PeerForm true "系统信息表单"
|
||||||
// @Success 200 {string} string "SYSINFO_UPDATED,ID_NOT_FOUND"
|
// @Success 200 {string} string "SYSINFO_UPDATED,ID_NOT_FOUND"
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /sysinfo [post]
|
// @Router /sysinfo [post]
|
||||||
@@ -34,7 +33,7 @@ func (p *Peer) SysInfo(c *gin.Context) {
|
|||||||
pe := service.AllService.PeerService.FindById(f.Id)
|
pe := service.AllService.PeerService.FindById(f.Id)
|
||||||
if pe.RowId == 0 {
|
if pe.RowId == 0 {
|
||||||
pe = f.ToPeer()
|
pe = f.ToPeer()
|
||||||
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid, pe.Id)
|
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid)
|
||||||
err = service.AllService.PeerService.Create(pe)
|
err = service.AllService.PeerService.Create(pe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
|
||||||
@@ -42,7 +41,7 @@ func (p *Peer) SysInfo(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if pe.UserId == 0 {
|
if pe.UserId == 0 {
|
||||||
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid, pe.Id)
|
pe.UserId = service.AllService.UserService.FindLatestUserIdFromLoginLogByUuid(pe.Uuid)
|
||||||
}
|
}
|
||||||
fpe.RowId = pe.RowId
|
fpe.RowId = pe.RowId
|
||||||
fpe.UserId = pe.UserId
|
fpe.UserId = pe.UserId
|
||||||
@@ -52,25 +51,8 @@ func (p *Peer) SysInfo(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SYSINFO_UPDATED upload successful
|
//SYSINFO_UPDATED 上传成功
|
||||||
//ID_NOT_FOUND will be uploaded on the next heartbeat
|
//ID_NOT_FOUND 下次心跳会上传
|
||||||
//respond with text directly
|
//直接响应文本
|
||||||
c.String(http.StatusOK, "SYSINFO_UPDATED")
|
c.String(http.StatusOK, "SYSINFO_UPDATED")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SysInfoVer
|
|
||||||
// @Tags System
|
|
||||||
// @Summary get system version info
|
|
||||||
// @Description get system version info
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200 {string} string ""
|
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
|
||||||
// @Router /sysinfo_ver [post]
|
|
||||||
func (p *Peer) SysInfoVer(c *gin.Context) {
|
|
||||||
// read the resources/version file
|
|
||||||
v := service.AllService.AppService.GetAppVersion()
|
|
||||||
// add the start time so the client can conveniently upload info
|
|
||||||
v = fmt.Sprintf("%s\n%s", v, service.AllService.AppService.GetStartTime())
|
|
||||||
c.String(http.StatusOK, v)
|
|
||||||
}
|
|
||||||
|
|||||||
+11
-11
@@ -1,19 +1,19 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
apiResp "Gwen/http/response/api"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
apiResp "github.com/lejianwen/rustdesk-api/v2/http/response/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// currentUser current user
|
// currentUser 当前用户
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary user info
|
// @Summary 用户信息
|
||||||
// @Description user info
|
// @Description 用户信息
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} apiResp.UserPayload
|
// @Success 200 {object} apiResp.UserPayload
|
||||||
@@ -26,15 +26,15 @@ type User struct {
|
|||||||
// c.JSON(http.StatusOK, up)
|
// c.JSON(http.StatusOK, up)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// Info user info
|
// Info 用户信息
|
||||||
// @Tags user
|
// @Tags 用户
|
||||||
// @Summary user info
|
// @Summary 用户信息
|
||||||
// @Description user info
|
// @Description 用户信息
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} apiResp.UserPayload
|
// @Success 200 {object} apiResp.UserPayload
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /currentUser [get]
|
// @Router /api [get]
|
||||||
// @Security token
|
// @Security token
|
||||||
func (u *User) Info(c *gin.Context) {
|
func (u *User) Info(c *gin.Context) {
|
||||||
user := service.AllService.UserService.CurUser(c)
|
user := service.AllService.UserService.CurUser(c)
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/http/response/api"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebClient struct {
|
type WebClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig service config
|
// ServerConfig 服务配置
|
||||||
// @Tags WEBCLIENT
|
// @Tags WEBCLIENT
|
||||||
// @Summary service config
|
// @Summary 服务配置
|
||||||
// @Description service config, provides an api-server for the webclient
|
// @Description 服务配置,给webclient提供api-server
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -42,10 +42,10 @@ func (i *WebClient) ServerConfig(c *gin.Context) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SharedPeer shared peer
|
// SharedPeer 分享的peer
|
||||||
// @Tags WEBCLIENT
|
// @Tags WEBCLIENT
|
||||||
// @Summary shared peer
|
// @Summary 分享的peer
|
||||||
// @Description shared peer
|
// @Description 分享的peer
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
@@ -65,7 +65,7 @@ func (i *WebClient) SharedPeer(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sr.Expire != 0 {
|
if sr.Expire != 0 {
|
||||||
//check whether expired,created_at + expire > now
|
//判断是否过期,created_at + expire > now
|
||||||
ca := time.Time(sr.CreatedAt)
|
ca := time.Time(sr.CreatedAt)
|
||||||
if ca.Add(time.Second * time.Duration(sr.Expire)).Before(time.Now()) {
|
if ca.Add(time.Second * time.Duration(sr.Expire)).Before(time.Now()) {
|
||||||
response.Fail(c, 101, "share expired")
|
response.Fail(c, 101, "share expired")
|
||||||
@@ -89,10 +89,10 @@ func (i *WebClient) SharedPeer(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfigV2 service config
|
// ServerConfigV2 服务配置
|
||||||
// @Tags WEBCLIENT_V2
|
// @Tags WEBCLIENT_V2
|
||||||
// @Summary service config
|
// @Summary 服务配置
|
||||||
// @Description service config, provides an api-server for the webclient
|
// @Description 服务配置,给webclient提供api-server
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} response.Response
|
// @Success 200 {object} response.Response
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"Gwen/global"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Index struct {
|
type Index struct {
|
||||||
@@ -15,21 +15,13 @@ func (i *Index) Index(c *gin.Context) {
|
|||||||
|
|
||||||
func (i *Index) ConfigJs(c *gin.Context) {
|
func (i *Index) ConfigJs(c *gin.Context) {
|
||||||
apiServer := global.Config.Rustdesk.ApiServer
|
apiServer := global.Config.Rustdesk.ApiServer
|
||||||
magicQueryonline := global.Config.Rustdesk.WebclientMagicQueryonline
|
magicQueryonline := strconv.Itoa(global.Config.Rustdesk.WebclientMagicQueryonline)
|
||||||
tmp := fmt.Sprintf(`localStorage.setItem('api-server', '%v');
|
tmp := `
|
||||||
const ws2_prefix = 'wc-';
|
localStorage.setItem('api-server', "` + apiServer + `")
|
||||||
localStorage.setItem(ws2_prefix+'api-server', '%v');
|
const ws2_prefix = 'wc-'
|
||||||
|
localStorage.setItem(ws2_prefix+'api-server', "` + apiServer + `")
|
||||||
|
|
||||||
window.webclient_magic_queryonline = %d;
|
window.webclient_magic_queryonline = ` + magicQueryonline + ``
|
||||||
window.ws_host = '%v';
|
|
||||||
`, apiServer, apiServer, magicQueryonline, global.Config.Rustdesk.WsHost)
|
|
||||||
// tmp := `
|
|
||||||
//localStorage.setItem('api-server', "` + apiServer + `")
|
|
||||||
//const ws2_prefix = 'wc-'
|
|
||||||
//localStorage.setItem(ws2_prefix+'api-server', "` + apiServer + `")
|
|
||||||
//
|
|
||||||
//window.webclient_magic_queryonline = ` + magicQueryonline + ``
|
|
||||||
|
|
||||||
c.Header("Content-Type", "application/javascript")
|
|
||||||
c.String(200, tmp)
|
c.String(200, tmp)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -1,10 +1,10 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/middleware"
|
||||||
|
"Gwen/http/router"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/middleware"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/router"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -25,7 +25,7 @@ func ApiInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if global.Config.Gin.Mode == gin.ReleaseMode {
|
if global.Config.Gin.Mode == gin.ReleaseMode {
|
||||||
// redirect gin's Recovery log output to the logger's output
|
//修改gin Recovery日志 输出为logger的输出点
|
||||||
if global.Logger != nil {
|
if global.Logger != nil {
|
||||||
gin.DefaultErrorWriter = global.Logger.WriterLevel(logrus.ErrorLevel)
|
gin.DefaultErrorWriter = global.Logger.WriterLevel(logrus.ErrorLevel)
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ func ApiInit() {
|
|||||||
g.NoRoute(func(c *gin.Context) {
|
g.NoRoute(func(c *gin.Context) {
|
||||||
c.String(http.StatusNotFound, "404 not found")
|
c.String(http.StatusNotFound, "404 not found")
|
||||||
})
|
})
|
||||||
g.Use(middleware.Logger(), middleware.Limiter(), gin.Recovery())
|
g.Use(middleware.Logger(), gin.Recovery())
|
||||||
router.WebInit(g)
|
router.WebInit(g)
|
||||||
router.Init(g)
|
router.Init(g)
|
||||||
router.ApiInit(g)
|
router.ApiInit(g)
|
||||||
|
|||||||
@@ -1,40 +1,32 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BackendUserAuth backend permission verification middleware
|
// AdminAuth 后台权限验证中间件
|
||||||
func BackendUserAuth() gin.HandlerFunc {
|
func AdminAuth() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
|
||||||
//disabled for testing
|
//测试先关闭
|
||||||
token := c.GetHeader("api-token")
|
token := c.GetHeader("api-token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
|
response.Fail(c, 403, "请先登录")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, ut := service.AllService.UserService.InfoByAccessToken(token)
|
user, ut := service.AllService.UserService.InfoByAccessToken(token)
|
||||||
if user.Id == 0 {
|
if user.Id == 0 {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
|
response.Fail(c, 403, "请先登录")
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !service.AllService.UserService.CheckUserEnable(user) {
|
|
||||||
c.JSON(401, gin.H{
|
|
||||||
"error": "Unauthorized",
|
|
||||||
})
|
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Set("curUser", user)
|
c.Set("curUser", user)
|
||||||
c.Set("token", token)
|
c.Set("token", token)
|
||||||
// if the remaining time is less than 1 day, the token is auto-renewed
|
//如果时间小于1天,token自动续期
|
||||||
service.AllService.UserService.AutoRefreshAccessToken(ut)
|
service.AllService.UserService.AutoRefreshAccessToken(ut)
|
||||||
|
|
||||||
c.Next()
|
c.Next()
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AdminPrivilege ...
|
// AdminPrivilege ...
|
||||||
@@ -12,7 +12,7 @@ func AdminPrivilege() gin.HandlerFunc {
|
|||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
|
|
||||||
if !service.AllService.UserService.IsAdmin(u) {
|
if !service.AllService.UserService.IsAdmin(u) {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NoAccess"))
|
response.Fail(c, 403, "无权限")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cors CORS
|
// Cors 跨域
|
||||||
func Cors() gin.HandlerFunc {
|
func Cors() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
origin := c.GetHeader("Origin")
|
origin := c.GetHeader("Origin")
|
||||||
|
|||||||
+10
-10
@@ -1,29 +1,29 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/response"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func JwtAuth() gin.HandlerFunc {
|
func JwtAuth() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
//disabled for testing
|
//测试先关闭
|
||||||
token := c.GetHeader("api-token")
|
token := c.GetHeader("api-token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
|
response.Fail(c, 403, "请先登录")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
uid, err := global.Jwt.ParseToken(token)
|
uid, err := global.Jwt.ParseToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
|
response.Fail(c, 403, "请先登录")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if uid == 0 {
|
if uid == 0 {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
|
response.Fail(c, 403, "请先登录")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -31,15 +31,15 @@ func JwtAuth() gin.HandlerFunc {
|
|||||||
user := service.AllService.UserService.InfoById(uid)
|
user := service.AllService.UserService.InfoById(uid)
|
||||||
//user := &model.User{
|
//user := &model.User{
|
||||||
// Id: uid,
|
// Id: uid,
|
||||||
// Username: "test user",
|
// Username: "测试用户",
|
||||||
//}
|
//}
|
||||||
if user.Id == 0 {
|
if user.Id == 0 {
|
||||||
response.Fail(c, 403, response.TranslateMsg(c, "NeedLogin"))
|
response.Fail(c, 403, "请先登录")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !service.AllService.UserService.CheckUserEnable(user) {
|
if !service.AllService.UserService.CheckUserEnable(user) {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "Banned"))
|
response.Fail(c, 101, "你已被禁用")
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package middleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/response"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Limiter() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
loginLimiter := global.LoginLimiter
|
|
||||||
clientIp := c.ClientIP()
|
|
||||||
banned, _ := loginLimiter.CheckSecurityStatus(clientIp)
|
|
||||||
if banned {
|
|
||||||
response.Fail(c, http.StatusLocked, response.TranslateMsg(c, "Banned"))
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logger logging middleware
|
// Logger 日志中间件
|
||||||
func Logger() gin.HandlerFunc {
|
func Logger() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
global.Logger.WithFields(
|
global.Logger.WithFields(
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func RustAuth() gin.HandlerFunc {
|
func RustAuth() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
//fmt.Println(c.Request.URL, c.Request.Header)
|
//fmt.Println(c.Request.URL, c.Request.Header)
|
||||||
//getHTTP_AUTHORIZATION
|
//获取HTTP_AUTHORIZATION
|
||||||
token := c.GetHeader("Authorization")
|
token := c.GetHeader("Authorization")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
c.JSON(401, gin.H{
|
c.JSON(401, gin.H{
|
||||||
@@ -25,13 +25,13 @@ func RustAuth() gin.HandlerFunc {
|
|||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//extracttoken, format is Bearer {token}
|
//提取token,格式是Bearer {token}
|
||||||
//this is just a simple extraction
|
//这里只是简单的提取
|
||||||
token = token[7:]
|
token = token[7:]
|
||||||
|
|
||||||
// verify the token
|
//验证token
|
||||||
|
|
||||||
//check whether it is set jwt key
|
//检查是否设置了jwt key
|
||||||
if len(global.Jwt.Key) > 0 {
|
if len(global.Jwt.Key) > 0 {
|
||||||
uid, _ := service.AllService.UserService.VerifyJWT(token)
|
uid, _ := service.AllService.UserService.VerifyJWT(token)
|
||||||
if uid == 0 {
|
if uid == 0 {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/model"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressBookForm struct {
|
type AddressBookForm struct {
|
||||||
@@ -27,7 +27,7 @@ type AddressBookForm struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a AddressBookForm) ToAddressBook() *model.AddressBook {
|
func (a AddressBookForm) ToAddressBook() *model.AddressBook {
|
||||||
//tagsconvert
|
//tags转换
|
||||||
tags, _ := json.Marshal(a.Tags)
|
tags, _ := json.Marshal(a.Tags)
|
||||||
|
|
||||||
return &model.AddressBook{
|
return &model.AddressBook{
|
||||||
@@ -52,7 +52,7 @@ func (a AddressBookForm) ToAddressBook() *model.AddressBook {
|
|||||||
|
|
||||||
}
|
}
|
||||||
func (a AddressBookForm) ToAddressBooks() []*model.AddressBook {
|
func (a AddressBookForm) ToAddressBooks() []*model.AddressBook {
|
||||||
//tagsconvert
|
//tags转换
|
||||||
tags, _ := json.Marshal(a.Tags)
|
tags, _ := json.Marshal(a.Tags)
|
||||||
|
|
||||||
abs := make([]*model.AddressBook, 0, len(a.UserIds))
|
abs := make([]*model.AddressBook, 0, len(a.UserIds))
|
||||||
@@ -92,7 +92,7 @@ type AddressBookQuery struct {
|
|||||||
|
|
||||||
type ShareByWebClientForm struct {
|
type ShareByWebClientForm struct {
|
||||||
Id string `json:"id" validate:"required"`
|
Id string `json:"id" validate:"required"`
|
||||||
PasswordType string `json:"password_type" validate:"required,oneof=once fixed"` //can only be once,fixed
|
PasswordType string `json:"password_type" validate:"required,oneof=once fixed"` //只能是once,fixed
|
||||||
Password string `json:"password" validate:"required"`
|
Password string `json:"password" validate:"required"`
|
||||||
Expire int64 `json:"expire"`
|
Expire int64 `json:"expire"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
type GroupForm struct {
|
type GroupForm struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
@@ -22,15 +22,3 @@ func (gf *GroupForm) ToGroup() *model.Group {
|
|||||||
group.Type = gf.Type
|
group.Type = gf.Type
|
||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceGroupForm struct {
|
|
||||||
Id uint `json:"id"`
|
|
||||||
Name string `json:"name" validate:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gf *DeviceGroupForm) ToDeviceGroup() *model.DeviceGroup {
|
|
||||||
group := &model.DeviceGroup{}
|
|
||||||
group.Id = gf.Id
|
|
||||||
group.Name = gf.Name
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
type Login struct {
|
type Login struct {
|
||||||
Username string `json:"username" validate:"required" label:"username"`
|
Username string `json:"username" validate:"required" label:"用户名"`
|
||||||
Password string `json:"password,omitempty" validate:"required" label:"password"`
|
Password string `json:"password,omitempty" validate:"required" label:"密码"`
|
||||||
Platform string `json:"platform" label:"platform"`
|
Platform string `json:"platform" label:"平台"`
|
||||||
Captcha string `json:"captcha,omitempty" label:"captcha"`
|
Captcha string `json:"captcha,omitempty" label:"验证码"`
|
||||||
CaptchaId string `json:"captcha_id,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoginLogQuery struct {
|
type LoginLogQuery struct {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
"Gwen/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BindOauthForm struct {
|
type BindOauthForm struct {
|
||||||
@@ -22,9 +22,8 @@ type OauthForm struct {
|
|||||||
Scopes string `json:"scopes" validate:"omitempty"`
|
Scopes string `json:"scopes" validate:"omitempty"`
|
||||||
ClientId string `json:"client_id" validate:"required"`
|
ClientId string `json:"client_id" validate:"required"`
|
||||||
ClientSecret string `json:"client_secret" validate:"required"`
|
ClientSecret string `json:"client_secret" validate:"required"`
|
||||||
|
RedirectUrl string `json:"redirect_url" validate:"required"`
|
||||||
AutoRegister *bool `json:"auto_register"`
|
AutoRegister *bool `json:"auto_register"`
|
||||||
PkceEnable *bool `json:"pkce_enable"`
|
|
||||||
PkceMethod string `json:"pkce_method"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (of *OauthForm) ToOauth() *model.Oauth {
|
func (of *OauthForm) ToOauth() *model.Oauth {
|
||||||
@@ -33,11 +32,10 @@ func (of *OauthForm) ToOauth() *model.Oauth {
|
|||||||
OauthType: of.OauthType,
|
OauthType: of.OauthType,
|
||||||
ClientId: of.ClientId,
|
ClientId: of.ClientId,
|
||||||
ClientSecret: of.ClientSecret,
|
ClientSecret: of.ClientSecret,
|
||||||
|
RedirectUrl: of.RedirectUrl,
|
||||||
AutoRegister: of.AutoRegister,
|
AutoRegister: of.AutoRegister,
|
||||||
Issuer: of.Issuer,
|
Issuer: of.Issuer,
|
||||||
Scopes: of.Scopes,
|
Scopes: of.Scopes,
|
||||||
PkceEnable: of.PkceEnable,
|
|
||||||
PkceMethod: of.PkceMethod,
|
|
||||||
}
|
}
|
||||||
oa.Id = of.Id
|
oa.Id = of.Id
|
||||||
return oa
|
return oa
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
type PeerForm struct {
|
type PeerForm struct {
|
||||||
RowId uint `json:"row_id" `
|
RowId uint `json:"row_id" `
|
||||||
@@ -12,8 +12,6 @@ type PeerForm struct {
|
|||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Uuid string `json:"uuid"`
|
Uuid string `json:"uuid"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
GroupId uint `json:"group_id"`
|
|
||||||
Alias string `json:"alias"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeerBatchDeleteForm struct {
|
type PeerBatchDeleteForm struct {
|
||||||
@@ -32,8 +30,6 @@ func (f *PeerForm) ToPeer() *model.Peer {
|
|||||||
Username: f.Username,
|
Username: f.Username,
|
||||||
Uuid: f.Uuid,
|
Uuid: f.Uuid,
|
||||||
Version: f.Version,
|
Version: f.Version,
|
||||||
GroupId: f.GroupId,
|
|
||||||
Alias: f.Alias,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,9 +39,6 @@ type PeerQuery struct {
|
|||||||
Id string `json:"id" form:"id"`
|
Id string `json:"id" form:"id"`
|
||||||
Hostname string `json:"hostname" form:"hostname"`
|
Hostname string `json:"hostname" form:"hostname"`
|
||||||
Uuids string `json:"uuids" form:"uuids"`
|
Uuids string `json:"uuids" form:"uuids"`
|
||||||
Ip string `json:"ip" form:"ip"`
|
|
||||||
Username string `json:"username" form:"username"`
|
|
||||||
Alias string `json:"alias" form:"alias"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SimpleDataQuery struct {
|
type SimpleDataQuery struct {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
type TagForm struct {
|
type TagForm struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
"Gwen/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserForm struct {
|
type UserForm struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Username string `json:"username" validate:"required,gte=2,lte=32"`
|
Username string `json:"username" validate:"required,gte=2,lte=32"`
|
||||||
Email string `json:"email"` //validate:"required,email" emailnot enforced
|
Email string `json:"email"` //validate:"required,email" email不强制
|
||||||
//Password string `json:"password" validate:"required,gte=4,lte=20"`
|
//Password string `json:"password" validate:"required,gte=4,lte=20"`
|
||||||
Nickname string `json:"nickname"`
|
Nickname string `json:"nickname"`
|
||||||
Avatar string `json:"avatar"`
|
Avatar string `json:"avatar"`
|
||||||
GroupId uint `json:"group_id" validate:"required"`
|
GroupId uint `json:"group_id" validate:"required"`
|
||||||
IsAdmin *bool `json:"is_admin" `
|
IsAdmin *bool `json:"is_admin" `
|
||||||
Status model.StatusCode `json:"status" validate:"required,gte=0"`
|
Status model.StatusCode `json:"status" validate:"required,gte=0"`
|
||||||
Remark string `json:"remark"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uf *UserForm) FromUser(user *model.User) *UserForm {
|
func (uf *UserForm) FromUser(user *model.User) *UserForm {
|
||||||
@@ -26,7 +25,6 @@ func (uf *UserForm) FromUser(user *model.User) *UserForm {
|
|||||||
uf.GroupId = user.GroupId
|
uf.GroupId = user.GroupId
|
||||||
uf.IsAdmin = user.IsAdmin
|
uf.IsAdmin = user.IsAdmin
|
||||||
uf.Status = user.Status
|
uf.Status = user.Status
|
||||||
uf.Remark = user.Remark
|
|
||||||
return uf
|
return uf
|
||||||
}
|
}
|
||||||
func (uf *UserForm) ToUser() *model.User {
|
func (uf *UserForm) ToUser() *model.User {
|
||||||
@@ -39,7 +37,6 @@ func (uf *UserForm) ToUser() *model.User {
|
|||||||
user.GroupId = uf.GroupId
|
user.GroupId = uf.GroupId
|
||||||
user.IsAdmin = uf.IsAdmin
|
user.IsAdmin = uf.IsAdmin
|
||||||
user.Status = uf.Status
|
user.Status = uf.Status
|
||||||
user.Remark = uf.Remark
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/model"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
type OidcAuthRequest struct {
|
type OidcAuthRequest struct {
|
||||||
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"device info"`
|
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"设备信息"`
|
||||||
Id string `json:"id" label:"id"`
|
Id string `json:"id" label:"id"`
|
||||||
Op string `json:"op" label:"op"`
|
Op string `json:"op" label:"op"`
|
||||||
Uuid string `json:"uuid" label:"uuid"`
|
Uuid string `json:"uuid" label:"uuid"`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
type AddressBookFormData struct {
|
type AddressBookFormData struct {
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
@@ -36,7 +36,7 @@ func (pf *PeerForm) ToPeer() *model.Peer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PersonalAddressBookForm personal address book form
|
// PersonalAddressBookForm 个人地址簿表单
|
||||||
type PersonalAddressBookForm struct {
|
type PersonalAddressBookForm struct {
|
||||||
model.AddressBook
|
model.AddressBook
|
||||||
ForceAlwaysRelay string `json:"forceAlwaysRelay"`
|
ForceAlwaysRelay string `json:"forceAlwaysRelay"`
|
||||||
|
|||||||
+10
-10
@@ -29,25 +29,25 @@ type DeviceInfoInLogin struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LoginForm struct {
|
type LoginForm struct {
|
||||||
AutoLogin bool `json:"autoLogin" label:"auto login"`
|
AutoLogin bool `json:"autoLogin" label:"自动登录"`
|
||||||
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"device info"`
|
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"设备信息"`
|
||||||
Id string `json:"id" label:"id"`
|
Id string `json:"id" label:"id"`
|
||||||
Type string `json:"type" label:"type"`
|
Type string `json:"type" label:"type"`
|
||||||
Uuid string `json:"uuid" label:"uuid"`
|
Uuid string `json:"uuid" label:"uuid"`
|
||||||
Username string `json:"username" validate:"required,gte=2,lte=32" label:"username"`
|
Username string `json:"username" validate:"required,gte=2,lte=32" label:"用户名"`
|
||||||
Password string `json:"password,omitempty" validate:"gte=4,lte=32" label:"password"`
|
Password string `json:"password,omitempty" validate:"gte=4,lte=32" label:"密码"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserListQuery struct {
|
type UserListQuery struct {
|
||||||
Page uint `json:"page" form:"page" validate:"required" label:"page number"`
|
Page uint `json:"page" form:"page" validate:"required" label:"页码"`
|
||||||
PageSize uint `json:"pageSize" form:"pageSize" validate:"required" label:"items per page"`
|
PageSize uint `json:"page_size" form:"page_size" validate:"required" label:"每页数量"`
|
||||||
Status int `json:"status" form:"status" label:"status"`
|
Status int `json:"status" form:"status" label:"状态"`
|
||||||
Accessible string `json:"accessible" form:"accessible"`
|
Accessible string `json:"accessible" form:"accessible"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeerListQuery struct {
|
type PeerListQuery struct {
|
||||||
Page uint `json:"page" form:"page" validate:"required" label:"page number"`
|
Page uint `json:"page" form:"page" validate:"required" label:"页码"`
|
||||||
PageSize uint `json:"pageSize" form:"pageSize" validate:"required" label:"items per page"`
|
PageSize uint `json:"page_size" form:"page_size" validate:"required" label:"每页数量"`
|
||||||
Status int `json:"status" form:"status" label:"status"`
|
Status int `json:"status" form:"status" label:"状态"`
|
||||||
Accessible string `json:"accessible" form:"accessible"`
|
Accessible string `json:"accessible" form:"accessible"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
type LoginPayload struct {
|
type LoginPayload struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
@@ -22,3 +22,15 @@ type UserOauthItem struct {
|
|||||||
Op string `json:"op"`
|
Op string `json:"op"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GroupUsersPayload struct {
|
||||||
|
Id uint `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GroupUsersPayload) FromUser(user *model.User) {
|
||||||
|
g.Id = user.Id
|
||||||
|
g.Username = user.Username
|
||||||
|
g.Status = 1
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
type AbList struct {
|
type AbList struct {
|
||||||
Peers []*model.AddressBook `json:"peers,omitempty"`
|
Peers []*model.AddressBook `json:"peers,omitempty"`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GroupPeerPayload
|
GroupPeerPayload
|
||||||
@@ -38,7 +38,6 @@ type GroupPeerPayload struct {
|
|||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
UserName string `json:"user_name"`
|
UserName string `json:"user_name"`
|
||||||
Note string `json:"note"`
|
Note string `json:"note"`
|
||||||
DeviceGroupName string `json:"device_group_name"`
|
|
||||||
}
|
}
|
||||||
type PeerPayloadInfo struct {
|
type PeerPayloadInfo struct {
|
||||||
DeviceName string `json:"device_name"`
|
DeviceName string `json:"device_name"`
|
||||||
@@ -60,7 +59,7 @@ func (gpp *GroupPeerPayload) FromAddressBook(a *model.AddressBook, username stri
|
|||||||
gpp.UserName = username
|
gpp.UserName = username
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string, dGroupName string) {
|
func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string) {
|
||||||
gpp.Id = p.Id
|
gpp.Id = p.Id
|
||||||
gpp.Info = &PeerPayloadInfo{
|
gpp.Info = &PeerPayloadInfo{
|
||||||
DeviceName: p.Hostname,
|
DeviceName: p.Hostname,
|
||||||
@@ -69,5 +68,4 @@ func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string, dGroupName
|
|||||||
}
|
}
|
||||||
gpp.Note = ""
|
gpp.Note = ""
|
||||||
gpp.UserName = username
|
gpp.UserName = username
|
||||||
gpp.DeviceGroupName = dGroupName
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "github.com/lejianwen/rustdesk-api/v2/model"
|
import "Gwen/model"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub enum UserStatus {
|
pub enum UserStatus {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lejianwen/rustdesk-api/v2/model"
|
"Gwen/model"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ type WebClientPeerInfoPayload struct {
|
|||||||
|
|
||||||
func (wcpp *WebClientPeerPayload) FromAddressBook(a *model.AddressBook) {
|
func (wcpp *WebClientPeerPayload) FromAddressBook(a *model.AddressBook) {
|
||||||
wcpp.ViewStyle = "shrink"
|
wcpp.ViewStyle = "shrink"
|
||||||
//24 hours ago
|
//24小时前
|
||||||
wcpp.Tm = time.Now().Add(-time.Hour * 24).UnixNano()
|
wcpp.Tm = time.Now().Add(-time.Hour * 24).UnixNano()
|
||||||
wcpp.Info = WebClientPeerInfoPayload{
|
wcpp.Info = WebClientPeerInfoPayload{
|
||||||
Username: a.Username,
|
Username: a.Username,
|
||||||
@@ -34,7 +34,7 @@ func (wcpp *WebClientPeerPayload) FromAddressBook(a *model.AddressBook) {
|
|||||||
|
|
||||||
func (wcpp *WebClientPeerPayload) FromShareRecord(sr *model.ShareRecord) {
|
func (wcpp *WebClientPeerPayload) FromShareRecord(sr *model.ShareRecord) {
|
||||||
wcpp.ViewStyle = "shrink"
|
wcpp.ViewStyle = "shrink"
|
||||||
//24 hours ago
|
//24小时前
|
||||||
wcpp.Tm = time.Now().UnixNano()
|
wcpp.Tm = time.Now().UnixNano()
|
||||||
wcpp.Tmppwd = sr.Password
|
wcpp.Tmppwd = sr.Password
|
||||||
wcpp.Info = WebClientPeerInfoPayload{
|
wcpp.Info = WebClientPeerInfoPayload{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package response
|
package response
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|||||||
+10
-28
@@ -1,12 +1,12 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "Gwen/docs/admin"
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/controller/admin"
|
||||||
|
"Gwen/http/controller/admin/my"
|
||||||
|
"Gwen/http/middleware"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
_ "github.com/lejianwen/rustdesk-api/v2/docs/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/controller/admin"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/controller/admin/my"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/middleware"
|
|
||||||
swaggerFiles "github.com/swaggo/files"
|
swaggerFiles "github.com/swaggo/files"
|
||||||
ginSwagger "github.com/swaggo/gin-swagger"
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
)
|
)
|
||||||
@@ -22,10 +22,7 @@ func Init(g *gin.Engine) {
|
|||||||
adg := g.Group("/api/admin")
|
adg := g.Group("/api/admin")
|
||||||
LoginBind(adg)
|
LoginBind(adg)
|
||||||
adg.POST("/user/register", (&admin.User{}).Register)
|
adg.POST("/user/register", (&admin.User{}).Register)
|
||||||
|
adg.Use(middleware.AdminAuth())
|
||||||
ConfigBind(adg)
|
|
||||||
|
|
||||||
adg.Use(middleware.BackendUserAuth())
|
|
||||||
//FileBind(adg)
|
//FileBind(adg)
|
||||||
UserBind(adg)
|
UserBind(adg)
|
||||||
GroupBind(adg)
|
GroupBind(adg)
|
||||||
@@ -38,6 +35,7 @@ func Init(g *gin.Engine) {
|
|||||||
AddressBookCollectionBind(adg)
|
AddressBookCollectionBind(adg)
|
||||||
AddressBookCollectionRuleBind(adg)
|
AddressBookCollectionRuleBind(adg)
|
||||||
UserTokenBind(adg)
|
UserTokenBind(adg)
|
||||||
|
ConfigBind(adg)
|
||||||
|
|
||||||
//deprecated by ConfigBind
|
//deprecated by ConfigBind
|
||||||
//rs := &admin.Rustdesk{}
|
//rs := &admin.Rustdesk{}
|
||||||
@@ -49,8 +47,8 @@ func Init(g *gin.Engine) {
|
|||||||
MyBind(adg)
|
MyBind(adg)
|
||||||
|
|
||||||
RustdeskCmdBind(adg)
|
RustdeskCmdBind(adg)
|
||||||
DeviceGroupBind(adg)
|
|
||||||
//access static files
|
//访问静态文件
|
||||||
//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
|
//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,18 +104,6 @@ func GroupBind(rg *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeviceGroupBind(rg *gin.RouterGroup) {
|
|
||||||
aR := rg.Group("/device_group").Use(middleware.AdminPrivilege())
|
|
||||||
{
|
|
||||||
cont := &admin.DeviceGroup{}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TagBind(rg *gin.RouterGroup) {
|
func TagBind(rg *gin.RouterGroup) {
|
||||||
aR := rg.Group("/tag").Use(middleware.AdminPrivilege())
|
aR := rg.Group("/tag").Use(middleware.AdminPrivilege())
|
||||||
{
|
{
|
||||||
@@ -235,13 +221,9 @@ func UserTokenBind(rg *gin.RouterGroup) {
|
|||||||
func ConfigBind(rg *gin.RouterGroup) {
|
func ConfigBind(rg *gin.RouterGroup) {
|
||||||
aR := rg.Group("/config")
|
aR := rg.Group("/config")
|
||||||
rs := &admin.Config{}
|
rs := &admin.Config{}
|
||||||
|
|
||||||
aR.GET("/admin", rs.AdminConfig)
|
|
||||||
|
|
||||||
aR.Use(middleware.BackendUserAuth())
|
|
||||||
aR.GET("/server", rs.ServerConfig)
|
aR.GET("/server", rs.ServerConfig)
|
||||||
aR.GET("/app", rs.AppConfig)
|
aR.GET("/app", rs.AppConfig)
|
||||||
|
aR.GET("/admin", rs.AdminConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+9
-28
@@ -1,11 +1,11 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "Gwen/docs/api"
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/controller/api"
|
||||||
|
"Gwen/http/middleware"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
_ "github.com/lejianwen/rustdesk-api/v2/docs/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/controller/api"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/middleware"
|
|
||||||
swaggerFiles "github.com/swaggo/files"
|
swaggerFiles "github.com/swaggo/files"
|
||||||
ginSwagger "github.com/swaggo/gin-swagger"
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -18,27 +18,21 @@ func ApiInit(g *gin.Engine) {
|
|||||||
if global.Config.App.ShowSwagger == 1 {
|
if global.Config.App.ShowSwagger == 1 {
|
||||||
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("api")))
|
g.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.InstanceName("api")))
|
||||||
}
|
}
|
||||||
// load HTML template
|
|
||||||
g.LoadHTMLGlob("resources/templates/*")
|
|
||||||
|
|
||||||
frg := g.Group("/api")
|
frg := g.Group("/api")
|
||||||
|
|
||||||
{
|
|
||||||
i := &api.Index{}
|
i := &api.Index{}
|
||||||
frg.GET("/", i.Index)
|
frg.GET("/", i.Index)
|
||||||
frg.GET("/version", i.Version)
|
|
||||||
|
|
||||||
frg.POST("/heartbeat", i.Heartbeat)
|
frg.POST("/heartbeat", i.Heartbeat)
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
l := &api.Login{}
|
l := &api.Login{}
|
||||||
// if oidc is returned, login via oidc is possible
|
// 如果返回oidc则可以通过oidc登录
|
||||||
frg.GET("/login-options", l.LoginOptions)
|
frg.GET("/login-options", l.LoginOptions)
|
||||||
frg.POST("/login", l.Login)
|
frg.POST("/login", l.Login)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
o := &api.Oauth{}
|
o := &api.Oauth{}
|
||||||
// [method:POST] [uri:/api/oidc/auth]
|
// [method:POST] [uri:/api/oidc/auth]
|
||||||
@@ -48,31 +42,21 @@ func ApiInit(g *gin.Engine) {
|
|||||||
//api/oauth/callback
|
//api/oauth/callback
|
||||||
frg.GET("/oauth/callback", o.OauthCallback)
|
frg.GET("/oauth/callback", o.OauthCallback)
|
||||||
frg.GET("/oauth/login", o.OauthCallback)
|
frg.GET("/oauth/login", o.OauthCallback)
|
||||||
frg.GET("/oauth/msg", o.Message)
|
|
||||||
|
|
||||||
frg.GET("/oidc/callback", o.OauthCallback)
|
|
||||||
frg.GET("/oidc/login", o.OauthCallback)
|
|
||||||
frg.GET("/oidc/msg", o.Message)
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
pe := &api.Peer{}
|
pe := &api.Peer{}
|
||||||
//submit system info
|
//提交系统信息
|
||||||
frg.POST("/sysinfo", pe.SysInfo)
|
frg.POST("/sysinfo", pe.SysInfo)
|
||||||
frg.POST("/sysinfo_ver", pe.SysInfoVer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if global.Config.App.WebClient == 1 {
|
if global.Config.App.WebClient == 1 {
|
||||||
WebClientRoutes(frg)
|
WebClientRoutes(frg)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
au := &api.Audit{}
|
au := &api.Audit{}
|
||||||
//[method:POST] [uri:/api/audit/conn]
|
//[method:POST] [uri:/api/audit/conn]
|
||||||
frg.POST("/audit/conn", au.AuditConn)
|
frg.POST("/audit/conn", au.AuditConn)
|
||||||
//[method:POST] [uri:/api/audit/file]
|
//[method:POST] [uri:/api/audit/file]
|
||||||
frg.POST("/audit/file", au.AuditFile)
|
frg.POST("/audit/file", au.AuditFile)
|
||||||
}
|
|
||||||
|
|
||||||
frg.Use(middleware.RustAuth())
|
frg.Use(middleware.RustAuth())
|
||||||
{
|
{
|
||||||
u := &api.User{}
|
u := &api.User{}
|
||||||
@@ -87,20 +71,17 @@ func ApiInit(g *gin.Engine) {
|
|||||||
gr := &api.Group{}
|
gr := &api.Group{}
|
||||||
frg.GET("/users", gr.Users)
|
frg.GET("/users", gr.Users)
|
||||||
frg.GET("/peers", gr.Peers)
|
frg.GET("/peers", gr.Peers)
|
||||||
// /api/device-group/accessible?current=1&pageSize=100
|
|
||||||
frg.GET("/device-group/accessible", gr.Device)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ab := &api.Ab{}
|
ab := &api.Ab{}
|
||||||
//get address
|
//获取地址
|
||||||
frg.GET("/ab", ab.Ab)
|
frg.GET("/ab", ab.Ab)
|
||||||
//update address
|
//更新地址
|
||||||
frg.POST("/ab", ab.UpAb)
|
frg.POST("/ab", ab.UpAb)
|
||||||
}
|
}
|
||||||
|
|
||||||
PersonalRoutes(frg)
|
PersonalRoutes(frg)
|
||||||
//access static files
|
//访问静态文件
|
||||||
g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/public/upload"))
|
g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/public/upload"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"Gwen/global"
|
||||||
|
"Gwen/http/controller/web"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/lejianwen/rustdesk-api/v2/global"
|
|
||||||
"github.com/lejianwen/rustdesk-api/v2/http/controller/web"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -10,7 +10,7 @@ type Handler interface {
|
|||||||
Gc() error
|
Gc() error
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxTimeOut maximum timeout
|
// MaxTimeOut 最大超时时间
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TypeMem = "memory"
|
TypeMem = "memory"
|
||||||
@@ -49,7 +49,7 @@ func EncodeValue(value interface{}) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DecodeValue(value string, rtv interface{}) error {
|
func DecodeValue(value string, rtv interface{}) error {
|
||||||
// check whether rtv's type is string; if so, assign directly and return
|
//判断rtv的类型是否是string,如果是string,直接赋值并返回
|
||||||
/*switch rtv.(type) {
|
/*switch rtv.(type) {
|
||||||
case *string:
|
case *string:
|
||||||
*(rtv.(*string)) = value
|
*(rtv.(*string)) = value
|
||||||
|
|||||||
Vendored
+6
-6
@@ -42,7 +42,7 @@ func TestFileCacheSet(t *testing.T) {
|
|||||||
err := fc.Set("123", "ddd", 0)
|
err := fc.Set("123", "ddd", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,12 +50,12 @@ func TestFileCacheGet(t *testing.T) {
|
|||||||
fc := New("file")
|
fc := New("file")
|
||||||
err := fc.Set("123", "45156", 300)
|
err := fc.Set("123", "45156", 300)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
res := ""
|
res := ""
|
||||||
err = fc.Get("123", &res)
|
err = fc.Get("123", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed")
|
t.Fatalf("读取失败")
|
||||||
}
|
}
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ func TestRedisCacheSet(t *testing.T) {
|
|||||||
err := rc.Set("123", "ddd", 0)
|
err := rc.Set("123", "ddd", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,12 +81,12 @@ func TestRedisCacheGet(t *testing.T) {
|
|||||||
})
|
})
|
||||||
err := rc.Set("123", "451156", 300)
|
err := rc.Set("123", "451156", 300)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
res := ""
|
res := ""
|
||||||
err = rc.Get("123", &res)
|
err = rc.Get("123", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed")
|
t.Fatalf("读取失败")
|
||||||
}
|
}
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
-4
@@ -32,12 +32,12 @@ func (c *FileCache) Get(key string, value interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get value; if the file does not exist or has expired, return empty and ignore errors
|
// 获取值,如果文件不存在或者过期,返回空,过滤掉错误
|
||||||
func (c *FileCache) getValue(key string) (string, error) {
|
func (c *FileCache) getValue(key string) (string, error) {
|
||||||
f := c.fileName(key)
|
f := c.fileName(key)
|
||||||
fileInfo, err := os.Stat(f)
|
fileInfo, err := os.Stat(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// file does not exist
|
//文件不存在
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
difT := time.Now().Sub(fileInfo.ModTime())
|
difT := time.Now().Sub(fileInfo.ModTime())
|
||||||
@@ -52,7 +52,7 @@ func (c *FileCache) getValue(key string) (string, error) {
|
|||||||
return string(data), nil
|
return string(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// save value
|
// 保存值
|
||||||
func (c *FileCache) saveValue(key string, value string, exp int) error {
|
func (c *FileCache) saveValue(key string, value string, exp int) error {
|
||||||
f := c.fileName(key)
|
f := c.fileName(key)
|
||||||
lock := c.getLock(f)
|
lock := c.getLock(f)
|
||||||
@@ -91,7 +91,7 @@ func (c *FileCache) fileName(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *FileCache) Gc() error {
|
func (c *FileCache) Gc() error {
|
||||||
// check file expiration time and delete
|
//检查文件过期时间,并删除
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+7
-7
@@ -11,7 +11,7 @@ func TestFileSet(t *testing.T) {
|
|||||||
err := fc.Set("123", "ddd", 0)
|
err := fc.Set("123", "ddd", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ func TestFileGet(t *testing.T) {
|
|||||||
err := fc.Get("123", &res)
|
err := fc.Get("123", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
t.Fatalf("read failed")
|
t.Fatalf("读取失败")
|
||||||
}
|
}
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ func TestFileSetGet(t *testing.T) {
|
|||||||
err = fc.Get("key1", &res)
|
err = fc.Get("key1", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
t.Fatalf("read failed")
|
t.Fatalf("读取失败")
|
||||||
}
|
}
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ func TestFileGetJson(t *testing.T) {
|
|||||||
err2 := fc.Get("123", res)
|
err2 := fc.Get("123", res)
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatalf("read failed" + err2.Error())
|
t.Fatalf("读取失败" + err2.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestFileSetGetJson(t *testing.T) {
|
func TestFileSetGetJson(t *testing.T) {
|
||||||
@@ -59,7 +59,7 @@ func TestFileSetGetJson(t *testing.T) {
|
|||||||
}
|
}
|
||||||
err := fc.Set("123", old, 300)
|
err := fc.Set("123", old, 300)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
//old_rr.AA = "aaa"
|
//old_rr.AA = "aaa"
|
||||||
fmt.Println("old_rr", old)
|
fmt.Println("old_rr", old)
|
||||||
@@ -68,10 +68,10 @@ func TestFileSetGetJson(t *testing.T) {
|
|||||||
err2 := fc.Get("123", res)
|
err2 := fc.Get("123", res)
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatalf("read failed" + err2.Error())
|
t.Fatalf("读取失败" + err2.Error())
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(res, old) {
|
if !reflect.DeepEqual(res, old) {
|
||||||
t.Fatalf("read error")
|
t.Fatalf("读取错误")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+9
-9
@@ -11,8 +11,8 @@ import (
|
|||||||
|
|
||||||
type MemoryCache struct {
|
type MemoryCache struct {
|
||||||
data map[string]*CacheItem
|
data map[string]*CacheItem
|
||||||
ll *list.List // used to implement LRU
|
ll *list.List // 用于实现LRU
|
||||||
pq PriorityQueue // used to implement TTL
|
pq PriorityQueue // 用于实现TTL
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
maxBytes int64
|
maxBytes int64
|
||||||
@@ -58,12 +58,12 @@ func (pq *PriorityQueue) Pop() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MemoryCache) Get(key string, value interface{}) error {
|
func (m *MemoryCache) Get(key string, value interface{}) error {
|
||||||
// use reflection to set the stored value into the passed-in pointer variable
|
// 使用反射将存储的值设置到传入的指针变量中
|
||||||
val := reflect.ValueOf(value)
|
val := reflect.ValueOf(value)
|
||||||
if val.Kind() != reflect.Ptr {
|
if val.Kind() != reflect.Ptr {
|
||||||
return errors.New("value must be a pointer")
|
return errors.New("value must be a pointer")
|
||||||
}
|
}
|
||||||
// set to zero value
|
//设为空值
|
||||||
val.Elem().Set(reflect.Zero(val.Elem().Type()))
|
val.Elem().Set(reflect.Zero(val.Elem().Type()))
|
||||||
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
@@ -78,7 +78,7 @@ func (m *MemoryCache) Get(key string, value interface{}) error {
|
|||||||
m.deleteItem(item)
|
m.deleteItem(item)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// move to the tail of the queue
|
//移动到队列尾部
|
||||||
m.ll.MoveToBack(item.ListEle)
|
m.ll.MoveToBack(item.ListEle)
|
||||||
|
|
||||||
err := DecodeValue(item.Value, value)
|
err := DecodeValue(item.Value, value)
|
||||||
@@ -97,11 +97,11 @@ func (m *MemoryCache) Set(key string, value interface{}, exp int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// memory occupied by the key
|
//key 所占用的内存
|
||||||
keyBytes := int64(len(key))
|
keyBytes := int64(len(key))
|
||||||
// size of memory occupied by the value
|
//value所占用的内存空间大小
|
||||||
valueBytes := int64(len(v))
|
valueBytes := int64(len(v))
|
||||||
// check whether the maximum memory limit is exceeded
|
//判断是否超过最大内存限制
|
||||||
if m.maxBytes != 0 && m.maxBytes < keyBytes+valueBytes {
|
if m.maxBytes != 0 && m.maxBytes < keyBytes+valueBytes {
|
||||||
return errors.New("exceed maxBytes")
|
return errors.New("exceed maxBytes")
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ func (m *MemoryCache) startEviction() {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopEviction stops the scheduled cleanup
|
// stopEviction 停止定时清理
|
||||||
func (m *MemoryCache) stopEviction() {
|
func (m *MemoryCache) stopEviction() {
|
||||||
close(m.quit)
|
close(m.quit)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+14
-14
@@ -11,7 +11,7 @@ func TestMemorySet(t *testing.T) {
|
|||||||
err := mc.Set("123", "44567", 0)
|
err := mc.Set("123", "44567", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,10 +22,10 @@ func TestMemoryGet(t *testing.T) {
|
|||||||
err := mc.Get("123", &res)
|
err := mc.Get("123", &res)
|
||||||
fmt.Println("res", res)
|
fmt.Println("res", res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed " + err.Error())
|
t.Fatalf("读取失败 " + err.Error())
|
||||||
}
|
}
|
||||||
if res != "44567" {
|
if res != "44567" {
|
||||||
t.Fatalf("read error")
|
t.Fatalf("读取错误")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -37,30 +37,30 @@ func TestMemorySetExpGet(t *testing.T) {
|
|||||||
mc.Set("2", "5", 5)
|
mc.Set("2", "5", 5)
|
||||||
err := mc.Set("3", "3", 3)
|
err := mc.Set("3", "3", 3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("write failed")
|
t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
res := ""
|
res := ""
|
||||||
err = mc.Get("3", &res)
|
err = mc.Get("3", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res 3", res)
|
fmt.Println("res 3", res)
|
||||||
time.Sleep(4 * time.Second)
|
time.Sleep(4 * time.Second)
|
||||||
//res = ""
|
//res = ""
|
||||||
err = mc.Get("3", &res)
|
err = mc.Get("3", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res 3", res)
|
fmt.Println("res 3", res)
|
||||||
err = mc.Get("2", &res)
|
err = mc.Get("2", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res 2", res)
|
fmt.Println("res 2", res)
|
||||||
err = mc.Get("1", &res)
|
err = mc.Get("1", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res 1", res)
|
fmt.Println("res 1", res)
|
||||||
|
|
||||||
@@ -69,29 +69,29 @@ func TestMemoryLru(t *testing.T) {
|
|||||||
mc := NewMemoryCache(18)
|
mc := NewMemoryCache(18)
|
||||||
mc.Set("1", "1111", 10)
|
mc.Set("1", "1111", 10)
|
||||||
mc.Set("2", "2222", 5)
|
mc.Set("2", "2222", 5)
|
||||||
// read once, so 2 will be moved to the end
|
//读取一次,2就会被放到最后
|
||||||
mc.Get("1", nil)
|
mc.Get("1", nil)
|
||||||
err := mc.Set("3", "three", 3)
|
err := mc.Set("3", "三", 3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//t.Fatalf("write failed")
|
//t.Fatalf("写入失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
res := ""
|
res := ""
|
||||||
err = mc.Get("3", &res)
|
err = mc.Get("3", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res3", res)
|
fmt.Println("res3", res)
|
||||||
res = ""
|
res = ""
|
||||||
err = mc.Get("2", &res)
|
err = mc.Get("2", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res2", res)
|
fmt.Println("res2", res)
|
||||||
res = ""
|
res = ""
|
||||||
err = mc.Get("1", &res)
|
err = mc.Get("1", &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read failed" + err.Error())
|
t.Fatalf("读取失败" + err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("res1", res)
|
fmt.Println("res1", res)
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user