diff --git a/cmd/apimain.go b/cmd/apimain.go index 17348fe..e5d73d3 100644 --- a/cmd/apimain.go +++ b/cmd/apimain.go @@ -166,7 +166,7 @@ func InitGlobal() { global.Lock = lock.NewLocal() } func DatabaseAutoUpdate() { - version := 261 + version := 262 db := global.DB @@ -251,6 +251,7 @@ func Migrate(version uint) { &model.AddressBookCollection{}, &model.AddressBookCollectionRule{}, &model.ServerCmd{}, + &model.DeviceGroup{}, ) if err != nil { global.Logger.Error("migrate err :=>", err) diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index a212079..5fa6476 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -1407,6 +1407,280 @@ const docTemplateadmin = `{ } } }, + "/admin/device_group/create": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "创建设备群组", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "创建设备群组", + "parameters": [ + { + "description": "设备群组信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.DeviceGroupForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.DeviceGroup" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "设备群组删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "设备群组删除", + "parameters": [ + { + "description": "群组信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.DeviceGroupForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/detail/{id}": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "设备群组详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "设备群组详情", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.Group" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/list": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "群组列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "群组" + ], + "summary": "群组列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "页大小", + "name": "page_size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.GroupList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/update": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "设备群组编辑", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "设备群组编辑", + "parameters": [ + { + "description": "群组信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.DeviceGroupForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.Group" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/admin/file/oss_token": { "get": { "security": [ @@ -1783,7 +2057,7 @@ const docTemplateadmin = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_lejianwen_rustdesk-api_http_request_admin.Login" + "$ref": "#/definitions/github_com_lejianwen_rustdesk-api_v2_http_request_admin.Login" } } ], @@ -5219,6 +5493,20 @@ const docTemplateadmin = `{ } } }, + "admin.DeviceGroupForm": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, "admin.GroupForm": { "type": "object", "required": [ @@ -5306,6 +5594,12 @@ const docTemplateadmin = `{ "op": { "type": "string" }, + "pkce_enable": { + "type": "boolean" + }, + "pkce_method": { + "type": "string" + }, "redirect_url": { "type": "string" }, @@ -5334,6 +5628,9 @@ const docTemplateadmin = `{ "cpu": { "type": "string" }, + "group_id": { + "type": "integer" + }, "hostname": { "type": "string" }, @@ -5521,7 +5818,7 @@ const docTemplateadmin = `{ } } }, - "github_com_lejianwen_rustdesk-api_http_request_admin.Login": { + "github_com_lejianwen_rustdesk-api_v2_http_request_admin.Login": { "type": "object", "required": [ "password", @@ -5842,6 +6139,23 @@ const docTemplateadmin = `{ } } }, + "model.DeviceGroup": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "model.Group": { "type": "object", "properties": { @@ -5973,6 +6287,12 @@ const docTemplateadmin = `{ "op": { "type": "string" }, + "pkce_enable": { + "type": "boolean" + }, + "pkce_method": { + "type": "string" + }, "redirect_url": { "type": "string" }, @@ -6013,6 +6333,9 @@ const docTemplateadmin = `{ "created_at": { "type": "string" }, + "group_id": { + "type": "integer" + }, "hostname": { "type": "string" }, diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json index 7264375..7d03c34 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -1400,6 +1400,280 @@ } } }, + "/admin/device_group/create": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "创建设备群组", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "创建设备群组", + "parameters": [ + { + "description": "设备群组信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.DeviceGroupForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.DeviceGroup" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "设备群组删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "设备群组删除", + "parameters": [ + { + "description": "群组信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.DeviceGroupForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/detail/{id}": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "设备群组详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "设备群组详情", + "parameters": [ + { + "type": "integer", + "description": "ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.Group" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/list": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "群组列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "群组" + ], + "summary": "群组列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "页大小", + "name": "page_size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.GroupList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/device_group/update": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "设备群组编辑", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设备群组" + ], + "summary": "设备群组编辑", + "parameters": [ + { + "description": "群组信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.DeviceGroupForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.Group" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/admin/file/oss_token": { "get": { "security": [ @@ -1776,7 +2050,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_lejianwen_rustdesk-api_http_request_admin.Login" + "$ref": "#/definitions/github_com_lejianwen_rustdesk-api_v2_http_request_admin.Login" } } ], @@ -5212,6 +5486,20 @@ } } }, + "admin.DeviceGroupForm": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, "admin.GroupForm": { "type": "object", "required": [ @@ -5299,6 +5587,12 @@ "op": { "type": "string" }, + "pkce_enable": { + "type": "boolean" + }, + "pkce_method": { + "type": "string" + }, "redirect_url": { "type": "string" }, @@ -5327,6 +5621,9 @@ "cpu": { "type": "string" }, + "group_id": { + "type": "integer" + }, "hostname": { "type": "string" }, @@ -5514,7 +5811,7 @@ } } }, - "github_com_lejianwen_rustdesk-api_http_request_admin.Login": { + "github_com_lejianwen_rustdesk-api_v2_http_request_admin.Login": { "type": "object", "required": [ "password", @@ -5835,6 +6132,23 @@ } } }, + "model.DeviceGroup": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "model.Group": { "type": "object", "properties": { @@ -5966,6 +6280,12 @@ "op": { "type": "string" }, + "pkce_enable": { + "type": "boolean" + }, + "pkce_method": { + "type": "string" + }, "redirect_url": { "type": "string" }, @@ -6006,6 +6326,9 @@ "created_at": { "type": "string" }, + "group_id": { + "type": "integer" + }, "hostname": { "type": "string" }, diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml index 0927b76..55eb47a 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -77,6 +77,15 @@ definitions: - new_password - old_password type: object + admin.DeviceGroupForm: + properties: + id: + type: integer + name: + type: string + required: + - name + type: object admin.GroupForm: properties: id: @@ -130,6 +139,10 @@ definitions: type: string op: type: string + pkce_enable: + type: boolean + pkce_method: + type: string redirect_url: type: string scopes: @@ -153,6 +166,8 @@ definitions: properties: cpu: type: string + group_id: + type: integer hostname: type: string id: @@ -278,7 +293,7 @@ definitions: required: - ids type: object - github_com_lejianwen_rustdesk-api_http_request_admin.Login: + github_com_lejianwen_rustdesk-api_v2_http_request_admin.Login: properties: captcha: type: string @@ -492,6 +507,17 @@ definitions: total: type: integer type: object + model.DeviceGroup: + properties: + created_at: + type: string + id: + type: integer + name: + type: string + updated_at: + type: string + type: object model.Group: properties: created_at: @@ -579,6 +605,10 @@ definitions: type: string op: type: string + pkce_enable: + type: boolean + pkce_method: + type: string redirect_url: type: string scopes: @@ -605,6 +635,8 @@ definitions: type: string created_at: type: string + group_id: + type: integer hostname: type: string id: @@ -1610,6 +1642,167 @@ paths: summary: RUSTDESK服务配置 tags: - ADMIN + /admin/device_group/create: + post: + consumes: + - application/json + description: 创建设备群组 + parameters: + - description: 设备群组信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/admin.DeviceGroupForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.DeviceGroup' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 创建设备群组 + tags: + - 设备群组 + /admin/device_group/delete: + post: + consumes: + - application/json + description: 设备群组删除 + parameters: + - description: 群组信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/admin.DeviceGroupForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 设备群组删除 + tags: + - 设备群组 + /admin/device_group/detail/{id}: + get: + consumes: + - application/json + description: 设备群组详情 + parameters: + - description: ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.Group' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 设备群组详情 + tags: + - 设备群组 + /admin/device_group/list: + get: + consumes: + - application/json + description: 群组列表 + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 页大小 + in: query + name: page_size + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.GroupList' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 群组列表 + tags: + - 群组 + /admin/device_group/update: + post: + consumes: + - application/json + description: 设备群组编辑 + parameters: + - description: 群组信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/admin.DeviceGroupForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.Group' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 设备群组编辑 + tags: + - 设备群组 /admin/file/oss_token: get: consumes: @@ -1830,7 +2023,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/github_com_lejianwen_rustdesk-api_http_request_admin.Login' + $ref: '#/definitions/github_com_lejianwen_rustdesk-api_v2_http_request_admin.Login' produces: - application/json responses: diff --git a/docs/api/api_docs.go b/docs/api/api_docs.go index 71bae82..75c49cf 100644 --- a/docs/api/api_docs.go +++ b/docs/api/api_docs.go @@ -767,6 +767,66 @@ const docTemplateapi = `{ } } }, + "/device-group/accessible": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "机器", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "群组" + ], + "summary": "设备", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "状态", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "accessible", + "name": "accessible", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.DataResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/heartbeat": { "post": { "description": "心跳", diff --git a/docs/api/api_swagger.json b/docs/api/api_swagger.json index c121834..b2f5ff3 100644 --- a/docs/api/api_swagger.json +++ b/docs/api/api_swagger.json @@ -760,6 +760,66 @@ } } }, + "/device-group/accessible": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "机器", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "群组" + ], + "summary": "设备", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "状态", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "accessible", + "name": "accessible", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.DataResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/heartbeat": { "post": { "description": "心跳", diff --git a/docs/api/api_swagger.yaml b/docs/api/api_swagger.yaml index eb30f17..7ed13bc 100644 --- a/docs/api/api_swagger.yaml +++ b/docs/api/api_swagger.yaml @@ -671,6 +671,44 @@ paths: summary: 用户信息 tags: - 用户 + /device-group/accessible: + get: + consumes: + - application/json + description: 机器 + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页数量 + in: query + name: pageSize + type: integer + - description: 状态 + in: query + name: status + type: integer + - description: accessible + in: query + name: accessible + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.DataResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - BearerAuth: [] + summary: 设备 + tags: + - 群组 /heartbeat: post: consumes: diff --git a/http/controller/admin/deviceGroup.go b/http/controller/admin/deviceGroup.go new file mode 100644 index 0000000..3d3a884 --- /dev/null +++ b/http/controller/admin/deviceGroup.go @@ -0,0 +1,160 @@ +package admin + +import ( + "github.com/gin-gonic/gin" + "github.com/lejianwen/rustdesk-api/v2/global" + "github.com/lejianwen/rustdesk-api/v2/http/request/admin" + "github.com/lejianwen/rustdesk-api/v2/http/response" + "github.com/lejianwen/rustdesk-api/v2/service" + "strconv" +) + +type DeviceGroup struct { +} + +// Detail 设备群组 +// @Tags 设备群组 +// @Summary 设备群组详情 +// @Description 设备群组详情 +// @Accept json +// @Produce json +// @Param id path int true "ID" +// @Success 200 {object} response.Response{data=model.Group} +// @Failure 500 {object} response.Response +// @Router /admin/device_group/detail/{id} [get] +// @Security token +func (ct *DeviceGroup) Detail(c *gin.Context) { + id := c.Param("id") + iid, _ := strconv.Atoi(id) + u := service.AllService.GroupService.DeviceGroupInfoById(uint(iid)) + if u.Id > 0 { + response.Success(c, u) + return + } + response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound")) + return +} + +// Create 创建设备群组 +// @Tags 设备群组 +// @Summary 创建设备群组 +// @Description 创建设备群组 +// @Accept json +// @Produce json +// @Param body body admin.DeviceGroupForm true "设备群组信息" +// @Success 200 {object} response.Response{data=model.DeviceGroup} +// @Failure 500 {object} response.Response +// @Router /admin/device_group/create [post] +// @Security token +func (ct *DeviceGroup) Create(c *gin.Context) { + f := &admin.DeviceGroupForm{} + if err := c.ShouldBindJSON(f); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + errList := global.Validator.ValidStruct(c, f) + if len(errList) > 0 { + response.Fail(c, 101, errList[0]) + return + } + u := f.ToDeviceGroup() + err := service.AllService.GroupService.DeviceGroupCreate(u) + if err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Success(c, nil) +} + +// List 列表 +// @Tags 群组 +// @Summary 群组列表 +// @Description 群组列表 +// @Accept json +// @Produce json +// @Param page query int false "页码" +// @Param page_size query int false "页大小" +// @Success 200 {object} response.Response{data=model.GroupList} +// @Failure 500 {object} response.Response +// @Router /admin/device_group/list [get] +// @Security token +func (ct *DeviceGroup) List(c *gin.Context) { + query := &admin.PageQuery{} + if err := c.ShouldBindQuery(query); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + res := service.AllService.GroupService.DeviceGroupList(query.Page, query.PageSize, nil) + response.Success(c, res) +} + +// Update 编辑 +// @Tags 设备群组 +// @Summary 设备群组编辑 +// @Description 设备群组编辑 +// @Accept json +// @Produce json +// @Param body body admin.DeviceGroupForm true "群组信息" +// @Success 200 {object} response.Response{data=model.Group} +// @Failure 500 {object} response.Response +// @Router /admin/device_group/update [post] +// @Security token +func (ct *DeviceGroup) Update(c *gin.Context) { + f := &admin.DeviceGroupForm{} + if err := c.ShouldBindJSON(f); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + if f.Id == 0 { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")) + return + } + errList := global.Validator.ValidStruct(c, f) + if len(errList) > 0 { + response.Fail(c, 101, errList[0]) + return + } + u := f.ToDeviceGroup() + err := service.AllService.GroupService.DeviceGroupUpdate(u) + if err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Success(c, nil) +} + +// Delete 删除 +// @Tags 设备群组 +// @Summary 设备群组删除 +// @Description 设备群组删除 +// @Accept json +// @Produce json +// @Param body body admin.DeviceGroupForm true "群组信息" +// @Success 200 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /admin/device_group/delete [post] +// @Security token +func (ct *DeviceGroup) Delete(c *gin.Context) { + f := &admin.DeviceGroupForm{} + if err := c.ShouldBindJSON(f); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + id := f.Id + errList := global.Validator.ValidVar(c, id, "required,gt=0") + if len(errList) > 0 { + response.Fail(c, 101, errList[0]) + return + } + u := service.AllService.GroupService.DeviceGroupInfoById(f.Id) + if u.Id > 0 { + err := service.AllService.GroupService.DeviceGroupDelete(u) + if err == nil { + response.Success(c, nil) + return + } + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound")) +} diff --git a/http/controller/api/group.go b/http/controller/api/group.go index 472a4c0..a037f43 100644 --- a/http/controller/api/group.go +++ b/http/controller/api/group.go @@ -94,6 +94,11 @@ func (g *Group) Peers(c *gin.Context) { namesById[user.Id] = user.Username userIds = append(userIds, user.Id) } + dGroupNameById := make(map[uint]string) + allGroup := service.AllService.GroupService.DeviceGroupList(1, 999, nil) + for _, group := range allGroup.DeviceGroups { + dGroupNameById[group.Id] = group.Name + } peerList := service.AllService.PeerService.ListByUserIds(userIds, q.Page, q.PageSize) data := make([]*apiResp.GroupPeerPayload, 0, len(peerList.Peers)) for _, peer := range peerList.Peers { @@ -101,9 +106,12 @@ func (g *Group) Peers(c *gin.Context) { if !ok { uname = "" } + dGroupName, ok2 := dGroupNameById[peer.GroupId] + if !ok2 { + dGroupName = "" + } pp := &apiResp.GroupPeerPayload{} - pp.FromPeer(peer, uname) - //pp.DeviceGroupName = uname + pp.FromPeer(peer, uname, dGroupName) data = append(data, pp) } @@ -128,8 +136,15 @@ func (g *Group) Peers(c *gin.Context) { // @Router /device-group/accessible [get] // @Security BearerAuth func (g *Group) Device(c *gin.Context) { + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) { + response.Error(c, "Permission denied") + return + } + allGroup := service.AllService.GroupService.DeviceGroupList(1, 999, nil) + c.JSON(http.StatusOK, response.DataResponse{ Total: 0, - Data: nil, + Data: allGroup.DeviceGroups, }) } diff --git a/http/request/admin/group.go b/http/request/admin/group.go index 2b2125c..1c51e68 100644 --- a/http/request/admin/group.go +++ b/http/request/admin/group.go @@ -22,3 +22,15 @@ func (gf *GroupForm) ToGroup() *model.Group { group.Type = gf.Type return group } + +type DeviceGroupForm struct { + Id uint `json:"id"` + Name string `json:"name" validate:"required"` +} + +func (gf *DeviceGroupForm) ToDeviceGroup() *model.DeviceGroup { + group := &model.DeviceGroup{} + group.Id = gf.Id + group.Name = gf.Name + return group +} diff --git a/http/request/admin/peer.go b/http/request/admin/peer.go index a368a14..493c61a 100644 --- a/http/request/admin/peer.go +++ b/http/request/admin/peer.go @@ -12,6 +12,7 @@ type PeerForm struct { Username string `json:"username"` Uuid string `json:"uuid"` Version string `json:"version"` + GroupId uint `json:"group_id"` } type PeerBatchDeleteForm struct { @@ -30,6 +31,7 @@ func (f *PeerForm) ToPeer() *model.Peer { Username: f.Username, Uuid: f.Uuid, Version: f.Version, + GroupId: f.GroupId, } } diff --git a/http/response/api/peer.go b/http/response/api/peer.go index 8de3ea6..e36e8ea 100644 --- a/http/response/api/peer.go +++ b/http/response/api/peer.go @@ -60,7 +60,7 @@ func (gpp *GroupPeerPayload) FromAddressBook(a *model.AddressBook, username stri gpp.UserName = username } -func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string) { +func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string, dGroupName string) { gpp.Id = p.Id gpp.Info = &PeerPayloadInfo{ DeviceName: p.Hostname, @@ -69,4 +69,5 @@ func (gpp *GroupPeerPayload) FromPeer(p *model.Peer, username string) { } gpp.Note = "" gpp.UserName = username + gpp.DeviceGroupName = dGroupName } diff --git a/http/router/admin.go b/http/router/admin.go index 4b2822d..2cd01de 100644 --- a/http/router/admin.go +++ b/http/router/admin.go @@ -49,7 +49,7 @@ func Init(g *gin.Engine) { MyBind(adg) RustdeskCmdBind(adg) - + DeviceGroupBind(adg) //访问静态文件 //g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload")) } @@ -106,6 +106,18 @@ func GroupBind(rg *gin.RouterGroup) { } } +func DeviceGroupBind(rg *gin.RouterGroup) { + aR := rg.Group("/device_group").Use(middleware.AdminPrivilege()) + { + cont := &admin.DeviceGroup{} + aR.GET("/list", cont.List) + aR.GET("/detail/:id", cont.Detail) + aR.POST("/create", cont.Create) + aR.POST("/update", cont.Update) + aR.POST("/delete", cont.Delete) + } +} + func TagBind(rg *gin.RouterGroup) { aR := rg.Group("/tag").Use(middleware.AdminPrivilege()) { diff --git a/model/group.go b/model/group.go index 4d09b54..e49e794 100644 --- a/model/group.go +++ b/model/group.go @@ -16,3 +16,14 @@ type GroupList struct { Groups []*Group `json:"list"` Pagination } + +type DeviceGroup struct { + IdModel + Name string `json:"name" gorm:"default:'';not null;"` + TimeModel +} + +type DeviceGroupList struct { + DeviceGroups []*DeviceGroup `json:"list"` + Pagination +} diff --git a/model/peer.go b/model/peer.go index c5dfb11..cd9be40 100644 --- a/model/peer.go +++ b/model/peer.go @@ -14,6 +14,7 @@ type Peer struct { User *User `json:"user,omitempty"` LastOnlineTime int64 `json:"last_online_time" gorm:"default:0;not null;"` LastOnlineIp string `json:"last_online_ip" gorm:"default:'';not null;"` + GroupId uint `json:"group_id" gorm:"default:0;not null;index"` TimeModel } diff --git a/service/group.go b/service/group.go index 8291d9b..938bab0 100644 --- a/service/group.go +++ b/service/group.go @@ -43,3 +43,36 @@ func (us *GroupService) Delete(u *model.Group) error { func (us *GroupService) Update(u *model.Group) error { return global.DB.Model(u).Updates(u).Error } + +// DeviceGroupInfoById 根据用户id取用户信息 +func (us *GroupService) DeviceGroupInfoById(id uint) *model.DeviceGroup { + u := &model.DeviceGroup{} + global.DB.Where("id = ?", id).First(u) + return u +} + +func (us *GroupService) DeviceGroupList(page, pageSize uint, where func(tx *gorm.DB)) (res *model.DeviceGroupList) { + res = &model.DeviceGroupList{} + res.Page = int64(page) + res.PageSize = int64(pageSize) + tx := global.DB.Model(&model.DeviceGroup{}) + if where != nil { + where(tx) + } + tx.Count(&res.Total) + tx.Scopes(Paginate(page, pageSize)) + tx.Find(&res.DeviceGroups) + return +} + +func (us *GroupService) DeviceGroupCreate(u *model.DeviceGroup) error { + res := global.DB.Create(u).Error + return res +} +func (us *GroupService) DeviceGroupDelete(u *model.DeviceGroup) error { + return global.DB.Delete(u).Error +} + +func (us *GroupService) DeviceGroupUpdate(u *model.DeviceGroup) error { + return global.DB.Model(u).Updates(u).Error +}