Compare commits

..

10 Commits

Author SHA1 Message Date
ljw
8c97cc8686 up README 2024-09-26 13:38:43 +08:00
ljw
7ae976ee5d up README_EN.md 2024-09-26 13:21:17 +08:00
ljw
e91b53eb32 test release_arm64.yml 2024-09-26 11:49:11 +08:00
ljw
90311536a7 test release_arm64.yml 2024-09-26 11:46:17 +08:00
ljw
e951b7f2f9 fix Dockerfile 2024-09-26 09:29:02 +08:00
ljw
e0f94b62cf add i18n 2024-09-25 22:42:36 +08:00
ljw
8cb701ec85 add i18n 2024-09-25 22:41:57 +08:00
ljw
9afd11e3b8 up readme 2024-09-24 21:16:03 +08:00
ljw
a1d495f2db fix group peers 2024-09-24 19:35:20 +08:00
ljw
652fa93910 up readme 2024-09-24 15:22:21 +08:00
48 changed files with 866 additions and 397 deletions

84
.github/workflows/release_arm64.yml vendored Normal file
View File

@@ -0,0 +1,84 @@
name: Build and Release Arm64
on:
push:
tags:
- 'v*.*.*' # 当推送带有版本号的 tag例如 v1.0.0)时触发工作流
#on:
# push:
# branches: [ "master" ]
# pull_request:
# branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
goos: [ linux ] # 指定要构建的操作系统
goarch: [ arm64 ] # 指定架构
steps:
- name: Checkout code
uses: actions/checkout@v4
- 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: install gcc
run: |
sudo apt-get install gcc-aarch64-linux-gnu -y
- name: build rustdesk-api-web
run: |
git clone https://github.com/lejianwen/rustdesk-api-web
cd rustdesk-api-web
npm install
npm run build
mkdir ../resources/admin/ -p
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.goos }}-${{ matrix.goarch }}
run: |
mkdir release -p
cp -ar resources release/
cp -ar docs release/
cp -ar conf release/
mkdir -p release/data
mkdir -p release/runtime
GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} CC=aarch64-linux-gnu-gcc CGO_LDFLAGS="-static" CGO_ENABLED=1 go build -ldflags "-s -w" -o ./release/apimain ./cmd/apimain.go
tar -czf ${{ matrix.goos}}-${{ matrix.goarch }}.tar.gz ./release
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: myapp-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
${{ matrix.goos}}-${{ matrix.goarch }}.tar.gz
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
${{ matrix.goos}}-${{ matrix.goarch }}.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -5,5 +5,6 @@ go.sum
resources/*
!resources/public/upload/.gitignore
!resources/web
!resources/i18n
release
data

View File

@@ -25,11 +25,12 @@ RUN set -eux; \
mkdir -p release/data; \
mkdir -p release/runtime;
VOLUME /app/data
FROM alpine
WORKDIR /app
RUN apk add --no-cache tzdata
COPY --from=builder /go/rustdesk-api/release /app/
VOLUME /app/data
EXPOSE 21114
CMD ["./apimain"]

View File

@@ -21,6 +21,7 @@
- 地址簿
- 群组
- 授权登录,支持`github``google`登录,支持`web后台`授权登录
- i18n
- Web Admin
- 用户管理
- 设备管理
@@ -29,6 +30,7 @@
- 群组管理
- Oauth 管理
- 快速使用web client
- i18n
- Web Client
- 自动获取API server
- 自动获取ID服务器和KEY
@@ -55,7 +57,7 @@
## 功能
### API 服务: 基本实现了PC端基础的接口。支持Personal版本接口可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_PERSONAL`来控制是否启用
### API 服务: 基本实现了PC端基础的接口。支持Personal版本接口可以通过配置文件`rustdesk.personal`或环境变量`RUSTDESK_API_RUSTDESK_PERSONAL`来控制是否启用
#### 登录
@@ -68,13 +70,13 @@
![pc_ab](docs/pc_ab.png)
#### 群组,群组分为`共享组`和`普通组`,共享组中所有人都能看到小组成员的地址,普通组只有管理员能看到所有小组成员的地址
#### 群组,群组分为`共享组`和`普通组`,共享组中所有人都能看到小组成员的设备,普通组只有管理员能看到所有小组成员的设备
![pc_gr](docs/pc_gr.png)
### **Web Admin**: 使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。
### Web Admin:
***前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
***使用前后端分离,提供用户友好的管理界面,主要用来管理和展示。前端代码在[rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
***后台访问地址是`http://<your server>[:port]/_admin/`初次安装管理员为用户名密码为`admin` `admin`,请即时更改密码***
@@ -82,21 +84,21 @@
![web_admin](docs/web_admin.png)
2. 普通用户界面
![web_user](docs/web_admin_user.png)
3. 右上角也可以更改密码
右上角也可以更改密码
![web_resetpwd](docs/web_resetpwd.png)
4. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
3. 分组可以自定义,方便管理,暂时支持两种类型: `共享组` 和 `普通组`
![web_admin_gr](docs/web_admin_gr.png)
5. 可以直接打开webclient方便使用
4. 可以直接打开webclient方便使用
![web_webclient](docs/admin_webclient.png)
6. Oauth,暂时只支持了`Github`和`Google`, 需要创建一个`OAuth App`,然后配置到后台
5. Oauth,暂时只支持了`Github`和`Google`, 需要创建一个`OAuth App`,然后配置到后台
![web_admin_oauth](docs/web_admin_oauth.png)
- `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`
### **Web Client**:
### Web Client:
1. 如果已经登录了后台web client将自动直接登录
2. 如果没登录后台点击右上角登录即可api server已经自动配置好了
@@ -104,19 +106,22 @@
3. 登录后会自动同步ID服务器和KEY
4. 登录后会将地址簿自动保存到web client中方便使用
### **自动化文档**: 使用 Swag 生成 API 文档,方便开发者理解和使用 API。
### 自动化文档: 使用 Swag 生成 API 文档,方便开发者理解和使用 API。
1. 后台文档 `<youer server>/admin/swagger/index.html`
2. PC端文档 `<youer server>/swagger/index.html`
1. 后台文档 `<youer server[:port]>/admin/swagger/index.html`
2. PC端文档 `<youer server[:port]>/swagger/index.html`
![api_swag](docs/api_swag.png)
## 安装与运行
### 相关配置
* 参考`conf/config.yaml`配置文件,修改相关配置。如果`gorm.type`是`sqlite`则不需要配置mysql相关配置。
* 参考`conf/config.yaml`配置文件,修改相关配置。
* 如果`gorm.type`是`sqlite`则不需要配置mysql相关配置。
* 语言如果不设置默认为`zh-CN`
```yaml
lang: "en"
gin:
api-addr: "0.0.0.0:21114"
mode: "release"
@@ -136,6 +141,7 @@ rustdesk:
relay-server: "192.168.1.66:21117"
api-server: "http://192.168.1.66:21114"
key: "123456789"
personal: 1
```
* 环境变量,变量名前缀是RUSTDESK_API环境变量如果存在将覆盖配置文件中的配置
@@ -143,13 +149,14 @@ rustdesk:
| 变量名 | 说明 | 示例 |
|-------------------------------------|--------------------------------------|-----------------------------|
| TZ | 时区 | Asia/Shanghai |
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
| -----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_PERSONAL | 是否启用个人版API 1:启用,0:不启用; 默认启用 | 1 |
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API 1:启用,0:不启用; 默认启用 | 1 |
| -----MYSQL配置----- | ---------- | ---------- |
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
@@ -370,7 +377,7 @@ lejianwen/rustdesk-api
5. 编译,如果想自己编译,先cd到项目根目录然后windows下直接运行`build.bat`,linux下运行`build.sh`,编译后会在`release`
目录下生成对应的可执行文件。直接运行编译后的可执行文件即可。
6. 打开浏览器访问`http://<your server>:21114/_admin/`,默认用户名密码为`admin`,请及时更改密码。
6. 打开浏览器访问`http://<your server[:port]>/_admin/`,默认用户名密码为`admin`,请及时更改密码。
## 其他

View File

@@ -20,6 +20,7 @@ desktop software that provides self-hosted solutions.
- Address Book
- Groups
- Authorized login, supports `GitHub` and `Google` login, supports `web admin` authorized login
- i18n
- Web Admin
- User Management
- Device Management
@@ -28,6 +29,7 @@ desktop software that provides self-hosted solutions.
- Group Management
- OAuth Management
- Quick access to web client
- i18n
- Web Client
- Automatically obtain API server
- Automatically obtain ID server and KEY
@@ -53,57 +55,54 @@ desktop software that provides self-hosted solutions.
hbbr -k abc1234567
```
## Features
## 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_PERSONAL` environment variable.
### API Service: Basic implementation of the PC client's primary interfaces.Supports the Personal version api, which can be enabled by configuring the `rustdesk.personal` file or the `RUSTDESK_API_RUSTDESK_PERSONAL` environment variable.
#### Login
- Added `GitHub` and `Google` login, which can be used after configuration in the admin panel. See the OAuth
configuration section
for details.
configuration section for details.
- Added authorization login for the web admin panel.
![pc_login](docs/pc_login.png)
![pc_login](docs/en_img/pc_login.png)
#### Address Book
![pc_ab](docs/pc_ab.png)
![pc_ab](docs/en_img/pc_ab.png)
#### Groups: Groups are divided into `shared groups` and `regular groups`. In shared groups, everyone can see the addresses of all group members, while in regular groups, only administrators can see all members' addresses.
#### 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.
![pc_gr](docs/pc_gr.png)
![pc_gr](docs/en_img/pc_gr.png)
### **Web UI
### Web Admin
**: The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and
displaying data.
***The frontend and backend are separated to provide a user-friendly management interface, primarily for managing and
displaying data.Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
***Frontend code is available at [rustdesk-api-web](https://github.com/lejianwen/rustdesk-api-web)***
***Admin panel URL: `http://<your server>[:port]/_admin/`. The default username and password for the initial
***Admin panel URL: `http://<your server[:port]>/_admin/`. The default username and password for the initial
installation are `admin` `admin`, please change the password immediately.***
1. Admin interface:
![web_admin](docs/web_admin.png)
![web_admin](docs/en_img/web_admin.png)
2. Regular user interface:
![web_user](docs/web_admin_user.png)
3. You can change your password from the top right corner:
![web_resetpwd](docs/web_resetpwd.png)
4. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
![web_admin_gr](docs/web_admin_gr.png)
5. You can open the web client directly for convenience:
![web_webclient](docs/admin_webclient.png)
6. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in
![web_user](docs/en_img/web_admin_user.png)
You can change your password from the top right corner:
![web_resetpwd](docs/en_img/web_resetpwd.png)
3. Groups can be customized for easy management. Currently, two types are supported: `shared group` and `regular group`.
![web_admin_gr](docs/en_img/web_admin_gr.png)
4. You can open the web client directly for convenience:
![web_webclient](docs/en_img/admin_webclient.png)
5. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in
the admin
panel.
![web_admin_oauth](docs/web_admin_oauth.png)
![web_admin_oauth](docs/en_img/web_admin_oauth.png)
- 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`.
### **Web Client**:
### Web Client:
1. If you're already logged into the admin panel, the web client will log in automatically.
2. If you're not logged in, simply click the login button at the top right corner, and the API server will be
@@ -112,22 +111,22 @@ installation are `admin` `admin`, please change the password immediately.***
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.
### **Automated Documentation
### Automated Documentation : API documentation is generated using Swag, making it easier for developers to understand and use the API.
** : API documentation is generated using Swag, making it easier for developers to understand and use the API.
1. Admin panel docs: `<your server>/admin/swagger/index.html`
2. PC client docs: `<your server>/swagger/index.html`
1. Admin panel docs: `<your server[:port]>/admin/swagger/index.html`
2. PC client docs: `<your server[:port]>/swagger/index.html`
![api_swag](docs/api_swag.png)
## Installation and Setup
### Configuration
* Modify the configuration in `conf/config.yaml`. If `gorm.type` is set to `sqlite`, MySQL-related configurations are
not required.
* Modify the configuration in `conf/config.yaml`.
* If `gorm.type` is set to `sqlite`, MySQL-related configurations are not required.
* Language support: `en` and `zh-CN` are supported. The default is `zh-CN`.
```yaml
lang: "en"
gin:
api-addr: "0.0.0.0:21114"
mode: "release"
@@ -147,21 +146,24 @@ rustdesk:
relay-server: "192.168.1.66:21117"
api-server: "http://192.168.1.66:21114"
key: "123456789"
personal: 1
```
* Environment variables, with the prefix `RUSTDESK_API`, will override the settings in the configuration file if
* Environment variables, with the prefix `RUSTDESK_API_RUSTDESK_PERSONAL`, will override the settings in the
configuration file if
present.
| Variable Name | Description | Example |
|------------------------------------|-----------------------------------------------------------|--------------------------------|
| TZ | timezone | Asia/Shanghai |
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
| ----- GIN Configuration ----- | --------------------------------------- | ------------------------------ |
| TZ | 时区 | Asia/Shanghai |
| 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_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
| 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 |
@@ -183,6 +185,7 @@ rustdesk:
```bash
docker run -d --name rustdesk-api -p 21114:21114 \
-v /data/rustdesk/api:/app/data \
-e RUSTDESK_API_LANG=en \
-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_API_SERVER=http://192.168.1.66:21114 \
@@ -382,7 +385,7 @@ Download the release from [release](https://github.com/lejianwen/rustdesk-api/re
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>:21114/_admin/`, with default credentials `admin admin`. Please
6. Open your browser and visit `http://<your server[:port]>/_admin/`, with default credentials `admin admin`. Please
change the password promptly.
## Miscellaneous

View File

@@ -12,12 +12,17 @@ import (
"Gwen/model"
"Gwen/service"
"fmt"
"github.com/BurntSushi/toml"
"github.com/gin-gonic/gin"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh_Hans_CN"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
"github.com/go-redis/redis/v8"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
"reflect"
)
@@ -98,6 +103,7 @@ func main() {
//locker
global.Lock = lock.NewLocal()
InitI18n()
//gin
http.ApiInit()
@@ -105,15 +111,25 @@ func main() {
func ApiInitValidator() {
validate := validator.New()
// 定义不同的语言翻译
enT := en.New()
cn := zh_Hans_CN.New()
uni := ut.New(enT, cn)
trans, _ := uni.GetTranslator("cn")
err := zh_translations.RegisterDefaultTranslations(validate, trans)
enTrans, _ := uni.GetTranslator("en")
zhTrans, _ := uni.GetTranslator("zh_Hans_CN")
err := zh_translations.RegisterDefaultTranslations(validate, zhTrans)
if err != nil {
//退出
panic(err)
}
err = en_translations.RegisterDefaultTranslations(validate, enTrans)
if err != nil {
panic(err)
}
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
label := field.Tag.Get("label")
if label == "" {
@@ -122,10 +138,16 @@ func ApiInitValidator() {
return label
})
global.Validator.Validate = validate
global.Validator.VTrans = trans
global.Validator.UT = uni // 存储 Universal Translator
global.Validator.VTrans = zhTrans
global.Validator.ValidStruct = func(i interface{}) []string {
global.Validator.ValidStruct = func(ctx *gin.Context, i interface{}) []string {
err := global.Validator.Validate.Struct(i)
lang := ctx.GetHeader("Accept-Language")
if lang == "" {
lang = global.Config.Lang
}
trans := getTranslatorForLang(lang)
errList := make([]string, 0, 10)
if err != nil {
if _, ok := err.(*validator.InvalidValidationError); ok {
@@ -133,14 +155,18 @@ func ApiInitValidator() {
return errList
}
for _, err2 := range err.(validator.ValidationErrors) {
errList = append(errList, err2.Translate(global.Validator.VTrans))
errList = append(errList, err2.Translate(trans))
}
}
return errList
}
global.Validator.ValidVar = func(field interface{}, tag string) []string {
global.Validator.ValidVar = func(ctx *gin.Context, field interface{}, tag string) []string {
err := global.Validator.Validate.Var(field, tag)
fmt.Println(err)
lang := ctx.GetHeader("Accept-Language")
if lang == "" {
lang = global.Config.Lang
}
trans := getTranslatorForLang(lang)
errList := make([]string, 0, 10)
if err != nil {
if _, ok := err.(*validator.InvalidValidationError); ok {
@@ -148,14 +174,29 @@ func ApiInitValidator() {
return errList
}
for _, err2 := range err.(validator.ValidationErrors) {
errList = append(errList, err2.Translate(global.Validator.VTrans))
errList = append(errList, err2.Translate(trans))
}
}
return errList
}
}
func getTranslatorForLang(lang string) ut.Translator {
switch lang {
case "zh_CN":
fallthrough
case "zh-CN":
fallthrough
case "zh":
trans, _ := global.Validator.UT.GetTranslator("zh_Hans_CN")
return trans
case "en":
fallthrough
default:
trans, _ := global.Validator.UT.GetTranslator("en")
return trans
}
}
func DatabaseAutoUpdate() {
version := 126
@@ -251,3 +292,37 @@ func Migrate(version uint) {
}
}
func InitI18n() {
bundle := i18n.NewBundle(language.English)
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
bundle.LoadMessageFile(global.Config.Gin.ResourcesPath + "/i18n/en.toml")
bundle.LoadMessageFile(global.Config.Gin.ResourcesPath + "/i18n/zh_CN.toml")
global.Localizer = func(ctx *gin.Context) *i18n.Localizer {
lang := ctx.GetHeader("Accept-Language")
if lang == "" {
lang = global.Config.Lang
}
if lang == "en" {
return i18n.NewLocalizer(bundle, "en")
} else {
return i18n.NewLocalizer(bundle, lang, "en")
}
}
//personUnreadEmails := localizer.MustLocalize(&i18n.LocalizeConfig{
// DefaultMessage: &i18n.Message{
// ID: "PersonUnreadEmails",
// },
// PluralCount: 6,
// TemplateData: map[string]interface{}{
// "Name": "LE",
// "PluralCount": 6,
// },
//})
//personUnreadEmails, err := global.Localizer.LocalizeMessage(&i18n.Message{
// ID: "ParamsError",
//})
//fmt.Println(err, personUnreadEmails)
}

View File

@@ -1,3 +1,4 @@
lang: "zh-CN"
gin:
api-addr: "0.0.0.0:21114"
mode: "release" #release,debug,test

View File

@@ -15,6 +15,7 @@ const (
)
type Config struct {
Lang string `mapstructure:"lang"`
Gorm Gorm
Mysql Mysql
Gin Gin

View File

@@ -1185,7 +1185,7 @@ const docTemplateadmin = `{
"token": []
}
],
"description": "创建机器",
"description": "创建设备",
"consumes": [
"application/json"
],
@@ -1193,12 +1193,12 @@ const docTemplateadmin = `{
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "创建机器",
"summary": "创建设备",
"parameters": [
{
"description": "机器信息",
"description": "设备信息",
"name": "body",
"in": "body",
"required": true,
@@ -1242,7 +1242,7 @@ const docTemplateadmin = `{
"token": []
}
],
"description": "机器删除",
"description": "设备删除",
"consumes": [
"application/json"
],
@@ -1250,12 +1250,12 @@ const docTemplateadmin = `{
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器删除",
"summary": "设备删除",
"parameters": [
{
"description": "机器信息",
"description": "设备信息",
"name": "body",
"in": "body",
"required": true,
@@ -1287,7 +1287,7 @@ const docTemplateadmin = `{
"token": []
}
],
"description": "机器详情",
"description": "设备详情",
"consumes": [
"application/json"
],
@@ -1295,9 +1295,9 @@ const docTemplateadmin = `{
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器详情",
"summary": "设备详情",
"parameters": [
{
"type": "integer",
@@ -1342,7 +1342,7 @@ const docTemplateadmin = `{
"token": []
}
],
"description": "机器列表",
"description": "设备列表",
"consumes": [
"application/json"
],
@@ -1350,9 +1350,9 @@ const docTemplateadmin = `{
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器列表",
"summary": "设备列表",
"parameters": [
{
"type": "integer",
@@ -1402,7 +1402,7 @@ const docTemplateadmin = `{
"token": []
}
],
"description": "机器编辑",
"description": "设备编辑",
"consumes": [
"application/json"
],
@@ -1410,12 +1410,12 @@ const docTemplateadmin = `{
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器编辑",
"summary": "设备编辑",
"parameters": [
{
"description": "机器信息",
"description": "设备信息",
"name": "body",
"in": "body",
"required": true,
@@ -2278,7 +2278,7 @@ const docTemplateadmin = `{
"id": {
"type": "string"
},
"login_name": {
"loginName": {
"type": "string"
},
"online": {
@@ -2290,16 +2290,16 @@ const docTemplateadmin = `{
"platform": {
"type": "string"
},
"rdp_port": {
"rdpPort": {
"type": "string"
},
"rdp_username": {
"rdpUsername": {
"type": "string"
},
"row_id": {
"type": "integer"
},
"same_server": {
"sameServer": {
"type": "boolean"
},
"tags": {
@@ -2455,7 +2455,6 @@ const docTemplateadmin = `{
"type": "object",
"required": [
"group_id",
"nickname",
"status",
"username"
],

View File

@@ -1178,7 +1178,7 @@
"token": []
}
],
"description": "创建机器",
"description": "创建设备",
"consumes": [
"application/json"
],
@@ -1186,12 +1186,12 @@
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "创建机器",
"summary": "创建设备",
"parameters": [
{
"description": "机器信息",
"description": "设备信息",
"name": "body",
"in": "body",
"required": true,
@@ -1235,7 +1235,7 @@
"token": []
}
],
"description": "机器删除",
"description": "设备删除",
"consumes": [
"application/json"
],
@@ -1243,12 +1243,12 @@
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器删除",
"summary": "设备删除",
"parameters": [
{
"description": "机器信息",
"description": "设备信息",
"name": "body",
"in": "body",
"required": true,
@@ -1280,7 +1280,7 @@
"token": []
}
],
"description": "机器详情",
"description": "设备详情",
"consumes": [
"application/json"
],
@@ -1288,9 +1288,9 @@
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器详情",
"summary": "设备详情",
"parameters": [
{
"type": "integer",
@@ -1335,7 +1335,7 @@
"token": []
}
],
"description": "机器列表",
"description": "设备列表",
"consumes": [
"application/json"
],
@@ -1343,9 +1343,9 @@
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器列表",
"summary": "设备列表",
"parameters": [
{
"type": "integer",
@@ -1395,7 +1395,7 @@
"token": []
}
],
"description": "机器编辑",
"description": "设备编辑",
"consumes": [
"application/json"
],
@@ -1403,12 +1403,12 @@
"application/json"
],
"tags": [
"机器"
"设备"
],
"summary": "机器编辑",
"summary": "设备编辑",
"parameters": [
{
"description": "机器信息",
"description": "设备信息",
"name": "body",
"in": "body",
"required": true,
@@ -2271,7 +2271,7 @@
"id": {
"type": "string"
},
"login_name": {
"loginName": {
"type": "string"
},
"online": {
@@ -2283,16 +2283,16 @@
"platform": {
"type": "string"
},
"rdp_port": {
"rdpPort": {
"type": "string"
},
"rdp_username": {
"rdpUsername": {
"type": "string"
},
"row_id": {
"type": "integer"
},
"same_server": {
"sameServer": {
"type": "boolean"
},
"tags": {
@@ -2448,7 +2448,6 @@
"type": "object",
"required": [
"group_id",
"nickname",
"status",
"username"
],

View File

@@ -24,7 +24,7 @@ definitions:
type: string
id:
type: string
login_name:
loginName:
type: string
online:
type: boolean
@@ -32,13 +32,13 @@ definitions:
type: string
platform:
type: string
rdp_port:
rdpPort:
type: string
rdp_username:
rdpUsername:
type: string
row_id:
type: integer
same_server:
sameServer:
type: boolean
tags:
items:
@@ -165,7 +165,6 @@ definitions:
type: string
required:
- group_id
- nickname
- status
- username
type: object
@@ -1162,9 +1161,9 @@ paths:
post:
consumes:
- application/json
description: 创建机器
description: 创建设备
parameters:
- description: 机器信息
- description: 设备信息
in: body
name: body
required: true
@@ -1188,16 +1187,16 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: 创建机器
summary: 创建设备
tags:
- 机器
- 设备
/admin/peer/delete:
post:
consumes:
- application/json
description: 机器删除
description: 设备删除
parameters:
- description: 机器信息
- description: 设备信息
in: body
name: body
required: true
@@ -1216,14 +1215,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: 机器删除
summary: 设备删除
tags:
- 机器
- 设备
/admin/peer/detail/{id}:
get:
consumes:
- application/json
description: 机器详情
description: 设备详情
parameters:
- description: ID
in: path
@@ -1248,14 +1247,14 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: 机器详情
summary: 设备详情
tags:
- 机器
- 设备
/admin/peer/list:
get:
consumes:
- application/json
description: 机器列表
description: 设备列表
parameters:
- description: 页码
in: query
@@ -1283,16 +1282,16 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: 机器列表
summary: 设备列表
tags:
- 机器
- 设备
/admin/peer/update:
post:
consumes:
- application/json
description: 机器编辑
description: 设备编辑
parameters:
- description: 机器信息
- description: 设备信息
in: body
name: body
required: true
@@ -1316,9 +1315,9 @@ paths:
$ref: '#/definitions/response.Response'
security:
- token: []
summary: 机器编辑
summary: 设备编辑
tags:
- 机器
- 设备
/admin/server-config:
get:
consumes:

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
docs/en_img/pc_ab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/en_img/pc_gr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
docs/en_img/pc_login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
docs/en_img/web_admin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -6,9 +6,11 @@ import (
"Gwen/lib/jwt"
"Gwen/lib/lock"
"Gwen/lib/upload"
"github.com/gin-gonic/gin"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
"github.com/go-redis/redis/v8"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"gorm.io/gorm"
@@ -23,11 +25,13 @@ var (
Cache cache.Handler
Validator struct {
Validate *validator.Validate
UT *ut.UniversalTranslator
VTrans ut.Translator
ValidStruct func(interface{}) []string
ValidVar func(field interface{}, tag string) []string
ValidStruct func(*gin.Context, interface{}) []string
ValidVar func(ctx *gin.Context, field interface{}, tag string) []string
}
Oss *upload.Oss
Jwt *jwt.Jwt
Lock lock.Locker
Oss *upload.Oss
Jwt *jwt.Jwt
Lock lock.Locker
Localizer func(ctx *gin.Context) *i18n.Localizer
)

8
go.mod
View File

@@ -3,6 +3,7 @@ module Gwen
go 1.22
require (
github.com/BurntSushi/toml v1.3.2
github.com/antonfisher/nested-logrus-formatter v1.3.1
github.com/fsnotify/fsnotify v1.5.1
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
@@ -12,12 +13,14 @@ require (
github.com/go-playground/validator/v10 v10.11.2
github.com/go-redis/redis/v8 v8.11.4
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/viper v1.9.0
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/swaggo/swag v1.16.3
golang.org/x/oauth2 v0.23.0
golang.org/x/text v0.18.0
gorm.io/driver/mysql v1.5.7
gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.7
@@ -64,10 +67,9 @@ require (
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/tools v0.7.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

View File

@@ -31,14 +31,14 @@ func (ct *AddressBook) Detail(c *gin.Context) {
t := service.AllService.AddressBookService.InfoByRowId(uint(iid))
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
if t.RowId > 0 {
response.Success(c, t)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
@@ -56,10 +56,10 @@ func (ct *AddressBook) Detail(c *gin.Context) {
func (ct *AddressBook) Create(c *gin.Context) {
f := &admin.AddressBookForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -71,7 +71,7 @@ func (ct *AddressBook) Create(c *gin.Context) {
}
err := service.AllService.AddressBookService.Create(t)
if err != nil {
response.Fail(c, 101, "创建失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, u)
@@ -94,7 +94,7 @@ func (ct *AddressBook) Create(c *gin.Context) {
func (ct *AddressBook) List(c *gin.Context) {
query := &admin.AddressBookQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
@@ -123,27 +123,27 @@ func (ct *AddressBook) List(c *gin.Context) {
func (ct *AddressBook) Update(c *gin.Context) {
f := &admin.AddressBookForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
if f.RowId == 0 {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
t := f.ToAddressBook()
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
err := service.AllService.AddressBookService.Update(t)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
@@ -163,11 +163,11 @@ func (ct *AddressBook) Update(c *gin.Context) {
func (ct *AddressBook) Delete(c *gin.Context) {
f := &admin.AddressBookForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.RowId
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -175,7 +175,7 @@ func (ct *AddressBook) Delete(c *gin.Context) {
t := service.AllService.AddressBookService.InfoByRowId(f.RowId)
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
if u.Id > 0 {
@@ -184,8 +184,8 @@ func (ct *AddressBook) Delete(c *gin.Context) {
response.Success(c, nil)
return
}
response.Fail(c, 101, err.Error())
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}

View File

@@ -31,7 +31,7 @@ func (ct *Group) Detail(c *gin.Context) {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
@@ -49,10 +49,10 @@ func (ct *Group) Detail(c *gin.Context) {
func (ct *Group) Create(c *gin.Context) {
f := &admin.GroupForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -60,7 +60,7 @@ func (ct *Group) Create(c *gin.Context) {
u := f.ToGroup()
err := service.AllService.GroupService.Create(u)
if err != nil {
response.Fail(c, 101, "创建失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, u)
@@ -81,7 +81,7 @@ func (ct *Group) Create(c *gin.Context) {
func (ct *Group) List(c *gin.Context) {
query := &admin.PageQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
res := service.AllService.GroupService.List(query.Page, query.PageSize, nil)
@@ -102,14 +102,14 @@ func (ct *Group) List(c *gin.Context) {
func (ct *Group) Update(c *gin.Context) {
f := &admin.GroupForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if f.Id == 0 {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -117,7 +117,7 @@ func (ct *Group) Update(c *gin.Context) {
u := f.ToGroup()
err := service.AllService.GroupService.Update(u)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
@@ -137,11 +137,11 @@ func (ct *Group) Update(c *gin.Context) {
func (ct *Group) Delete(c *gin.Context) {
f := &admin.GroupForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -153,8 +153,8 @@ func (ct *Group) Delete(c *gin.Context) {
response.Success(c, nil)
return
}
response.Fail(c, 101, err.Error())
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}

View File

@@ -28,11 +28,11 @@ func (ct *Login) Login(c *gin.Context) {
f := &admin.Login{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -40,7 +40,7 @@ func (ct *Login) Login(c *gin.Context) {
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
if u.Id == 0 {
response.Fail(c, 101, "用户名或密码错误")
response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
return
}

View File

@@ -33,7 +33,7 @@ func (ct *LoginLog) Detail(c *gin.Context) {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
@@ -53,7 +53,7 @@ func (ct *LoginLog) Detail(c *gin.Context) {
func (ct *LoginLog) List(c *gin.Context) {
query := &admin.LoginLogQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
@@ -82,11 +82,11 @@ func (ct *LoginLog) List(c *gin.Context) {
func (ct *LoginLog) Delete(c *gin.Context) {
f := &model.LoginLog{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -94,7 +94,7 @@ func (ct *LoginLog) Delete(c *gin.Context) {
l := service.AllService.LoginLogService.InfoById(f.Id)
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && l.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
if l.Id > 0 {
@@ -106,5 +106,5 @@ func (ct *LoginLog) Delete(c *gin.Context) {
response.Fail(c, 101, err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}

View File

@@ -18,12 +18,12 @@ type Oauth struct {
func (o *Oauth) Info(c *gin.Context) {
code := c.Query("code")
if code == "" {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
v := service.AllService.OauthService.GetOauthCache(code)
if v == nil {
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
response.Success(c, v)
@@ -33,20 +33,20 @@ func (o *Oauth) ToBind(c *gin.Context) {
f := &adminReq.BindOauthForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
utr := service.AllService.UserService.UserThirdInfo(u.Id, f.Op)
if utr.Id > 0 {
response.Fail(c, 101, "已绑定过了")
response.Fail(c, 101, response.TranslateMsg(c, "OauthHasBindOtherUser"))
return
}
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
if err != nil {
response.Error(c, err.Error())
response.Error(c, response.TranslateMsg(c, err.Error()))
return
}
@@ -89,22 +89,22 @@ func (o *Oauth) BindConfirm(c *gin.Context) {
j := &adminReq.OauthConfirmForm{}
err := c.ShouldBindJSON(j)
if err != nil {
response.Fail(c, 101, "参数错误"+err.Error())
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if j.Code == "" {
response.Fail(c, 101, "参数错误: code 不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
v := service.AllService.OauthService.GetOauthCache(j.Code)
if v == nil {
response.Fail(c, 101, "授权已过期")
response.Fail(c, 101, response.TranslateMsg(c, "OauthExpired"))
return
}
u := service.AllService.UserService.CurUser(c)
err = service.AllService.OauthService.BindGithubUser(v.ThirdOpenId, v.ThirdOpenId, u.Id)
if err != nil {
response.Fail(c, 101, "绑定失败,请重试")
response.Fail(c, 101, response.TranslateMsg(c, "BindFail"))
return
}
@@ -117,22 +117,30 @@ func (o *Oauth) Unbind(c *gin.Context) {
f := &adminReq.UnBindOauthForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
utr := service.AllService.UserService.UserThirdInfo(u.Id, f.Op)
if utr.Id == 0 {
response.Fail(c, 101, "未绑定")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
if f.Op == model.OauthTypeGithub {
err = service.AllService.OauthService.UnBindGithubUser(u.Id)
if err != nil {
response.Fail(c, 101, "解绑失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
}
if f.Op == model.OauthTypeGoogle {
err = service.AllService.OauthService.UnBindGoogleUser(u.Id)
if err != nil {
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
}
response.Success(c, nil)
}
@@ -155,7 +163,7 @@ func (o *Oauth) Detail(c *gin.Context) {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
@@ -173,10 +181,10 @@ func (o *Oauth) Detail(c *gin.Context) {
func (o *Oauth) Create(c *gin.Context) {
f := &admin.OauthForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误"+err.Error())
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -184,14 +192,14 @@ func (o *Oauth) Create(c *gin.Context) {
ex := service.AllService.OauthService.InfoByOp(f.Op)
if ex.Id > 0 {
response.Fail(c, 101, "已存在"+f.Op)
response.Fail(c, 101, response.TranslateMsg(c, "ItemExists"))
return
}
u := f.ToOauth()
err := service.AllService.OauthService.Create(u)
if err != nil {
response.Fail(c, 101, "创建失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, u)
@@ -212,7 +220,7 @@ func (o *Oauth) Create(c *gin.Context) {
func (o *Oauth) List(c *gin.Context) {
query := &admin.PageQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
res := service.AllService.OauthService.List(query.Page, query.PageSize, nil)
@@ -233,14 +241,14 @@ func (o *Oauth) List(c *gin.Context) {
func (o *Oauth) Update(c *gin.Context) {
f := &admin.OauthForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if f.Id == 0 {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -248,7 +256,7 @@ func (o *Oauth) Update(c *gin.Context) {
u := f.ToOauth()
err := service.AllService.OauthService.Update(u)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
@@ -268,11 +276,11 @@ func (o *Oauth) Update(c *gin.Context) {
func (o *Oauth) Delete(c *gin.Context) {
f := &admin.OauthForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -287,5 +295,5 @@ func (o *Oauth) Delete(c *gin.Context) {
response.Fail(c, 101, err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}

View File

@@ -12,10 +12,10 @@ import (
type Peer struct {
}
// Detail 机器
// @Tags 机器
// @Summary 机器详情
// @Description 机器详情
// Detail 设备
// @Tags 设备
// @Summary 设备详情
// @Description 设备详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
@@ -31,17 +31,17 @@ func (ct *Peer) Detail(c *gin.Context) {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
// Create 创建机器
// @Tags 机器
// @Summary 创建机器
// @Description 创建机器
// Create 创建设备
// @Tags 设备
// @Summary 创建设备
// @Description 创建设备
// @Accept json
// @Produce json
// @Param body body admin.PeerForm true "机器信息"
// @Param body body admin.PeerForm true "设备信息"
// @Success 200 {object} response.Response{data=model.Peer}
// @Failure 500 {object} response.Response
// @Router /admin/peer/create [post]
@@ -49,10 +49,10 @@ func (ct *Peer) Detail(c *gin.Context) {
func (ct *Peer) Create(c *gin.Context) {
f := &admin.PeerForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -60,16 +60,16 @@ func (ct *Peer) Create(c *gin.Context) {
u := f.ToPeer()
err := service.AllService.PeerService.Create(u)
if err != nil {
response.Fail(c, 101, "创建失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, u)
}
// List 列表
// @Tags 机器
// @Summary 机器列表
// @Description 机器列表
// @Tags 设备
// @Summary 设备列表
// @Description 设备列表
// @Accept json
// @Produce json
// @Param page query int false "页码"
@@ -81,7 +81,7 @@ func (ct *Peer) Create(c *gin.Context) {
func (ct *Peer) List(c *gin.Context) {
query := &admin.PageQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
res := service.AllService.PeerService.List(query.Page, query.PageSize, nil)
@@ -89,12 +89,12 @@ func (ct *Peer) List(c *gin.Context) {
}
// Update 编辑
// @Tags 机器
// @Summary 机器编辑
// @Description 机器编辑
// @Tags 设备
// @Summary 设备编辑
// @Description 设备编辑
// @Accept json
// @Produce json
// @Param body body admin.PeerForm true "机器信息"
// @Param body body admin.PeerForm true "设备信息"
// @Success 200 {object} response.Response{data=model.Peer}
// @Failure 500 {object} response.Response
// @Router /admin/peer/update [post]
@@ -102,14 +102,14 @@ func (ct *Peer) List(c *gin.Context) {
func (ct *Peer) Update(c *gin.Context) {
f := &admin.PeerForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if f.RowId == 0 {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -117,19 +117,19 @@ func (ct *Peer) Update(c *gin.Context) {
u := f.ToPeer()
err := service.AllService.PeerService.Update(u)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
}
// Delete 删除
// @Tags 机器
// @Summary 机器删除
// @Description 机器删除
// @Tags 设备
// @Summary 设备删除
// @Description 设备删除
// @Accept json
// @Produce json
// @Param body body admin.PeerForm true "机器信息"
// @Param body body admin.PeerForm true "设备信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/peer/delete [post]
@@ -137,11 +137,11 @@ func (ct *Peer) Update(c *gin.Context) {
func (ct *Peer) Delete(c *gin.Context) {
f := &admin.PeerForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.RowId
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -153,8 +153,8 @@ func (ct *Peer) Delete(c *gin.Context) {
response.Success(c, nil)
return
}
response.Fail(c, 101, err.Error())
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}

View File

@@ -30,14 +30,14 @@ func (ct *Tag) Detail(c *gin.Context) {
t := service.AllService.TagService.InfoById(uint(iid))
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
if t.Id > 0 {
response.Success(c, t)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
@@ -55,10 +55,10 @@ func (ct *Tag) Detail(c *gin.Context) {
func (ct *Tag) Create(c *gin.Context) {
f := &admin.TagForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -70,7 +70,7 @@ func (ct *Tag) Create(c *gin.Context) {
}
err := service.AllService.TagService.Create(t)
if err != nil {
response.Fail(c, 101, "创建失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, u)
@@ -93,7 +93,7 @@ func (ct *Tag) Create(c *gin.Context) {
func (ct *Tag) List(c *gin.Context) {
query := &admin.TagQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
@@ -122,27 +122,27 @@ func (ct *Tag) List(c *gin.Context) {
func (ct *Tag) Update(c *gin.Context) {
f := &admin.TagForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
if f.Id == 0 {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
t := f.ToTag()
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
err := service.AllService.TagService.Update(t)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
@@ -162,11 +162,11 @@ func (ct *Tag) Update(c *gin.Context) {
func (ct *Tag) Delete(c *gin.Context) {
f := &admin.TagForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -174,7 +174,7 @@ func (ct *Tag) Delete(c *gin.Context) {
t := service.AllService.TagService.InfoById(f.Id)
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
response.Fail(c, 101, "无权限")
response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
return
}
if u.Id > 0 {
@@ -186,5 +186,5 @@ func (ct *Tag) Delete(c *gin.Context) {
response.Fail(c, 101, err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}

View File

@@ -33,7 +33,7 @@ func (ct *User) Detail(c *gin.Context) {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
@@ -51,10 +51,10 @@ func (ct *User) Detail(c *gin.Context) {
func (ct *User) Create(c *gin.Context) {
f := &admin.UserForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -62,7 +62,7 @@ func (ct *User) Create(c *gin.Context) {
u := f.ToUser()
err := service.AllService.UserService.Create(u)
if err != nil {
response.Fail(c, 101, "创建失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, u)
@@ -84,7 +84,7 @@ func (ct *User) Create(c *gin.Context) {
func (ct *User) List(c *gin.Context) {
query := &admin.UserQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
res := service.AllService.UserService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
@@ -109,14 +109,14 @@ func (ct *User) List(c *gin.Context) {
func (ct *User) Update(c *gin.Context) {
f := &admin.UserForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误:"+err.Error())
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if f.Id == 0 {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -124,7 +124,7 @@ func (ct *User) Update(c *gin.Context) {
u := f.ToUser()
err := service.AllService.UserService.Update(u)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
@@ -144,11 +144,11 @@ func (ct *User) Update(c *gin.Context) {
func (ct *User) Delete(c *gin.Context) {
f := &admin.UserForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
errList := global.Validator.ValidVar(c, id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -163,7 +163,7 @@ func (ct *User) Delete(c *gin.Context) {
response.Fail(c, 101, err.Error())
return
}
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
}
// UpdatePassword 修改密码
@@ -180,22 +180,22 @@ func (ct *User) Delete(c *gin.Context) {
func (ct *User) UpdatePassword(c *gin.Context) {
f := &admin.UserPasswordForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
u := service.AllService.UserService.InfoById(f.Id)
if u.Id == 0 {
response.Fail(c, 101, "信息不存在")
response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
return
}
err := service.AllService.UserService.UpdatePassword(u, f.Password)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)
@@ -237,11 +237,11 @@ func (ct *User) Current(c *gin.Context) {
func (ct *User) ChangeCurPwd(c *gin.Context) {
f := &admin.ChangeCurPasswordForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
@@ -249,12 +249,12 @@ func (ct *User) ChangeCurPwd(c *gin.Context) {
u := service.AllService.UserService.CurUser(c)
oldPwd := service.AllService.UserService.EncryptPassword(f.OldPassword)
if u.Password != oldPwd {
response.Fail(c, 101, "旧密码错误")
response.Fail(c, 101, response.TranslateMsg(c, "OldPasswordError"))
return
}
err := service.AllService.UserService.UpdatePassword(u, f.NewPassword)
if err != nil {
response.Fail(c, 101, "更新失败")
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
response.Success(c, nil)

View File

@@ -68,37 +68,30 @@ func (a *Ab) UpAb(c *gin.Context) {
abf := &requstform.AddressBookForm{}
err := c.ShouldBindJSON(&abf)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
abd := &requstform.AddressBookFormData{}
err = json.Unmarshal([]byte(abf.Data), abd)
if err != nil {
response.Error(c, "系统错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
tc := map[string]uint{}
err = json.Unmarshal([]byte(abd.TagColors), &tc)
if err != nil {
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
//fmt.Println(abd)
//for _, peer := range abd.Peers {
// fmt.Println(peer)
//}
user := service.AllService.UserService.CurUser(c)
err = service.AllService.AddressBookService.UpdateAddressBook(abd.Peers, user.Id)
if err != nil {
c.Abort()
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
tc := map[string]uint{}
err = json.Unmarshal([]byte(abd.TagColors), &tc)
if err != nil {
response.Error(c, "系统错误")
return
} else {
service.AllService.TagService.UpdateTags(user.Id, tc)
}
service.AllService.TagService.UpdateTags(user.Id, tc)
c.JSON(http.StatusOK, nil)
}
@@ -134,19 +127,19 @@ func (a *Ab) TagAdd(c *gin.Context) {
t := &model.Tag{}
err := c.ShouldBindJSON(t)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name)
if tag != nil && tag.Id != 0 {
response.Error(c, "已存在")
response.Error(c, response.TranslateMsg(c, "ItemExists"))
return
}
t.UserId = u.Id
err = service.AllService.TagService.Create(t)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
c.String(http.StatusOK, "")
@@ -166,24 +159,24 @@ func (a *Ab) TagRename(c *gin.Context) {
t := &requstform.TagRenameForm{}
err := c.ShouldBindJSON(t)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Old)
if tag == nil || tag.Id == 0 {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
return
}
ntag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.New)
if ntag != nil && ntag.Id != 0 {
response.Error(c, "已存在")
response.Error(c, response.TranslateMsg(c, "ItemExists"))
return
}
tag.Name = t.New
err = service.AllService.TagService.Update(tag)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
c.String(http.StatusOK, "")
@@ -203,19 +196,19 @@ func (a *Ab) TagUpdate(c *gin.Context) {
t := &requstform.TagColorForm{}
err := c.ShouldBindJSON(t)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name)
if tag == nil || tag.Id == 0 {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
return
}
tag.Color = t.Color
err = service.AllService.TagService.Update(tag)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
c.String(http.StatusOK, "")
@@ -235,7 +228,7 @@ func (a *Ab) TagDel(c *gin.Context) {
t := &[]string{}
err := c.ShouldBind(t)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
//fmt.Println(t)
@@ -243,12 +236,12 @@ func (a *Ab) TagDel(c *gin.Context) {
for _, name := range *t {
tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, name)
if tag == nil || tag.Id == 0 {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
return
}
err = service.AllService.TagService.Delete(tag)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
}
@@ -406,7 +399,7 @@ func (a *Ab) PeerAdd(c *gin.Context) {
f := &requstform.PersonalAddressBookForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Error(c, "参数错误"+err.Error())
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
fmt.Println(f)
@@ -415,7 +408,7 @@ func (a *Ab) PeerAdd(c *gin.Context) {
ab := f.ToAddressBook()
err = service.AllService.AddressBookService.AddAddressBook(ab)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
c.String(http.StatusOK, "")
@@ -436,19 +429,19 @@ func (a *Ab) PeerDel(c *gin.Context) {
f := &[]string{}
err := c.ShouldBind(f)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
u := service.AllService.UserService.CurUser(c)
for _, id := range *f {
ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, id)
if ab == nil || ab.RowId == 0 {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
return
}
err = service.AllService.AddressBookService.Delete(ab)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
}
@@ -472,22 +465,22 @@ func (a *Ab) PeerUpdate(c *gin.Context) {
f := &requstform.PersonalAddressBookForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
fmt.Println(f)
//fmt.Println(f)
//return
u := service.AllService.UserService.CurUser(c)
ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, f.Id)
if ab == nil || ab.RowId == 0 {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
return
}
nab := f.ToAddressBook()
nab.RowId = ab.RowId
err = service.AllService.AddressBookService.Update(nab)
if err != nil {
response.Error(c, "操作失败")
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
c.String(http.StatusOK, "")

View File

@@ -33,7 +33,7 @@ func (g *Group) Users(c *gin.Context) {
if !*u.IsAdmin {
gr := service.AllService.GroupService.InfoById(u.GroupId)
if gr.Type != model.GroupTypeShare {
response.Error(c, "不是管理员也不在分享组")
response.Error(c, response.TranslateMsg(c, "NoAccess"))
return
}
}
@@ -77,7 +77,7 @@ func (g *Group) Peers(c *gin.Context) {
if !*u.IsAdmin {
gr := service.AllService.GroupService.InfoById(u.GroupId)
if gr.Type != model.GroupTypeShare {
response.Error(c, "不是管理员也不在分享组")
response.Error(c, response.TranslateMsg(c, "NoAccess"))
return
}
}
@@ -96,15 +96,15 @@ func (g *Group) Peers(c *gin.Context) {
namesById[user.Id] = user.Username
userIds = append(userIds, user.Id)
}
peerList := service.AllService.AddressBookService.ListByUserIds(userIds, q.Page, q.PageSize)
peerList := service.AllService.PeerService.ListByUserIds(userIds, q.Page, q.PageSize)
var data []*apiResp.GroupPeerPayload
for _, ab := range peerList.AddressBooks {
uname, ok := namesById[ab.UserId]
for _, peer := range peerList.Peers {
uname, ok := namesById[peer.UserId]
if !ok {
uname = ""
}
pp := &apiResp.GroupPeerPayload{}
pp.FromAddressBook(ab, uname)
pp.FromPeer(peer, uname)
data = append(data, pp)
}

View File

@@ -35,5 +35,10 @@ func (i *Index) Index(c *gin.Context) {
// @Failure 500 {object} response.Response
// @Router /heartbeat [post]
func (i *Index) Heartbeat(c *gin.Context) {
//b := &gin.H{}
//err := c.BindJSON(b)
//body : &map[id:xxx modified_at:0 uuid:NGIxZTZjM2YtNmNkMy00YTMwLWFiNjQtMzQ0MTA0NGE5ZDgz ver:1.003e+06]
//fmt.Println(b, err, c.Request.Header)
//header : map[Accept:[*/*] Accept-Encoding:[gzip] Content-Length:[105] Content-Type:[application/json]]
c.JSON(http.StatusOK, gin.H{})
}

