Просмотр исходного кода

upgrade: init by i18n
add: batch delete peer
add: batch peer to addressbook

ljw 1 год назад
Родитель
Сommit
609dfaeea0

+ 17 - 5
cmd/apimain.go

@@ -23,6 +23,7 @@ import (
23 23
 	"github.com/go-redis/redis/v8"
24 24
 	"github.com/nicksnyder/go-i18n/v2/i18n"
25 25
 	"golang.org/x/text/language"
26
+	nethttp "net/http"
26 27
 	"reflect"
27 28
 )
28 29
 
@@ -47,6 +48,8 @@ func main() {
47 48
 		ReportCaller: global.Config.Logger.ReportCaller,
48 49
 	})
49 50
 
51
+	InitI18n()
52
+
50 53
 	//redis
51 54
 	global.Redis = redis.NewClient(&redis.Options{
52 55
 		Addr:     global.Config.Redis.Addr,
@@ -103,7 +106,6 @@ func main() {
103 106
 	//locker
104 107
 	global.Lock = lock.NewLocal()
105 108
 
106
-	InitI18n()
107 109
 	//gin
108 110
 	http.ApiInit()
109 111
 
@@ -198,7 +200,7 @@ func getTranslatorForLang(lang string) ut.Translator {
198 200
 	}
199 201
 }
200 202
 func DatabaseAutoUpdate() {
201
-	version := 126
203
+	version := 212
202 204
 
203 205
 	db := global.DB
204 206
 
@@ -268,13 +270,23 @@ func Migrate(version uint) {
268 270
 	var vc int64
269 271
 	global.DB.Model(&model.Version{}).Count(&vc)
270 272
 	if vc == 1 {
273
+		localizer := global.Localizer(&gin.Context{
274
+			Request: &nethttp.Request{},
275
+		})
276
+		defaultGroup, _ := localizer.LocalizeMessage(&i18n.Message{
277
+			ID: "DefaultGroup",
278
+		})
271 279
 		group := &model.Group{
272
-			Name: "默认组",
280
+			Name: defaultGroup,
273 281
 			Type: model.GroupTypeDefault,
274 282
 		}
275 283
 		service.AllService.GroupService.Create(group)
284
+
285
+		shareGroup, _ := localizer.LocalizeMessage(&i18n.Message{
286
+			ID: "ShareGroup",
287
+		})
276 288
 		groupShare := &model.Group{
277
-			Name: "共享组",
289
+			Name: shareGroup,
278 290
 			Type: model.GroupTypeShare,
279 291
 		}
280 292
 		service.AllService.GroupService.Create(groupShare)
@@ -282,7 +294,7 @@ func Migrate(version uint) {
282 294
 		is_admin := true
283 295
 		admin := &model.User{
284 296
 			Username: "admin",
285
-			Nickname: "管理员",
297
+			Nickname: "Admin",
286 298
 			Status:   model.COMMON_STATUS_ENABLE,
287 299
 			IsAdmin:  &is_admin,
288 300
 			GroupId:  1,

+ 3 - 0
docs/admin/admin_docs.go

@@ -2759,6 +2759,9 @@ const docTemplateadmin = `{
2759 2759
                 "id": {
2760 2760
                     "type": "string"
2761 2761
                 },
2762
+                "last_online_time": {
2763
+                    "type": "integer"
2764
+                },
2762 2765
                 "memory": {
2763 2766
                     "type": "string"
2764 2767
                 },

+ 3 - 0
docs/admin/admin_swagger.json

@@ -2752,6 +2752,9 @@
2752 2752
                 "id": {
2753 2753
                     "type": "string"
2754 2754
                 },
2755
+                "last_online_time": {
2756
+                    "type": "integer"
2757
+                },
2755 2758
                 "memory": {
2756 2759
                     "type": "string"
2757 2760
                 },

+ 2 - 0
docs/admin/admin_swagger.yaml

@@ -346,6 +346,8 @@ definitions:
346 346
         type: string
347 347
       id:
348 348
         type: string
349
+      last_online_time:
350
+        type: integer
349 351
       memory:
350 352
         type: string
351 353
       os:

+ 68 - 0
http/controller/admin/addressBook.go

@@ -4,6 +4,7 @@ import (
4 4
 	"Gwen/global"
5 5
 	"Gwen/http/request/admin"
6 6
 	"Gwen/http/response"
7
+	"Gwen/model"
7 8
 	"Gwen/service"
8 9
 	_ "encoding/json"
9 10
 	"github.com/gin-gonic/gin"
@@ -69,6 +70,12 @@ func (ct *AddressBook) Create(c *gin.Context) {
69 70
 	if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 {
70 71
 		t.UserId = u.Id
71 72
 	}
73
+	ex := service.AllService.AddressBookService.InfoByUserIdAndId(t.UserId, t.Id)
74
+	if ex.RowId > 0 {
75
+		response.Fail(c, 101, response.TranslateMsg(c, "ItemExist"))
76
+		return
77
+	}
78
+
72 79
 	err := service.AllService.AddressBookService.Create(t)
73 80
 	if err != nil {
74 81
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
@@ -77,6 +84,58 @@ func (ct *AddressBook) Create(c *gin.Context) {
77 84
 	response.Success(c, u)
78 85
 }
79 86
 
87
+// BatchCreate 批量创建地址簿
88
+// @Tags 地址簿
89
+// @Summary 批量创建地址簿
90
+// @Description 批量创建地址簿
91
+// @Accept  json
92
+// @Produce  json
93
+// @Param body body admin.AddressBookForm true "地址簿信息"
94
+// @Success 200 {object} response.Response{data=model.AddressBook}
95
+// @Failure 500 {object} response.Response
96
+// @Router /admin/address_book/create [post]
97
+// @Security token
98
+func (ct *AddressBook) BatchCreate(c *gin.Context) {
99
+	f := &admin.AddressBookForm{}
100
+	if err := c.ShouldBindJSON(f); err != nil {
101
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
102
+		return
103
+	}
104
+	errList := global.Validator.ValidStruct(c, f)
105
+	if len(errList) > 0 {
106
+		response.Fail(c, 101, errList[0])
107
+		return
108
+	}
109
+
110
+	//创建标签
111
+	for _, fu := range f.UserIds {
112
+		if fu == 0 {
113
+			continue
114
+		}
115
+		for _, ft := range f.Tags {
116
+			exTag := service.AllService.TagService.InfoByUserIdAndName(fu, ft)
117
+			if exTag.Id == 0 {
118
+				service.AllService.TagService.Create(&model.Tag{
119
+					UserId: fu,
120
+					Name:   ft,
121
+				})
122
+			}
123
+		}
124
+	}
125
+	ts := f.ToAddressBooks()
126
+	for _, t := range ts {
127
+		if t.UserId == 0 {
128
+			continue
129
+		}
130
+		ex := service.AllService.AddressBookService.InfoByUserIdAndId(t.UserId, t.Id)
131
+		if ex.RowId == 0 {
132
+			service.AllService.AddressBookService.Create(t)
133
+		}
134
+	}
135
+
136
+	response.Success(c, nil)
137
+}
138
+
80 139
 // List 列表
81 140
 // @Tags 地址簿
82 141
 // @Summary 地址簿列表
@@ -102,9 +161,18 @@ func (ct *AddressBook) List(c *gin.Context) {
102 161
 		query.UserId = int(u.Id)
103 162
 	}
104 163
 	res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
164
+		if query.Id != "" {
165
+			tx.Where("id like ?", "%"+query.Id+"%")
166
+		}
105 167
 		if query.UserId > 0 {
106 168
 			tx.Where("user_id = ?", query.UserId)
107 169
 		}
170
+		if query.Username != "" {
171
+			tx.Where("username like ?", "%"+query.Username+"%")
172
+		}
173
+		if query.Hostname != "" {
174
+			tx.Where("hostname like ?", "%"+query.Hostname+"%")
175
+		}
108 176
 	})
109 177
 	response.Success(c, res)
110 178
 }

+ 43 - 2
http/controller/admin/peer.go

@@ -6,7 +6,9 @@ import (
6 6
 	"Gwen/http/response"
7 7
 	"Gwen/service"
8 8
 	"github.com/gin-gonic/gin"
9
+	"gorm.io/gorm"
9 10
 	"strconv"
11
+	"time"
10 12
 )
11 13
 
12 14
 type Peer struct {
@@ -74,17 +76,27 @@ func (ct *Peer) Create(c *gin.Context) {
74 76
 // @Produce  json
75 77
 // @Param page query int false "页码"
76 78
 // @Param page_size query int false "页大小"
79
+// @Param time_ago query int false "时间"
77 80
 // @Success 200 {object} response.Response{data=model.PeerList}
78 81
 // @Failure 500 {object} response.Response
79 82
 // @Router /admin/peer/list [get]
80 83
 // @Security token
81 84
 func (ct *Peer) List(c *gin.Context) {
82
-	query := &admin.PageQuery{}
85
+	query := &admin.PeerQuery{}
83 86
 	if err := c.ShouldBindQuery(query); err != nil {
84 87
 		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
85 88
 		return
86 89
 	}
87
-	res := service.AllService.PeerService.List(query.Page, query.PageSize, nil)
90
+	res := service.AllService.PeerService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
91
+		if query.TimeAgo > 0 {
92
+			lt := time.Now().Unix() - int64(query.TimeAgo)
93
+			tx.Where("last_online_time < ?", lt)
94
+		}
95
+		if query.TimeAgo < 0 {
96
+			lt := time.Now().Unix() + int64(query.TimeAgo)
97
+			tx.Where("last_online_time > ?", lt)
98
+		}
99
+	})
88 100
 	response.Success(c, res)
89 101
 }
90 102
 
@@ -158,3 +170,32 @@ func (ct *Peer) Delete(c *gin.Context) {
158 170
 	}
159 171
 	response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
160 172
 }
173
+
174
+// BatchDelete 批量删除
175
+// @Tags 设备
176
+// @Summary 批量设备删除
177
+// @Description 批量设备删除
178
+// @Accept  json
179
+// @Produce  json
180
+// @Param body body admin.PeerBatchDeleteForm true "设备id"
181
+// @Success 200 {object} response.Response
182
+// @Failure 500 {object} response.Response
183
+// @Router /admin/peer/delete [post]
184
+// @Security token
185
+func (ct *Peer) BatchDelete(c *gin.Context) {
186
+	f := &admin.PeerBatchDeleteForm{}
187
+	if err := c.ShouldBindJSON(f); err != nil {
188
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
189
+		return
190
+	}
191
+	if len(f.RowIds) == 0 {
192
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
193
+		return
194
+	}
195
+	err := service.AllService.PeerService.BatchDelete(f.RowIds)
196
+	if err != nil {
197
+		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
198
+		return
199
+	}
200
+	response.Success(c, nil)
201
+}

+ 20 - 5
http/controller/api/index.go

@@ -1,9 +1,12 @@
1 1
 package api
2 2
 
3 3
 import (
4
+	requstform "Gwen/http/request/api"
4 5
 	"Gwen/http/response"
6
+	"Gwen/service"
5 7
 	"github.com/gin-gonic/gin"
6 8
 	"net/http"
9
+	"time"
7 10
 )
8 11
 
9 12
 type Index struct {
@@ -35,10 +38,22 @@ func (i *Index) Index(c *gin.Context) {
35 38
 // @Failure 500 {object} response.Response
36 39
 // @Router /heartbeat [post]
37 40
 func (i *Index) Heartbeat(c *gin.Context) {
38
-	//b := &gin.H{}
39
-	//err := c.BindJSON(b)
40
-	//body : &map[id:xxx modified_at:0 uuid:NGIxZTZjM2YtNmNkMy00YTMwLWFiNjQtMzQ0MTA0NGE5ZDgz ver:1.003e+06]
41
-	//fmt.Println(b, err, c.Request.Header)
42
-	//header : map[Accept:[*/*] Accept-Encoding:[gzip] Content-Length:[105] Content-Type:[application/json]]
41
+	info := &requstform.PeerInfoInHeartbeat{}
42
+	err := c.ShouldBindJSON(info)
43
+	if err != nil {
44
+		c.JSON(http.StatusOK, gin.H{})
45
+		return
46
+	}
47
+	if info.Uuid == "" {
48
+		c.JSON(http.StatusOK, gin.H{})
49
+		return
50
+	}
51
+	peer := service.AllService.PeerService.FindByUuid(info.Uuid)
52
+	if peer == nil {
53
+		c.JSON(http.StatusOK, gin.H{})
54
+		return
55
+	}
56
+	peer.LastOnlineTime = time.Now().Unix()
57
+	service.AllService.PeerService.Update(peer)
43 58
 	c.JSON(http.StatusOK, gin.H{})
44 59
 }

+ 33 - 2
http/request/admin/addressBook.go

@@ -16,6 +16,7 @@ type AddressBookForm struct {
16 16
 	Tags             []string `json:"tags"`
17 17
 	Hash             string   `json:"hash"`
18 18
 	UserId           uint     `json:"user_id"`
19
+	UserIds          []uint   `json:"user_ids"`
19 20
 	ForceAlwaysRelay bool     `json:"forceAlwaysRelay"`
20 21
 	RdpPort          string   `json:"rdpPort"`
21 22
 	RdpUsername      string   `json:"rdpUsername"`
@@ -48,9 +49,39 @@ func (a AddressBookForm) ToAddressBook() *model.AddressBook {
48 49
 	}
49 50
 
50 51
 }
52
+func (a AddressBookForm) ToAddressBooks() []*model.AddressBook {
53
+	//tags转换
54
+	tags, _ := json.Marshal(a.Tags)
55
+
56
+	abs := make([]*model.AddressBook, 0, len(a.UserIds))
57
+	for _, userId := range a.UserIds {
58
+		abs = append(abs, &model.AddressBook{
59
+			RowId:            a.RowId,
60
+			Id:               a.Id,
61
+			Username:         a.Username,
62
+			Password:         a.Password,
63
+			Hostname:         a.Hostname,
64
+			Alias:            a.Alias,
65
+			Platform:         a.Platform,
66
+			Tags:             tags,
67
+			Hash:             a.Hash,
68
+			UserId:           userId,
69
+			ForceAlwaysRelay: a.ForceAlwaysRelay,
70
+			RdpPort:          a.RdpPort,
71
+			RdpUsername:      a.RdpUsername,
72
+			Online:           a.Online,
73
+			LoginName:        a.LoginName,
74
+			SameServer:       a.SameServer,
75
+		})
76
+	}
77
+	return abs
78
+}
51 79
 
52 80
 type AddressBookQuery struct {
53
-	UserId int `form:"user_id"`
54
-	IsMy   int `form:"is_my"`
81
+	UserId   int    `form:"user_id"`
82
+	IsMy     int    `form:"is_my"`
83
+	Username string `form:"username"`
84
+	Hostname string `form:"hostname"`
85
+	Id       string `form:"id"`
55 86
 	PageQuery
56 87
 }

+ 9 - 0
http/request/admin/peer.go

@@ -14,6 +14,10 @@ type PeerForm struct {
14 14
 	Version  string `json:"version"`
15 15
 }
16 16
 
17
+type PeerBatchDeleteForm struct {
18
+	RowIds []uint `json:"row_ids" validate:"required"`
19
+}
20
+
17 21
 // ToPeer
18 22
 func (f *PeerForm) ToPeer() *model.Peer {
19 23
 	return &model.Peer{
@@ -28,3 +32,8 @@ func (f *PeerForm) ToPeer() *model.Peer {
28 32
 		Version:  f.Version,
29 33
 	}
30 34
 }
35
+
36
+type PeerQuery struct {
37
+	PageQuery
38
+	TimeAgo int `json:"time_ago" form:"time_ago"`
39
+}

+ 6 - 0
http/request/api/peer.go

@@ -71,3 +71,9 @@ type TagColorForm struct {
71 71
 	Name  string `json:"name"`
72 72
 	Color uint   `json:"color"`
73 73
 }
74
+
75
+type PeerInfoInHeartbeat struct {
76
+	Id   string `json:"id"`
77
+	Uuid string `json:"uuid"`
78
+	Ver  int    `json:"ver"`
79
+}

+ 6 - 0
http/router/admin.go

@@ -93,6 +93,9 @@ func AddressBookBind(rg *gin.RouterGroup) {
93 93
 		aR.POST("/create", cont.Create)
94 94
 		aR.POST("/update", cont.Update)
95 95
 		aR.POST("/delete", cont.Delete)
96
+
97
+		arp := aR.Use(middleware.AdminPrivilege())
98
+		arp.POST("/batchCreate", cont.BatchCreate)
96 99
 	}
97 100
 }
98 101
 func PeerBind(rg *gin.RouterGroup) {
@@ -104,6 +107,9 @@ func PeerBind(rg *gin.RouterGroup) {
104 107
 		aR.POST("/create", cont.Create)
105 108
 		aR.POST("/update", cont.Update)
106 109
 		aR.POST("/delete", cont.Delete)
110
+
111
+		arp := aR.Use(middleware.AdminPrivilege())
112
+		arp.POST("/batchDelete", cont.BatchDelete)
107 113
 	}
108 114
 }
109 115
 

+ 12 - 11
model/peer.go

@@ -1,17 +1,18 @@
1 1
 package model
2 2
 
3 3
 type Peer struct {
4
-	RowId    uint   `json:"row_id" gorm:"primaryKey;"`
5
-	Id       string `json:"id"  gorm:"default:'';not null;index"`
6
-	Cpu      string `json:"cpu"  gorm:"default:'';not null;"`
7
-	Hostname string `json:"hostname"  gorm:"default:'';not null;"`
8
-	Memory   string `json:"memory"  gorm:"default:'';not null;"`
9
-	Os       string `json:"os"  gorm:"default:'';not null;"`
10
-	Username string `json:"username"  gorm:"default:'';not null;"`
11
-	Uuid     string `json:"uuid"  gorm:"default:'';not null;index"`
12
-	Version  string `json:"version"  gorm:"default:'';not null;"`
13
-	UserId   uint   `json:"user_id"  gorm:"default:0;not null;index"`
14
-	User     User   `json:"user,omitempty" gorm:""`
4
+	RowId          uint   `json:"row_id" gorm:"primaryKey;"`
5
+	Id             string `json:"id"  gorm:"default:'';not null;index"`
6
+	Cpu            string `json:"cpu"  gorm:"default:'';not null;"`
7
+	Hostname       string `json:"hostname"  gorm:"default:'';not null;"`
8
+	Memory         string `json:"memory"  gorm:"default:'';not null;"`
9
+	Os             string `json:"os"  gorm:"default:'';not null;"`
10
+	Username       string `json:"username"  gorm:"default:'';not null;"`
11
+	Uuid           string `json:"uuid"  gorm:"default:'';not null;index"`
12
+	Version        string `json:"version"  gorm:"default:'';not null;"`
13
+	UserId         uint   `json:"user_id"  gorm:"default:0;not null;index"`
14
+	User           User   `json:"user,omitempty" gorm:""`
15
+	LastOnlineTime int64  `json:"last_online_time"  gorm:"default:0;not null;"`
15 16
 	TimeModel
16 17
 }
17 18
 

+ 10 - 0
resources/i18n/en.toml

@@ -109,3 +109,13 @@ other = "Decode oauth user info error."
109 109
 description = "Old password error."
110 110
 one = "Old password error."
111 111
 other = "Old password error."
112
+
113
+[DefaultGroup]
114
+description = "Default group"
115
+one = "Default Group"
116
+other = "Default Group"
117
+
118
+[ShareGroup]
119
+description = "Share group"
120
+one = "Share Group"
121
+other = "Share Group"

+ 12 - 1
resources/i18n/zh_CN.toml

@@ -109,4 +109,15 @@ other = "解析授权用户信息失败。"
109 109
 [OldPasswordError]
110 110
 description = "Old password error."
111 111
 one = "旧密码错误。"
112
-other = "旧密码错误。"
112
+other = "旧密码错误。"
113
+
114
+
115
+[DefaultGroup]
116
+description = "Default group."
117
+one = "默认组"
118
+other = "默认组"
119
+
120
+[ShareGroup]
121
+description = "Share group."
122
+one = "共享组"
123
+other = "共享组"

+ 5 - 0
service/peer.go

@@ -71,6 +71,11 @@ func (ps *PeerService) Delete(u *model.Peer) error {
71 71
 	return global.DB.Delete(u).Error
72 72
 }
73 73
 
74
+// BatchDelete
75
+func (ps *PeerService) BatchDelete(ids []uint) error {
76
+	return global.DB.Where("row_id in (?)", ids).Delete(&model.Peer{}).Error
77
+}
78
+
74 79
 // Update 更新
75 80
 func (ps *PeerService) Update(u *model.Peer) error {
76 81
 	return global.DB.Model(u).Updates(u).Error