diff --git a/cmd/apimain.go b/cmd/apimain.go index f65c3ff..e8862d9 100644 --- a/cmd/apimain.go +++ b/cmd/apimain.go @@ -200,7 +200,7 @@ func getTranslatorForLang(lang string) ut.Translator { } } func DatabaseAutoUpdate() { - version := 220 + version := 233 db := global.DB @@ -262,6 +262,7 @@ func Migrate(version uint) { &model.Oauth{}, &model.LoginLog{}, &model.ShareRecord{}, + &model.AuditConn{}, ) if err != nil { fmt.Println("migrate err :=>", err) diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index 0313e44..6efbd52 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -380,6 +380,123 @@ const docTemplateadmin = `{ } } }, + "/admin/audit_conn/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "链接日志删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "链接日志" + ], + "summary": "链接日志删除", + "parameters": [ + { + "description": "链接日志信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AuditConn" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/audit_conn/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" + }, + { + "type": "integer", + "description": "目标设备", + "name": "peer_id", + "in": "query" + }, + { + "type": "integer", + "description": "来源设备", + "name": "from_peer", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AuditConnList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/admin/file/oss_token": { "get": { "security": [ @@ -2744,6 +2861,70 @@ const docTemplateadmin = `{ } } }, + "model.AuditConn": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "close_time": { + "type": "integer" + }, + "conn_id": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "from_name": { + "type": "string" + }, + "from_peer": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "ip": { + "type": "string" + }, + "peer_id": { + "type": "string" + }, + "session_id": { + "type": "string" + }, + "type": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "uuid": { + "type": "string" + } + } + }, + "model.AuditConnList": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.AuditConn" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "model.Group": { "type": "object", "properties": { diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json index 25b829a..6eeb3f3 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -373,6 +373,123 @@ } } }, + "/admin/audit_conn/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "链接日志删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "链接日志" + ], + "summary": "链接日志删除", + "parameters": [ + { + "description": "链接日志信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AuditConn" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/audit_conn/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" + }, + { + "type": "integer", + "description": "目标设备", + "name": "peer_id", + "in": "query" + }, + { + "type": "integer", + "description": "来源设备", + "name": "from_peer", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AuditConnList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/admin/file/oss_token": { "get": { "security": [ @@ -2737,6 +2854,70 @@ } } }, + "model.AuditConn": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "close_time": { + "type": "integer" + }, + "conn_id": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "from_name": { + "type": "string" + }, + "from_peer": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "ip": { + "type": "string" + }, + "peer_id": { + "type": "string" + }, + "session_id": { + "type": "string" + }, + "type": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "uuid": { + "type": "string" + } + } + }, + "model.AuditConnList": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.AuditConn" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "model.Group": { "type": "object", "properties": { diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml index 7e31628..ccbcdff 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -273,6 +273,48 @@ definitions: total: type: integer type: object + model.AuditConn: + properties: + action: + type: string + close_time: + type: integer + conn_id: + type: integer + created_at: + type: string + from_name: + type: string + from_peer: + type: string + id: + type: integer + ip: + type: string + peer_id: + type: string + session_id: + type: string + type: + type: integer + updated_at: + type: string + uuid: + type: string + type: object + model.AuditConnList: + properties: + list: + items: + $ref: '#/definitions/model.AuditConn' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object model.Group: properties: created_at: @@ -719,6 +761,77 @@ paths: summary: APP服务配置 tags: - ADMIN + /admin/audit_conn/delete: + post: + consumes: + - application/json + description: 链接日志删除 + parameters: + - description: 链接日志信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AuditConn' + 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/audit_conn/list: + get: + consumes: + - application/json + description: 链接日志列表 + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 页大小 + in: query + name: page_size + type: integer + - description: 目标设备 + in: query + name: peer_id + type: integer + - description: 来源设备 + in: query + name: from_peer + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AuditConnList' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 链接日志列表 + tags: + - 链接日志 /admin/file/oss_token: get: consumes: diff --git a/docs/api/api_docs.go b/docs/api/api_docs.go index 43e44af..18b5264 100644 --- a/docs/api/api_docs.go +++ b/docs/api/api_docs.go @@ -121,40 +121,6 @@ const docTemplateapi = `{ } } }, - "/ab/add": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "标签", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "地址[Personal]" - ], - "summary": "标签添加", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.ErrorResponse" - } - } - } - } - }, "/ab/peer/add/{guid}": { "post": { "security": [ @@ -176,8 +142,8 @@ const docTemplateapi = `{ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -217,8 +183,8 @@ const docTemplateapi = `{ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -260,8 +226,8 @@ const docTemplateapi = `{ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -302,12 +268,22 @@ const docTemplateapi = `{ "summary": "地址列表", "parameters": [ { - "description": "string valid", - "name": "string", - "in": "body", - "schema": { - "type": "string" - } + "type": "integer", + "description": "页码", + "name": "current", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "guid", + "name": "ab", + "in": "query" } ], "responses": { @@ -434,12 +410,16 @@ const docTemplateapi = `{ "summary": "共享地址簿", "parameters": [ { - "description": "string valid", - "name": "string", - "in": "body", - "schema": { - "type": "string" - } + "type": "integer", + "description": "页码", + "name": "current", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "pageSize", + "in": "query" } ], "responses": { @@ -458,6 +438,49 @@ const docTemplateapi = `{ } } }, + "/ab/tag/add/{guid}": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "标签", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "地址[Personal]" + ], + "summary": "标签添加", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.ErrorResponse" + } + } + } + } + }, "/ab/tag/rename/{guid}": { "put": { "security": [ @@ -476,6 +499,15 @@ const docTemplateapi = `{ "地址[Personal]" ], "summary": "标签重命名", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -510,6 +542,15 @@ const docTemplateapi = `{ "地址[Personal]" ], "summary": "标签修改颜色", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -544,6 +585,15 @@ const docTemplateapi = `{ "地址[Personal]" ], "summary": "标签删除", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -581,8 +631,8 @@ const docTemplateapi = `{ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -637,6 +687,46 @@ const docTemplateapi = `{ } } }, + "/audit/conn": { + "post": { + "description": "审计连接", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "审计" + ], + "summary": "审计连接", + "parameters": [ + { + "description": "审计连接", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.AuditConnForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/heartbeat": { "post": { "description": "心跳", @@ -1137,6 +1227,38 @@ const docTemplateapi = `{ } } }, + "api.AuditConnForm": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "conn_id": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "peer": { + "type": "array", + "items": { + "type": "string" + } + }, + "session_id": { + "type": "number" + }, + "type": { + "type": "integer" + }, + "uuid": { + "type": "string" + } + } + }, "api.DeviceInfoInLogin": { "type": "object", "properties": { diff --git a/docs/api/api_swagger.json b/docs/api/api_swagger.json index 399f009..3c8d4e0 100644 --- a/docs/api/api_swagger.json +++ b/docs/api/api_swagger.json @@ -114,40 +114,6 @@ } } }, - "/ab/add": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "标签", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "地址[Personal]" - ], - "summary": "标签添加", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.ErrorResponse" - } - } - } - } - }, "/ab/peer/add/{guid}": { "post": { "security": [ @@ -169,8 +135,8 @@ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -210,8 +176,8 @@ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -253,8 +219,8 @@ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -295,12 +261,22 @@ "summary": "地址列表", "parameters": [ { - "description": "string valid", - "name": "string", - "in": "body", - "schema": { - "type": "string" - } + "type": "integer", + "description": "页码", + "name": "current", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "guid", + "name": "ab", + "in": "query" } ], "responses": { @@ -427,12 +403,16 @@ "summary": "共享地址簿", "parameters": [ { - "description": "string valid", - "name": "string", - "in": "body", - "schema": { - "type": "string" - } + "type": "integer", + "description": "页码", + "name": "current", + "in": "query" + }, + { + "type": "integer", + "description": "每页数量", + "name": "pageSize", + "in": "query" } ], "responses": { @@ -451,6 +431,49 @@ } } }, + "/ab/tag/add/{guid}": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "标签", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "地址[Personal]" + ], + "summary": "标签添加", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.ErrorResponse" + } + } + } + } + }, "/ab/tag/rename/{guid}": { "put": { "security": [ @@ -469,6 +492,15 @@ "地址[Personal]" ], "summary": "标签重命名", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -503,6 +535,15 @@ "地址[Personal]" ], "summary": "标签修改颜色", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -537,6 +578,15 @@ "地址[Personal]" ], "summary": "标签删除", + "parameters": [ + { + "type": "string", + "description": "guid", + "name": "guid", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -574,8 +624,8 @@ "parameters": [ { "type": "string", - "description": "id", - "name": "id", + "description": "guid", + "name": "guid", "in": "path", "required": true } @@ -630,6 +680,46 @@ } } }, + "/audit/conn": { + "post": { + "description": "审计连接", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "审计" + ], + "summary": "审计连接", + "parameters": [ + { + "description": "审计连接", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.AuditConnForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/heartbeat": { "post": { "description": "心跳", @@ -1130,6 +1220,38 @@ } } }, + "api.AuditConnForm": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "conn_id": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "peer": { + "type": "array", + "items": { + "type": "string" + } + }, + "session_id": { + "type": "number" + }, + "type": { + "type": "integer" + }, + "uuid": { + "type": "string" + } + } + }, "api.DeviceInfoInLogin": { "type": "object", "properties": { diff --git a/docs/api/api_swagger.yaml b/docs/api/api_swagger.yaml index f2efd10..ea10ac0 100644 --- a/docs/api/api_swagger.yaml +++ b/docs/api/api_swagger.yaml @@ -6,6 +6,27 @@ definitions: example: '{"tags":["tag1","tag2","tag3"],"peers":[{"id":"abc","username":"abv-l","hostname":"","platform":"Windows","alias":"","tags":["tag1","tag2"],"hash":"hash"}],"tag_colors":"{\"tag1\":4288585374,\"tag2\":4278238420,\"tag3\":4291681337}"}' type: string type: object + api.AuditConnForm: + properties: + action: + type: string + conn_id: + type: integer + id: + type: string + ip: + type: string + peer: + items: + type: string + type: array + session_id: + type: number + type: + type: integer + uuid: + type: string + type: object api.DeviceInfoInLogin: properties: name: @@ -208,36 +229,15 @@ paths: summary: 地址更新 tags: - 地址 - /ab/add: - post: - consumes: - - application/json - description: 标签 - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.ErrorResponse' - security: - - BearerAuth: [] - summary: 标签添加 - tags: - - 地址[Personal] /ab/peer/add/{guid}: delete: consumes: - application/json description: 删除地址 parameters: - - description: id + - description: guid in: path - name: id + name: guid required: true type: string produces: @@ -261,9 +261,9 @@ paths: - application/json description: 添加地址 parameters: - - description: id + - description: guid in: path - name: id + name: guid required: true type: string produces: @@ -288,9 +288,9 @@ paths: - application/json description: 更新地址 parameters: - - description: id + - description: guid in: path - name: id + name: guid required: true type: string produces: @@ -315,11 +315,18 @@ paths: - application/json description: 地址 parameters: - - description: string valid - in: body - name: string - schema: - type: string + - description: 页码 + in: query + name: current + type: integer + - description: 每页数量 + in: query + name: pageSize + type: integer + - description: guid + in: query + name: ab + type: string produces: - application/json responses: @@ -396,11 +403,14 @@ paths: - application/json description: 共享 parameters: - - description: string valid - in: body - name: string - schema: - type: string + - description: 页码 + in: query + name: current + type: integer + - description: 每页数量 + in: query + name: pageSize + type: integer produces: - application/json responses: @@ -422,6 +432,12 @@ paths: consumes: - application/json description: 标签 + parameters: + - description: guid + in: path + name: guid + required: true + type: string produces: - application/json responses: @@ -438,11 +454,44 @@ paths: summary: 标签删除 tags: - 地址[Personal] + /ab/tag/add/{guid}: + post: + consumes: + - application/json + description: 标签 + parameters: + - description: guid + in: path + name: guid + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.ErrorResponse' + security: + - BearerAuth: [] + summary: 标签添加 + tags: + - 地址[Personal] /ab/tag/rename/{guid}: put: consumes: - application/json description: 标签 + parameters: + - description: guid + in: path + name: guid + required: true + type: string produces: - application/json responses: @@ -464,6 +513,12 @@ paths: consumes: - application/json description: 标签 + parameters: + - description: guid + in: path + name: guid + required: true + type: string produces: - application/json responses: @@ -486,9 +541,9 @@ paths: - application/json description: 标签 parameters: - - description: id + - description: guid in: path - name: id + name: guid required: true type: string produces: @@ -528,6 +583,32 @@ paths: summary: 用户信息 tags: - 用户 + /audit/conn: + post: + consumes: + - application/json + description: 审计连接 + parameters: + - description: 审计连接 + in: body + name: body + required: true + schema: + $ref: '#/definitions/api.AuditConnForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + summary: 审计连接 + tags: + - 审计 /heartbeat: post: consumes: diff --git a/http/controller/admin/audit.go b/http/controller/admin/audit.go new file mode 100644 index 0000000..8714b64 --- /dev/null +++ b/http/controller/admin/audit.go @@ -0,0 +1,81 @@ +package admin + +import ( + "Gwen/global" + "Gwen/http/request/admin" + "Gwen/http/response" + "Gwen/model" + "Gwen/service" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type Audit struct { +} + +// ConnList 列表 +// @Tags 链接日志 +// @Summary 链接日志列表 +// @Description 链接日志列表 +// @Accept json +// @Produce json +// @Param page query int false "页码" +// @Param page_size query int false "页大小" +// @Param peer_id query int false "目标设备" +// @Param from_peer query int false "来源设备" +// @Success 200 {object} response.Response{data=model.AuditConnList} +// @Failure 500 {object} response.Response +// @Router /admin/audit_conn/list [get] +// @Security token +func (a *Audit) ConnList(c *gin.Context) { + query := &admin.AuditQuery{} + if err := c.ShouldBindQuery(query); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + res := service.AllService.AuditService.AuditConnList(query.Page, query.PageSize, func(tx *gorm.DB) { + if query.PeerId != "" { + tx.Where("peer_id like ?", "%"+query.PeerId+"%") + } + if query.FromPeer != "" { + tx.Where("from_peer like ?", "%"+query.FromPeer+"%") + } + }) + response.Success(c, res) +} + +// ConnDelete 删除 +// @Tags 链接日志 +// @Summary 链接日志删除 +// @Description 链接日志删除 +// @Accept json +// @Produce json +// @Param body body model.AuditConn true "链接日志信息" +// @Success 200 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /admin/audit_conn/delete [post] +// @Security token +func (a *Audit) ConnDelete(c *gin.Context) { + f := &model.AuditConn{} + 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 + } + l := service.AllService.AuditService.InfoById(f.Id) + if l.Id > 0 { + err := service.AllService.AuditService.DeleteAuditConn(l) + if err == nil { + response.Success(c, nil) + return + } + response.Fail(c, 101, err.Error()) + return + } + response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound")) +} diff --git a/http/controller/api/ab.go b/http/controller/api/ab.go index 489f8d6..3bdf4d3 100644 --- a/http/controller/api/ab.go +++ b/http/controller/api/ab.go @@ -118,9 +118,10 @@ func (a *Ab) Tags(c *gin.Context) { // @Description 标签 // @Accept json // @Produce json +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse -// @Router /ab/add [post] +// @Router /ab/tag/add/{guid} [post] // @Security BearerAuth func (a *Ab) TagAdd(c *gin.Context) { t := &model.Tag{} @@ -150,6 +151,7 @@ func (a *Ab) TagAdd(c *gin.Context) { // @Description 标签 // @Accept json // @Produce json +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse // @Router /ab/tag/rename/{guid} [put] @@ -187,6 +189,7 @@ func (a *Ab) TagRename(c *gin.Context) { // @Description 标签 // @Accept json // @Produce json +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse // @Router /ab/tag/update/{guid} [put] @@ -219,6 +222,7 @@ func (a *Ab) TagUpdate(c *gin.Context) { // @Description 标签 // @Accept json // @Produce json +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse // @Router /ab/tag/{guid} [delete] @@ -273,7 +277,7 @@ func (a *Ab) Personal(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "guid": guid, "name": user.Username, - "rule": 0, + "rule": 3, }) } else { c.JSON(http.StatusOK, nil) @@ -304,7 +308,8 @@ func (a *Ab) Settings(c *gin.Context) { // @Description 共享 // @Accept json // @Produce json -// @Param string body string false "string valid" +// @Param current query int false "页码" +// @Param pageSize query int false "每页数量" // @Success 200 {object} response.Response // @Failure 500 {object} response.Response // @Router /ab/shared/profiles [post] @@ -322,14 +327,14 @@ func (a *Ab) SharedProfiles(c *gin.Context) { "name": "admin", "owner": "admin", "note": "admin11", - "rule": 0, + "rule": 3, } item2 := map[string]interface{}{ "guid": "2", "name": "admin2", "owner": "admin2", "note": "admin22", - "rule": 0, + "rule": 2, } c.JSON(http.StatusOK, gin.H{ "total": 2, @@ -348,7 +353,9 @@ func (a *Ab) SharedProfiles(c *gin.Context) { // @Description 地址 // @Accept json // @Produce json -// @Param string body string false "string valid" +// @Param current query int false "页码" +// @Param pageSize query int false "每页数量" +// @Param ab query string false "guid" // @Success 200 {object} response.Response // @Failure 500 {object} response.Response // @Router /ab/peers [post] @@ -369,7 +376,7 @@ func (a *Ab) Peers(c *gin.Context) { // @Description 标签 // @Accept json // @Produce json -// @Param id path string true "id" +// @Param guid path string true "guid" // @Success 200 {object} model.TagList // @Failure 500 {object} response.ErrorResponse // @Router /ab/tags/{guid} [post] @@ -387,7 +394,7 @@ func (a *Ab) PTags(c *gin.Context) { // @Description 添加地址 // @Accept json // @Produce json -// @Param id path string true "id" +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse // @Router /ab/peer/add/{guid} [post] @@ -395,6 +402,7 @@ func (a *Ab) PTags(c *gin.Context) { func (a *Ab) PeerAdd(c *gin.Context) { // forceAlwaysRelay永远是字符串"false" //f := &gin.H{} + //guid := c.Param("guid") f := &requstform.PersonalAddressBookForm{} err := c.ShouldBindJSON(f) if err != nil { @@ -429,7 +437,7 @@ func (a *Ab) PeerAdd(c *gin.Context) { // @Description 删除地址 // @Accept json // @Produce json -// @Param id path string true "id" +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse // @Router /ab/peer/add/{guid} [delete] @@ -464,7 +472,7 @@ func (a *Ab) PeerDel(c *gin.Context) { // @Description 更新地址 // @Accept json // @Produce json -// @Param id path string true "id" +// @Param guid path string true "guid" // @Success 200 {string} string // @Failure 500 {object} response.ErrorResponse // @Router /ab/peer/update/{guid} [put] diff --git a/http/controller/api/audit.go b/http/controller/api/audit.go new file mode 100644 index 0000000..cf89057 --- /dev/null +++ b/http/controller/api/audit.go @@ -0,0 +1,56 @@ +package api + +import ( + request "Gwen/http/request/api" + "Gwen/http/response" + "Gwen/model" + "Gwen/service" + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "time" +) + +type Audit struct { +} + +// AuditConn +// @Tags 审计 +// @Summary 审计连接 +// @Description 审计连接 +// @Accept json +// @Produce json +// @Param body body request.AuditConnForm true "审计连接" +// @Success 200 {string} string "" +// @Failure 500 {object} response.Response +// @Router /audit/conn [post] +func (a *Audit) AuditConn(c *gin.Context) { + af := &request.AuditConnForm{} + err := c.ShouldBindBodyWith(af, binding.JSON) + if err != nil { + response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + //fmt.Println(af) + ac := af.ToAuditConn() + if af.Action == model.AuditActionNew { + service.AllService.AuditService.CreateAuditConn(ac) + } else if af.Action == model.AuditActionClose { + ex := service.AllService.AuditService.InfoByPeerIdAndConnId(af.Id, af.ConnId) + if ex.Id != 0 { + ex.CloseTime = time.Now().Unix() + service.AllService.AuditService.UpdateAuditConn(ex) + } + } else if af.Action == "" { + ex := service.AllService.AuditService.InfoByPeerIdAndConnId(af.Id, af.ConnId) + if ex.Id != 0 { + up := &model.AuditConn{ + IdModel: model.IdModel{Id: ex.Id}, + FromPeer: ac.FromPeer, + FromName: ac.FromName, + SessionId: ac.SessionId, + } + service.AllService.AuditService.UpdateAuditConn(up) + } + } + response.Success(c, "") +} diff --git a/http/controller/api/user.go b/http/controller/api/user.go index 2d5c3e8..a7f8b01 100644 --- a/http/controller/api/user.go +++ b/http/controller/api/user.go @@ -22,7 +22,7 @@ type User struct { // @Security token //func (u *User) currentUser(c *gin.Context) { // user := service.AllService.UserService.CurUser(c) -// up := (&apiResp.UserPayload{}).FromUser(user) +// up := (&apiResp.UserPayload{}).FromName(user) // c.JSON(http.StatusOK, up) //} diff --git a/http/request/admin/audit.go b/http/request/admin/audit.go new file mode 100644 index 0000000..964dfbb --- /dev/null +++ b/http/request/admin/audit.go @@ -0,0 +1,7 @@ +package admin + +type AuditQuery struct { + PeerId string `form:"peer_id"` + FromPeer string `form:"from_peer"` + PageQuery +} diff --git a/http/request/api/audit.go b/http/request/api/audit.go new file mode 100644 index 0000000..99b54a8 --- /dev/null +++ b/http/request/api/audit.go @@ -0,0 +1,40 @@ +package api + +import ( + "Gwen/model" + "strconv" +) + +type AuditConnForm struct { + Action string `json:"action"` + ConnId int64 `json:"conn_id"` + Id string `json:"id"` + Peer []string `json:"peer"` + Ip string `json:"ip"` + SessionId float64 `json:"session_id"` + Type int `json:"type"` + Uuid string `json:"uuid"` +} + +func (a *AuditConnForm) ToAuditConn() *model.AuditConn { + fp := "" + fn := "" + if len(a.Peer) >= 1 { + fp = a.Peer[0] + if len(a.Peer) == 2 { + fn = a.Peer[1] + } + } + ssid := strconv.FormatFloat(a.SessionId, 'f', -1, 64) + return &model.AuditConn{ + Action: a.Action, + ConnId: a.ConnId, + PeerId: a.Id, + FromPeer: fp, + FromName: fn, + Ip: a.Ip, + SessionId: ssid, + Type: a.Type, + Uuid: a.Uuid, + } +} diff --git a/http/router/admin.go b/http/router/admin.go index 946a419..7291f3f 100644 --- a/http/router/admin.go +++ b/http/router/admin.go @@ -27,7 +27,7 @@ func Init(g *gin.Engine) { PeerBind(adg) OauthBind(adg) LoginLogBind(adg) - + AuditBind(adg) rs := &admin.Rustdesk{} adg.GET("/server-config", rs.ServerConfig) adg.GET("/app-config", rs.AppConfig) @@ -143,6 +143,12 @@ func LoginLogBind(rg *gin.RouterGroup) { aR.GET("/list", cont.List) aR.POST("/delete", cont.Delete) } +func AuditBind(rg *gin.RouterGroup) { + cont := &admin.Audit{} + aR := rg.Group("/audit_conn").Use(middleware.AdminPrivilege()) + aR.GET("/list", cont.ConnList) + aR.POST("/delete", cont.ConnDelete) +} /* func FileBind(rg *gin.RouterGroup) { diff --git a/http/router/api.go b/http/router/api.go index 2f27dcb..a228c46 100644 --- a/http/router/api.go +++ b/http/router/api.go @@ -50,7 +50,9 @@ func ApiInit(g *gin.Engine) { if global.Config.App.WebClient == 1 { WebClientRoutes(frg) } - + au := &api.Audit{} + //[method:POST] [uri:/api/audit/conn] + frg.POST("/audit/conn", au.AuditConn) frg.Use(middleware.RustAuth()) { u := &api.User{} diff --git a/model/audit.go b/model/audit.go new file mode 100644 index 0000000..4d18852 --- /dev/null +++ b/model/audit.go @@ -0,0 +1,26 @@ +package model + +const ( + AuditActionNew = "new" + AuditActionClose = "close" +) + +type AuditConn struct { + IdModel + Action string `json:"action" gorm:"default:'';not null;"` + ConnId int64 `json:"conn_id" gorm:"default:0;not null;index"` + PeerId string `json:"peer_id" gorm:"default:'';not null;index"` + FromPeer string `json:"from_peer" gorm:"default:'';not null;"` + FromName string `json:"from_name" gorm:"default:'';not null;"` + Ip string `json:"ip" gorm:"default:'';not null;"` + SessionId string `json:"session_id" gorm:"default:'';not null;"` + Type int `json:"type" gorm:"default:0;not null;"` + Uuid string `json:"uuid" gorm:"default:'';not null;"` + CloseTime int64 `json:"close_time" gorm:"default:0;not null;"` + TimeModel +} + +type AuditConnList struct { + AuditConns []*AuditConn `json:"list"` + Pagination +} diff --git a/service/audit.go b/service/audit.go new file mode 100644 index 0000000..b79acc4 --- /dev/null +++ b/service/audit.go @@ -0,0 +1,52 @@ +package service + +import ( + "Gwen/global" + "Gwen/model" + "gorm.io/gorm" +) + +type AuditService struct { +} + +func (as *AuditService) AuditConnList(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AuditConnList) { + res = &model.AuditConnList{} + res.Page = int64(page) + res.PageSize = int64(pageSize) + tx := global.DB.Model(&model.AuditConn{}) + if where != nil { + where(tx) + } + tx.Count(&res.Total) + tx.Scopes(Paginate(page, pageSize)) + tx.Find(&res.AuditConns) + return +} + +// Create 创建 +func (as *AuditService) CreateAuditConn(u *model.AuditConn) error { + res := global.DB.Create(u).Error + return res +} +func (as *AuditService) DeleteAuditConn(u *model.AuditConn) error { + return global.DB.Delete(u).Error +} + +// Update 更新 +func (as *AuditService) UpdateAuditConn(u *model.AuditConn) error { + return global.DB.Model(u).Updates(u).Error +} + +// InfoByPeerIdAndConnId +func (as *AuditService) InfoByPeerIdAndConnId(peerId string, connId int64) (res *model.AuditConn) { + res = &model.AuditConn{} + global.DB.Where("peer_id = ? and conn_id = ?", peerId, connId).First(res) + return +} + +// InfoById +func (as *AuditService) InfoById(id uint) (res *model.AuditConn) { + res = &model.AuditConn{} + global.DB.Where("id = ?", id).First(res) + return +} diff --git a/service/oauth.go b/service/oauth.go index 889d4ae..c28db44 100644 --- a/service/oauth.go +++ b/service/oauth.go @@ -7,7 +7,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "golang.org/x/oauth2" "golang.org/x/oauth2/github" "golang.org/x/oauth2/google" @@ -174,7 +173,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)) + global.Logger.Warn("oauthConfig.Exchange() failed: ", err) error = errors.New("GetOauthTokenError") return } @@ -183,20 +182,20 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith client := oauthConfig.Client(context.Background(), token) resp, err := client.Get("https://api.github.com/user") if err != nil { - global.Logger.Warn("failed getting user info: %s\n", err) + global.Logger.Warn("failed getting user info: ", err) error = errors.New("GetOauthUserInfoError") return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { - global.Logger.Warn("failed closing response body: %s\n", err) + global.Logger.Warn("failed closing response body: ", err) } }(resp.Body) // 在这里处理 GitHub 用户信息 if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil { - global.Logger.Warn("failed decoding user info: %s\n", err) + global.Logger.Warn("failed decoding user info: ", err) error = errors.New("DecodeOauthUserInfoError") return } @@ -207,7 +206,7 @@ func (os *OauthService) GoogleCallback(code string) (error error, userData *Goog err, oauthConfig := os.GetOauthConfig(model.OauthTypeGoogle) token, err := oauthConfig.Exchange(context.Background(), code) if err != nil { - global.Logger.Warn(fmt.Printf("oauthConfig.Exchange() failed: %s\n", err)) + global.Logger.Warn("oauthConfig.Exchange() failed: ", err) error = errors.New("GetOauthTokenError") return } @@ -215,14 +214,14 @@ func (os *OauthService) GoogleCallback(code string) (error error, userData *Goog client := oauthConfig.Client(context.Background(), token) resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo") if err != nil { - global.Logger.Warn("failed getting user info: %s\n", err) + global.Logger.Warn("failed getting user info: ", err) error = errors.New("GetOauthUserInfoError") return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { - global.Logger.Warn("failed closing response body: %s\n", err) + global.Logger.Warn("failed closing response body: ", err) } }(resp.Body) diff --git a/service/service.go b/service/service.go index c25388d..013ebc2 100644 --- a/service/service.go +++ b/service/service.go @@ -15,6 +15,7 @@ type Service struct { *GroupService *OauthService *LoginLogService + *AuditService } func New() *Service { diff --git a/service/user.go b/service/user.go index d00f032..c38fce3 100644 --- a/service/user.go +++ b/service/user.go @@ -21,6 +21,11 @@ func (us *UserService) InfoById(id uint) *model.User { global.DB.Where("id = ?", id).First(u) return u } +func (us *UserService) InfoByUsername(un string) *model.User { + u := &model.User{} + global.DB.Where("username = ?", un).First(u) + return u +} // InfoByOpenid 根据openid取用户信息 func (us *UserService) InfoByOpenid(openid string) *model.User {