View File

@@ -30,11 +30,11 @@ func (l *Login) Login(c *gin.Context) {
err := c.ShouldBindJSON(f)
//fmt.Println(f)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
errList := global.Validator.ValidStruct(c, f)
if len(errList) > 0 {
response.Error(c, errList[0])
return
@@ -43,7 +43,7 @@ func (l *Login) Login(c *gin.Context) {
u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
if u.Id == 0 {
response.Error(c, "用户名或密码错误")
response.Error(c, response.TranslateMsg(c, "UsernameOrPasswordError"))
return
}
@@ -95,7 +95,7 @@ func (l *Login) LoginOptions(c *gin.Context) {
}
common, err := json.Marshal(oidcItems)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "SystemError")+err.Error())
return
}
var res []string

View File

@@ -29,17 +29,17 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
f := &api.OidcAuthRequest{}
err := c.ShouldBindJSON(&f)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError"))
return
}
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
if err != nil {
response.Error(c, err.Error())
response.Error(c, response.TranslateMsg(c, err.Error()))
return
}
@@ -72,12 +72,12 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
q := &api.OidcAuthQuery{}
err := c.ShouldBindQuery(q)
if err != nil {
response.Error(c, "参数错误")
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
v := service.AllService.OauthService.GetOauthCache(q.Code)
if v == nil {
response.Error(c, "授权已过期,请重新授权")
response.Error(c, response.TranslateMsg(c, "OauthExpired"))
return
}
if v.UserId == 0 {
@@ -87,24 +87,20 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
}
u := service.AllService.UserService.InfoById(v.UserId)
//fmt.Println("auth success u", u)
if u.Id > 0 {
service.AllService.OauthService.DeleteOauthCache(q.Code)
ut := service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
Client: v.DeviceType,
Uuid: v.Uuid,
Ip: c.ClientIP(),
Type: model.LoginLogTypeOauth,
Platform: v.DeviceOs,
})
c.JSON(http.StatusOK, apiResp.LoginRes{
AccessToken: ut.Token,
Type: "access_token",
User: *(&apiResp.UserPayload{}).FromUser(u),
})
return
}
response.Error(c, "用户不存在")
service.AllService.OauthService.DeleteOauthCache(q.Code)
ut := service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
Client: v.DeviceType,
Uuid: v.Uuid,
Ip: c.ClientIP(),
Type: model.LoginLogTypeOauth,
Platform: v.DeviceOs,
})
c.JSON(http.StatusOK, apiResp.LoginRes{
AccessToken: ut.Token,
Type: "access_token",
User: *(&apiResp.UserPayload{}).FromUser(u),
})
}
// OauthCallback 回调
@@ -119,7 +115,7 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
func (o *Oauth) OauthCallback(c *gin.Context) {
state := c.Query("state")
if state == "" {
c.String(http.StatusInternalServerError, "state为空")
c.String(http.StatusInternalServerError, response.TranslateParamMsg(c, "ParamIsEmpty", "state"))
return
}
@@ -127,7 +123,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
//从缓存中获取
v := service.AllService.OauthService.GetOauthCache(cacheKey)
if v == nil {
c.String(http.StatusInternalServerError, "授权已过期,请重新授权")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthExpired"))
return
}
@@ -138,34 +134,34 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
code := c.Query("code")
err, userData := service.AllService.OauthService.GithubCallback(code)
if err != nil {
c.String(http.StatusInternalServerError, "授权失败:"+err.Error())
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
return
}
if ac == service.OauthActionTypeBind {
//fmt.Println("bind", ty, userData)
utr := service.AllService.OauthService.UserThirdInfo(ty, strconv.Itoa(userData.Id))
if utr.UserId > 0 {
c.String(http.StatusInternalServerError, "已经绑定其他账号")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
return
}
//绑定
u := service.AllService.UserService.InfoById(v.UserId)
if u == nil {
c.String(http.StatusInternalServerError, "用户不存在")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
return
}
//绑定github
err = service.AllService.OauthService.BindGithubUser(strconv.Itoa(userData.Id), userData.Login, v.UserId)
if err != nil {
c.String(http.StatusInternalServerError, "绑定失败")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
return
}
c.String(http.StatusOK, "绑定成功")
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
return
} else if ac == service.OauthActionTypeLogin {
//登录
if v.UserId != 0 {
c.String(http.StatusInternalServerError, "授权已经成功")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
return
}
u := service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
@@ -183,19 +179,16 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
//自动注册
u = service.AllService.UserService.RegisterByGithub(userData.Login, strconv.Itoa(userData.Id))
if u.Id == 0 {
c.String(http.StatusInternalServerError, "注册失败")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
return
}
}
v.UserId = u.Id
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
c.String(http.StatusOK, "授权成功")
c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
return
}
//返回js
c.Header("Content-Type", "text/html; charset=utf-8")
c.String(http.StatusOK, "授权错误")
}
@@ -203,7 +196,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
code := c.Query("code")
err, userData := service.AllService.OauthService.GoogleCallback(code)
if err != nil {
c.String(http.StatusInternalServerError, "授权失败:"+err.Error())
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
return
}
//将空格替换成_
@@ -212,26 +205,26 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
//fmt.Println("bind", ty, userData)
utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Email)
if utr.UserId > 0 {
c.String(http.StatusInternalServerError, "已经绑定其他账号")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
return
}
//绑定
u := service.AllService.UserService.InfoById(v.UserId)
if u == nil {
c.String(http.StatusInternalServerError, "用户不存在")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
return
}
//绑定
err = service.AllService.OauthService.BindGoogleUser(userData.Email, googleName, v.UserId)
if err != nil {
c.String(http.StatusInternalServerError, "绑定失败")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
return
}
c.String(http.StatusOK, "绑定成功")
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
return
} else if ac == service.OauthActionTypeLogin {
if v.UserId != 0 {
c.String(http.StatusInternalServerError, "授权已经成功")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
return
}
u := service.AllService.UserService.InfoByGoogleEmail(userData.Email)
@@ -250,17 +243,17 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
//自动注册
u = service.AllService.UserService.RegisterByGoogle(googleName, userData.Email)
if u.Id == 0 {
c.String(http.StatusInternalServerError, "注册失败")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
return
}
}
v.UserId = u.Id
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
c.String(http.StatusOK, "授权成功")
c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
return
}
}
c.String(http.StatusInternalServerError, "授权配置错误,请联系管理员")
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError"))
}

View File

@@ -27,7 +27,7 @@ func (p *Peer) SysInfo(c *gin.Context) {
f := &requstform.PeerForm{}
err := c.ShouldBindBodyWith(f, binding.JSON)
if err != nil {
response.Error(c, err.Error())
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
return
}
@@ -36,7 +36,7 @@ func (p *Peer) SysInfo(c *gin.Context) {
pe = f.ToPeer()
err = service.AllService.PeerService.Create(pe)
if err != nil {
response.Error(c, err.Error())
response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
return
}
}

View File

@@ -7,7 +7,7 @@ import (
func RustAuth() gin.HandlerFunc {
return func(c *gin.Context) {
//fmt.Println(c.Request.Header)
//获取HTTP_AUTHORIZATION
token := c.GetHeader("Authorization")
if token == "" {

View File

@@ -17,11 +17,11 @@ type AddressBookForm struct {
Hash string `json:"hash"`
UserId uint `json:"user_id"`
ForceAlwaysRelay bool `json:"forceAlwaysRelay"`
RdpPort string `json:"rdp_port"`
RdpUsername string `json:"rdp_username"`
RdpPort string `json:"rdpPort"`
RdpUsername string `json:"rdpUsername"`
Online bool `json:"online"`
LoginName string `json:"login_name" `
SameServer bool `json:"same_server"`
LoginName string `json:"loginName" `
SameServer bool `json:"sameServer"`
}
func (a AddressBookForm) ToAddressBook() *model.AddressBook {

View File

@@ -8,7 +8,7 @@ type UserForm struct {
Id uint `json:"id"`
Username string `json:"username" validate:"required,gte=4,lte=10"`
//Password string `json:"password" validate:"required,gte=4,lte=20"`
Nickname string `json:"nickname" validate:"required"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
GroupId uint `json:"group_id" validate:"required"`
IsAdmin *bool `json:"is_admin" `

View File

@@ -59,7 +59,7 @@ func (gpp *GroupPeerPayload) FromAddressBook(a *model.AddressBook, username stri
gpp.UserName = username
}
func (gpp *GroupPeerPayload) FromPeer(p *model.Peer) {
func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string) {
gpp.Id = p.Id
gpp.Info = &PeerPayloadInfo{
DeviceName: p.Hostname,
@@ -67,5 +67,5 @@ func (gpp *GroupPeerPayload) FromPeer(p *model.Peer) {
Username: p.Username,
}
gpp.Note = ""
gpp.UserName = p.User.Username
gpp.UserName = username
}

View File

@@ -1,7 +1,10 @@
package response
import (
"Gwen/global"
"fmt"
"github.com/gin-gonic/gin"
"github.com/nicksnyder/go-i18n/v2/i18n"
"net/http"
)
@@ -51,3 +54,48 @@ type ServerConfigResponse struct {
RelayServer string `json:"relay_server"`
ApiServer string `json:"api_server"`
}
func TranslateMsg(c *gin.Context, messageId string) string {
localizer := global.Localizer(c)
errMsg, err := localizer.LocalizeMessage(&i18n.Message{
ID: messageId,
})
if err != nil {
global.Logger.Warn("LocalizeMessage Error: " + err.Error())
errMsg = messageId
}
return errMsg
}
func TranslateTempMsg(c *gin.Context, messageId string, templateData map[string]interface{}) string {
localizer := global.Localizer(c)
errMsg, err := localizer.Localize(&i18n.LocalizeConfig{
DefaultMessage: &i18n.Message{
ID: messageId,
},
TemplateData: templateData,
})
if err != nil {
global.Logger.Warn("LocalizeMessage Error: " + err.Error())
errMsg = messageId
}
return errMsg
}
func TranslateParamMsg(c *gin.Context, messageId string, params ...string) string {
localizer := global.Localizer(c)
templateData := make(map[string]interface{})
for i, v := range params {
k := fmt.Sprintf("P%d", i)
templateData[k] = v
}
errMsg, err := localizer.Localize(&i18n.LocalizeConfig{
DefaultMessage: &i18n.Message{
ID: messageId,
},
TemplateData: templateData,
})
if err != nil {
global.Logger.Warn("LocalizeMessage Error: " + err.Error())
errMsg = messageId
}
return errMsg
}

111
resources/i18n/en.toml Normal file
View File

@@ -0,0 +1,111 @@
[Test]
description = "test"
one = "test1 "
other = "Test2 {{.P0}}"
[ParamsError]
description = "Params validation failed."
one = "Params validation failed."
other = "Params validation failed."
[OperationFailed]
description = "OperationFailed."
one = "the operation failed."
other = "the operation failed."
[OperationSuccess]
description = "OperationSuccess."
one = "the operation success."
other = "the operation success."
[ItemExists]
description = "Item already exists."
one = "Item already exists."
other = "Item already exists."
[ItemNotFound]
description = "Item not found."
one = "Item not found."
other = "Item not found."
[NoAccess]
description = "No access."
one = "No access."
other = "No access."
[UsernameOrPasswordError]
description = "Username or password error."
one = "Username or password error."
other = "Username or password error."
[SystemError]
description = "System error."
one = "System error."
other = "System error."
[ConfigNotFound]
description = "Config not found."
one = "Config not found."
other = "Config not found."
[OauthExpired]
description = "Oauth expired."
one = "Oauth expired, please try again."
other = "Oauth expired,please try again."
[OauthFailed]
description = "Oauth failed."
one = "Oauth failed."
other = "Oauth failed."
[OauthHasBindOtherUser]
description = "Oauth has bind other user."
one = "Oauth has bind other user."
other = "Oauth has bind other user."
[ParamIsEmpty]
description = "Param is empty."
one = "{{.P0}} is empty."
other = "{{.P0}} is empty."
[BindFail]
description = "Bind fail."
one = "Bind fail."
other = "Bind fail."
[BindSuccess]
description = "Bind success."
one = "Bind success."
other = "Bind success."
[OauthHasBeenSuccess]
description = "Oauth has been success."
one = "Oauth has been success."
other = "Oauth has been success."
[OauthSuccess]
description = "Oauth success."
one = "Oauth success."
other = "Oauth success."
[OauthRegisterSuccess]
description = "Oauth register success."
one = "Oauth register success."
other = "Oauth register success."
[OauthRegisterFailed]
description = "Oauth register failed."
one = "Oauth register failed."
other = "Oauth register failed."
[GetOauthTokenError]
description = "Get oauth token error."
one = "Get oauth token error."
other = "Get oauth token error."
[GetOauthUserInfoError]
description = "Get oauth user info error."
one = "Get oauth user info error."
other = "Get oauth user info error."
[DecodeOauthUserInfoError]
description = "Decode oauth user info error."
one = "Decode oauth user info error."
other = "Decode oauth user info error."
[OldPasswordError]
description = "Old password error."
one = "Old password error."
other = "Old password error."

112
resources/i18n/zh_CN.toml Normal file
View File

@@ -0,0 +1,112 @@
[Test]
description = "test"
one = "测试1 {{.P0}}"
other = "测试2 {{.P0}}"
[ParamsError]
description = "Params validation failed."
one = "参数错误。"
other = "参数错误。"
[OperationFailed]
description = "OperationFailed."
one = "操作失败。"
other = "操作失败。"
[OperationSuccess]
description = "OperationSuccess."
one = "操作成功。"
other = "操作成功。"
[ItemExists]
description = "Item already exists."
one = "数据已存在。"
other = "数据已存在。"
[ItemNotFound]
description = "Item not found."
one = "数据不存在。"
other = "数据不存在。"
[NoAccess]
description = "No access."
one = "无权限。"
other = "无权限。"
[UsernameOrPasswordError]
description = "Username or password error."
one = "用户名或密码错误。"
other = "用户名或密码错误。"
[SystemError]
description = "System error."
one = "系统错误。"
other = "系统错误。"
[ConfigNotFound]
description = "Config not found."
one = "配置不存在。"
other = "配置不存在。"
#授权过期
[OauthExpired]
description = "Oauth expired."
one = "授权过期,请重新授权。"
other = "授权过期,请重新授权。"
[OauthFailed]
description = "Oauth failed."
one = "授权失败。"
other = "授权失败。"
[OauthHasBindOtherUser]
description = "Oauth has bind other user."
one = "授权已绑定其他用户。"
other = "授权已绑定其他用户。"
[ParamIsEmpty]
description = "Param is empty."
one = "{{.P0}} 为空。"
other = "{{.P0}} 为空。"
[BindFail]
description = "Bind fail."
one = "绑定失败。"
other = "绑定失败。"
[BindSuccess]
description = "Bind success."
one = "绑定成功。"
other = "绑定成功。"
[OauthHasBeenSuccess]
description = "Oauth has been success."
one = "授权已成功。"
other = "授权已成功。"
[OauthSuccess]
description = "Oauth success."
one = "授权成功。"
other = "授权成功。"
[OauthRegisterSuccess]
description = "Oauth register success."
one = "授权注册成功。"
other = "授权注册成功。"
[OauthRegisterFailed]
description = "Oauth register failed."
one = "授权注册失败。"
other = "授权注册失败。"
[GetOauthTokenError]
description = "Get oauth token error."
one = "获取授权token失败。"
other = "获取授权token失败。"
[GetOauthUserInfoError]
description = "Get oauth user info error."
one = "获取授权用户信息失败。"
other = "获取授权用户信息失败。"
[DecodeOauthUserInfoError]
description = "Decode oauth user info error."
one = "解析授权用户信息失败。"
other = "解析授权用户信息失败。"
[OldPasswordError]
description = "Old password error."
one = "旧密码错误。"
other = "旧密码错误。"

View File

@@ -133,7 +133,7 @@ func (os *OauthService) BeginAuth(op string) (error error, code, url string) {
return err, code, conf.AuthCodeURL(code)
}
return errors.New("op错误"), code, ""
return err, code, ""
}
// GetOauthConfig 获取配置
@@ -141,7 +141,7 @@ func (os *OauthService) GetOauthConfig(op string) (error, *oauth2.Config) {
if op == model.OauthTypeGithub {
g := os.InfoByOp(model.OauthTypeGithub)
if g.Id == 0 || g.ClientId == "" || g.ClientSecret == "" || g.RedirectUrl == "" {
return errors.New("配置不存在"), nil
return errors.New("ConfigNotFound"), nil
}
return nil, &oauth2.Config{
ClientID: g.ClientId,
@@ -154,7 +154,7 @@ func (os *OauthService) GetOauthConfig(op string) (error, *oauth2.Config) {
if op == model.OauthTypeGoogle {
g := os.InfoByOp(model.OauthTypeGoogle)
if g.Id == 0 || g.ClientId == "" || g.ClientSecret == "" || g.RedirectUrl == "" {
return errors.New("配置不存在"), nil
return errors.New("ConfigNotFound"), nil
}
return nil, &oauth2.Config{
ClientID: g.ClientId,
@@ -164,7 +164,7 @@ func (os *OauthService) GetOauthConfig(op string) (error, *oauth2.Config) {
Scopes: []string{"https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"},
}
}
return errors.New("op错误"), nil
return errors.New("ConfigNotFound"), nil
}
func (os *OauthService) GithubCallback(code string) (error error, userData *GithubUserdata) {
@@ -175,7 +175,7 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith
token, err := oauthConfig.Exchange(context.Background(), code)
if err != nil {
global.Logger.Warn(fmt.Printf("oauthConfig.Exchange() failed: %s\n", err))
error = errors.New("获取token失败")
error = errors.New("GetOauthTokenError")
return
}
@@ -184,7 +184,7 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith
resp, err := client.Get("https://api.github.com/user")
if err != nil {
global.Logger.Warn("failed getting user info: %s\n", err)
error = errors.New("获取user info失败")
error = errors.New("GetOauthUserInfoError")
return
}
defer func(Body io.ReadCloser) {
@@ -197,7 +197,7 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith
// 在这里处理 GitHub 用户信息
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
global.Logger.Warn("failed decoding user info: %s\n", err)
error = errors.New("解析user info失败")
error = errors.New("DecodeOauthUserInfoError")
return
}
return
@@ -208,7 +208,7 @@ func (os *OauthService) GoogleCallback(code string) (error error, userData *Goog
token, err := oauthConfig.Exchange(context.Background(), code)
if err != nil {
global.Logger.Warn(fmt.Printf("oauthConfig.Exchange() failed: %s\n", err))
error = errors.New("获取token失败")
error = errors.New("GetOauthTokenError")
return
}
// 创建 HTTP 客户端,并将 access_token 添加到 Authorization 头中
@@ -216,7 +216,7 @@ func (os *OauthService) GoogleCallback(code string) (error error, userData *Goog
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
global.Logger.Warn("failed getting user info: %s\n", err)
error = errors.New("获取user info失败: " + err.Error())
error = errors.New("GetOauthUserInfoError")
return
}
defer func(Body io.ReadCloser) {
@@ -228,7 +228,7 @@ func (os *OauthService) GoogleCallback(code string) (error error, userData *Goog
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
global.Logger.Warn("failed decoding user info: %s\n", err)
error = errors.New("解析user info失败:" + err.Error())
error = errors.New("DecodeOauthUserInfoError")
return
}
return
@@ -258,7 +258,13 @@ func (os *OauthService) BindOauthUser(thirdType, openid, username string, userId
}
func (os *OauthService) UnBindGithubUser(userid uint) error {
return global.DB.Where("user_id = ? and third_type = ?", userid, model.OauthTypeGithub).Delete(&model.UserThird{}).Error
return os.UnBindThird(model.OauthTypeGithub, userid)
}
func (os *OauthService) UnBindGoogleUser(userid uint) error {
return os.UnBindThird(model.OauthTypeGoogle, userid)
}
func (os *OauthService) UnBindThird(thirdType string, userid uint) error {
return global.DB.Where("user_id = ? and third_type = ?", userid, thirdType).Delete(&model.UserThird{}).Error
}
// InfoById 根据id取用户信息

View File

@@ -15,24 +15,38 @@ func (ps *PeerService) FindById(id string) *model.Peer {
global.DB.Where("id = ?", id).First(p)
return p
}
func (ps *PeerService) FindByUuid(uuid string) *model.Peer {
p := &model.Peer{}
global.DB.Where("uuid = ?", uuid).First(p)
return p
}
func (ps *PeerService) InfoByRowId(id uint) *model.Peer {
p := &model.Peer{}
global.DB.Where("row_id = ?", id).First(p)
return p
}
//// ListByUserIds 根据用户id取列表
//func (ps *PeerService) ListByUserIds(userIds []uint, page, pageSize uint) (res *model.PeerList) {
// res = &model.PeerList{}
// res.Page = int64(page)
// res.PageSize = int64(pageSize)
// tx := global.DB.Model(&model.Peer{}).Preload("User")
// tx.Where("user_id in (?)", userIds)
// tx.Count(&res.Total)
// tx.Scopes(Paginate(page, pageSize))
// tx.Find(&res.Peers)
// return
//}
// UuidBindUserId 绑定用户id
func (ps *PeerService) UuidBindUserId(uuid string, userId uint) {
peer := ps.FindByUuid(uuid)
if peer.RowId > 0 {
peer.UserId = userId
ps.Update(peer)
}
}
// ListByUserIds 根据用户id取列表
func (ps *PeerService) ListByUserIds(userIds []uint, page, pageSize uint) (res *model.PeerList) {
res = &model.PeerList{}
res.Page = int64(page)
res.PageSize = int64(pageSize)
tx := global.DB.Model(&model.Peer{})
tx.Where("user_id in (?)", userIds)
tx.Count(&res.Total)
tx.Scopes(Paginate(page, pageSize))
tx.Find(&res.Peers)
return
}
func (ps *PeerService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.PeerList) {
res = &model.PeerList{}

View File

@@ -66,6 +66,9 @@ func (us *UserService) Login(u *model.User, llog *model.LoginLog) *model.UserTok
}
global.DB.Create(ut)
global.DB.Create(llog)
if llog.Uuid != "" {
AllService.PeerService.UuidBindUserId(llog.Uuid, u.Id)
}
return ut
}