diff --git a/cmd/apimain.go b/cmd/apimain.go index f7783c3..15a1516 100644 --- a/cmd/apimain.go +++ b/cmd/apimain.go @@ -101,7 +101,7 @@ func main() { } func DatabaseAutoUpdate() { - version := 235 + version := 240 db := global.DB @@ -165,6 +165,8 @@ func Migrate(version uint) { &model.ShareRecord{}, &model.AuditConn{}, &model.AuditFile{}, + &model.AddressBookCollection{}, + &model.AddressBookCollectionRule{}, ) if err != nil { fmt.Println("migrate err :=>", err) diff --git a/conf/config.yaml b/conf/config.yaml index b818cbd..84c342e 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -3,7 +3,7 @@ app: web-client: 1 # 1:启用 0:禁用 gin: api-addr: "0.0.0.0:21114" - mode: "release" #release,debug,test + mode: "debug" #release,debug,test resources-path: 'resources' #对外静态文件目录 trust-proxy: "" gorm: @@ -23,11 +23,11 @@ rustdesk: personal: 1 logger: path: "./runtime/log.txt" - level: "warn" #trace,debug,info,warn,error,fatal + level: "debug" #trace,debug,info,warn,error,fatal report-caller: true proxy: enable: false - host: "" + host: "http://127.0.0.1:1080" redis: addr: "127.0.0.1:6379" password: "" diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index edba631..f4547ab 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -346,6 +346,554 @@ const docTemplateadmin = `{ } } }, + "/admin/address_book_collection/create": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "创建地址簿集合", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "创建地址簿集合", + "parameters": [ + { + "description": "地址簿集合信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合删除", + "parameters": [ + { + "description": "地址簿集合信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/detail/{id}": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "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.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/list": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "页大小", + "name": "page_size", + "in": "query" + }, + { + "type": "integer", + "description": "是否是我的", + "name": "is_my", + "in": "query" + }, + { + "type": "integer", + "description": "用户id", + "name": "user_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollectionList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/update": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合编辑", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合编辑", + "parameters": [ + { + "description": "地址簿集合信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/create": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "创建地址簿集合规则", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "创建地址簿集合规则", + "parameters": [ + { + "description": "地址簿集合规则信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollectionRule" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合规则删除", + "parameters": [ + { + "description": "地址簿集合规则信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollectionRule" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/detail/{id}": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "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.AddressBookCollectionRule" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/list": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合规则列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "页大小", + "name": "page_size", + "in": "query" + }, + { + "type": "integer", + "description": "是否是我的", + "name": "is_my", + "in": "query" + }, + { + "type": "integer", + "description": "用户id", + "name": "user_id", + "in": "query" + }, + { + "type": "integer", + "description": "地址簿集合id", + "name": "collection_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollectionList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/update": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则编辑", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合规则编辑", + "parameters": [ + { + "description": "地址簿集合规则信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollectionRule" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/admin/app-config": { "get": { "security": [ @@ -2480,6 +3028,9 @@ const docTemplateadmin = `{ "alias": { "type": "string" }, + "collection_id": { + "type": "integer" + }, "forceAlwaysRelay": { "type": "boolean" }, @@ -2701,6 +3252,9 @@ const docTemplateadmin = `{ "name" ], "properties": { + "collection_id": { + "type": "integer" + }, "color": { "type": "integer" }, @@ -2788,6 +3342,12 @@ const docTemplateadmin = `{ "alias": { "type": "string" }, + "collection": { + "$ref": "#/definitions/model.AddressBookCollection" + }, + "collection_id": { + "type": "integer" + }, "created_at": { "type": "string" }, @@ -2844,6 +3404,90 @@ const docTemplateadmin = `{ } } }, + "model.AddressBookCollection": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, + "model.AddressBookCollectionList": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.AddressBookCollection" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "model.AddressBookCollectionRule": { + "type": "object", + "required": [ + "collection_id", + "rule", + "to_id", + "type" + ], + "properties": { + "collection_id": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rule": { + "description": "0: 无 1: 读 2: 读写 3: 完全控制", + "type": "integer", + "maximum": 3, + "minimum": 1 + }, + "to_id": { + "type": "integer" + }, + "type": { + "description": "1: 个人 2: 群组", + "type": "integer", + "maximum": 2, + "minimum": 1 + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, "model.AddressBookList": { "type": "object", "properties": { @@ -3221,6 +3865,12 @@ const docTemplateadmin = `{ "model.Tag": { "type": "object", "properties": { + "collection": { + "$ref": "#/definitions/model.AddressBookCollection" + }, + "collection_id": { + "type": "integer" + }, "color": { "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba", "type": "integer" diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json index 5b42d2a..7e871e7 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -339,6 +339,554 @@ } } }, + "/admin/address_book_collection/create": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "创建地址簿集合", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "创建地址簿集合", + "parameters": [ + { + "description": "地址簿集合信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合删除", + "parameters": [ + { + "description": "地址簿集合信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/detail/{id}": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "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.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/list": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "页大小", + "name": "page_size", + "in": "query" + }, + { + "type": "integer", + "description": "是否是我的", + "name": "is_my", + "in": "query" + }, + { + "type": "integer", + "description": "用户id", + "name": "user_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollectionList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection/update": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合编辑", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合编辑", + "parameters": [ + { + "description": "地址簿集合信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/create": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "创建地址簿集合规则", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "创建地址簿集合规则", + "parameters": [ + { + "description": "地址簿集合规则信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollectionRule" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/delete": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合规则删除", + "parameters": [ + { + "description": "地址簿集合规则信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollectionRule" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/detail/{id}": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "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.AddressBookCollectionRule" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/list": { + "get": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合规则列表", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "页大小", + "name": "page_size", + "in": "query" + }, + { + "type": "integer", + "description": "是否是我的", + "name": "is_my", + "in": "query" + }, + { + "type": "integer", + "description": "用户id", + "name": "user_id", + "in": "query" + }, + { + "type": "integer", + "description": "地址簿集合id", + "name": "collection_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollectionList" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/admin/address_book_collection_rule/update": { + "post": { + "security": [ + { + "token": [] + } + ], + "description": "地址簿集合规则编辑", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "地址簿集合规则编辑", + "parameters": [ + { + "description": "地址簿集合规则信息", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddressBookCollectionRule" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.AddressBookCollection" + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/admin/app-config": { "get": { "security": [ @@ -2473,6 +3021,9 @@ "alias": { "type": "string" }, + "collection_id": { + "type": "integer" + }, "forceAlwaysRelay": { "type": "boolean" }, @@ -2694,6 +3245,9 @@ "name" ], "properties": { + "collection_id": { + "type": "integer" + }, "color": { "type": "integer" }, @@ -2781,6 +3335,12 @@ "alias": { "type": "string" }, + "collection": { + "$ref": "#/definitions/model.AddressBookCollection" + }, + "collection_id": { + "type": "integer" + }, "created_at": { "type": "string" }, @@ -2837,6 +3397,90 @@ } } }, + "model.AddressBookCollection": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, + "model.AddressBookCollectionList": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.AddressBookCollection" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "model.AddressBookCollectionRule": { + "type": "object", + "required": [ + "collection_id", + "rule", + "to_id", + "type" + ], + "properties": { + "collection_id": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rule": { + "description": "0: 无 1: 读 2: 读写 3: 完全控制", + "type": "integer", + "maximum": 3, + "minimum": 1 + }, + "to_id": { + "type": "integer" + }, + "type": { + "description": "1: 个人 2: 群组", + "type": "integer", + "maximum": 2, + "minimum": 1 + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, "model.AddressBookList": { "type": "object", "properties": { @@ -3214,6 +3858,12 @@ "model.Tag": { "type": "object", "properties": { + "collection": { + "$ref": "#/definitions/model.AddressBookCollection" + }, + "collection_id": { + "type": "integer" + }, "color": { "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba", "type": "integer" diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml index 980891a..ea9d4f9 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -16,6 +16,8 @@ definitions: properties: alias: type: string + collection_id: + type: integer forceAlwaysRelay: type: boolean hash: @@ -164,6 +166,8 @@ definitions: type: object admin.TagForm: properties: + collection_id: + type: integer color: type: integer id: @@ -225,6 +229,10 @@ definitions: properties: alias: type: string + collection: + $ref: '#/definitions/model.AddressBookCollection' + collection_id: + type: integer created_at: type: string forceAlwaysRelay: @@ -262,6 +270,64 @@ definitions: username: type: string type: object + model.AddressBookCollection: + properties: + created_at: + type: string + id: + type: integer + name: + type: string + updated_at: + type: string + user_id: + type: integer + required: + - name + type: object + model.AddressBookCollectionList: + properties: + list: + items: + $ref: '#/definitions/model.AddressBookCollection' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + model.AddressBookCollectionRule: + properties: + collection_id: + type: integer + created_at: + type: string + id: + type: integer + rule: + description: '0: 无 1: 读 2: 读写 3: 完全控制' + maximum: 3 + minimum: 1 + type: integer + to_id: + type: integer + type: + description: '1: 个人 2: 群组' + maximum: 2 + minimum: 1 + type: integer + updated_at: + type: string + user_id: + type: integer + required: + - collection_id + - rule + - to_id + - type + type: object model.AddressBookList: properties: list: @@ -511,6 +577,10 @@ definitions: - COMMON_STATUS_DISABLED model.Tag: properties: + collection: + $ref: '#/definitions/model.AddressBookCollection' + collection_id: + type: integer color: description: color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba @@ -784,6 +854,328 @@ paths: summary: 地址簿编辑 tags: - 地址簿 + /admin/address_book_collection/create: + post: + consumes: + - application/json + description: 创建地址簿集合 + parameters: + - description: 地址簿集合信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AddressBookCollection' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AddressBookCollection' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 创建地址簿集合 + /admin/address_book_collection/delete: + post: + consumes: + - application/json + description: 地址簿集合删除 + parameters: + - description: 地址簿集合信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AddressBookCollection' + 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: 地址簿集合删除 + /admin/address_book_collection/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.AddressBookCollection' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 地址簿集合详情 + /admin/address_book_collection/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: is_my + type: integer + - description: 用户id + in: query + name: user_id + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AddressBookCollectionList' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 地址簿集合列表 + /admin/address_book_collection/update: + post: + consumes: + - application/json + description: 地址簿集合编辑 + parameters: + - description: 地址簿集合信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AddressBookCollection' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AddressBookCollection' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 地址簿集合编辑 + /admin/address_book_collection_rule/create: + post: + consumes: + - application/json + description: 创建地址簿集合规则 + parameters: + - description: 地址簿集合规则信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AddressBookCollectionRule' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AddressBookCollection' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 创建地址簿集合规则 + /admin/address_book_collection_rule/delete: + post: + consumes: + - application/json + description: 地址簿集合规则删除 + parameters: + - description: 地址簿集合规则信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AddressBookCollectionRule' + 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: 地址簿集合规则删除 + /admin/address_book_collection_rule/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.AddressBookCollectionRule' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 地址簿集合规则详情 + /admin/address_book_collection_rule/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: is_my + type: integer + - description: 用户id + in: query + name: user_id + type: integer + - description: 地址簿集合id + in: query + name: collection_id + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AddressBookCollectionList' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 地址簿集合规则列表 + /admin/address_book_collection_rule/update: + post: + consumes: + - application/json + description: 地址簿集合规则编辑 + parameters: + - description: 地址簿集合规则信息 + in: body + name: body + required: true + schema: + $ref: '#/definitions/model.AddressBookCollectionRule' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/model.AddressBookCollection' + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - token: [] + summary: 地址簿集合规则编辑 /admin/app-config: get: consumes: diff --git a/docs/api/api_docs.go b/docs/api/api_docs.go index 81a342e..b2fd617 100644 --- a/docs/api/api_docs.go +++ b/docs/api/api_docs.go @@ -1445,9 +1445,38 @@ const docTemplateapi = `{ } } }, + "model.AddressBookCollection": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, "model.Tag": { "type": "object", "properties": { + "collection": { + "$ref": "#/definitions/model.AddressBookCollection" + }, + "collection_id": { + "type": "integer" + }, "color": { "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba", "type": "integer" diff --git a/docs/api/api_swagger.json b/docs/api/api_swagger.json index ed95d19..4a4ccc5 100644 --- a/docs/api/api_swagger.json +++ b/docs/api/api_swagger.json @@ -1438,9 +1438,38 @@ } } }, + "model.AddressBookCollection": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, "model.Tag": { "type": "object", "properties": { + "collection": { + "$ref": "#/definitions/model.AddressBookCollection" + }, + "collection_id": { + "type": "integer" + }, "color": { "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba", "type": "integer" diff --git a/docs/api/api_swagger.yaml b/docs/api/api_swagger.yaml index 2e5e949..2bd93b4 100644 --- a/docs/api/api_swagger.yaml +++ b/docs/api/api_swagger.yaml @@ -124,8 +124,27 @@ definitions: status: type: integer type: object + model.AddressBookCollection: + properties: + created_at: + type: string + id: + type: integer + name: + type: string + updated_at: + type: string + user_id: + type: integer + required: + - name + type: object model.Tag: properties: + collection: + $ref: '#/definitions/model.AddressBookCollection' + collection_id: + type: integer color: description: color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba diff --git a/http/controller/admin/addressBook.go b/http/controller/admin/addressBook.go index 4bbefc7..49cbc34 100644 --- a/http/controller/admin/addressBook.go +++ b/http/controller/admin/addressBook.go @@ -70,9 +70,14 @@ func (ct *AddressBook) Create(c *gin.Context) { if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 { t.UserId = u.Id } - ex := service.AllService.AddressBookService.InfoByUserIdAndId(t.UserId, t.Id) + if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")) + return + } + + ex := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(t.UserId, t.Id, t.CollectionId) if ex.RowId > 0 { - response.Fail(c, 101, response.TranslateMsg(c, "ItemExist")) + response.Fail(c, 101, response.TranslateMsg(c, "ItemExists")) return } @@ -81,7 +86,7 @@ func (ct *AddressBook) Create(c *gin.Context) { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) return } - response.Success(c, u) + response.Success(c, nil) } // BatchCreate 批量创建地址簿 @@ -113,7 +118,7 @@ func (ct *AddressBook) BatchCreate(c *gin.Context) { continue } for _, ft := range f.Tags { - exTag := service.AllService.TagService.InfoByUserIdAndName(fu, ft) + exTag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(fu, ft, 0) if exTag.Id == 0 { service.AllService.TagService.Create(&model.Tag{ UserId: fu, @@ -161,6 +166,9 @@ func (ct *AddressBook) List(c *gin.Context) { query.UserId = int(u.Id) } res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) { + tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB { + return txc.Select("id,name") + }) if query.Id != "" { tx.Where("id like ?", "%"+query.Id+"%") } @@ -173,7 +181,20 @@ func (ct *AddressBook) List(c *gin.Context) { if query.Hostname != "" { tx.Where("hostname like ?", "%"+query.Hostname+"%") } + if query.CollectionId != nil && *query.CollectionId >= 0 { + tx.Where("collection_id = ?", query.CollectionId) + } }) + + abCIds := make([]uint, 0) + for _, ab := range res.AddressBooks { + abCIds = append(abCIds, ab.CollectionId) + } + //获取地址簿名称 + //cRes := service.AllService.AddressBookService.ListCollection(1, 999, func(tx *gorm.DB) { + // tx.Where("id in ?", abCIds) + //}) + // response.Success(c, res) } @@ -209,6 +230,10 @@ func (ct *AddressBook) Update(c *gin.Context) { response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) return } + if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")) + return + } err := service.AllService.AddressBookService.Update(t) if err != nil { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) @@ -241,6 +266,10 @@ func (ct *AddressBook) Delete(c *gin.Context) { return } t := service.AllService.AddressBookService.InfoByRowId(f.RowId) + if t.RowId == 0 { + response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound")) + return + } u := service.AllService.UserService.CurUser(c) if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) diff --git a/http/controller/admin/addressBookCollection.go b/http/controller/admin/addressBookCollection.go new file mode 100644 index 0000000..529cedb --- /dev/null +++ b/http/controller/admin/addressBookCollection.go @@ -0,0 +1,192 @@ +package admin + +import ( + "Gwen/global" + "Gwen/http/request/admin" + "Gwen/http/response" + "Gwen/model" + "Gwen/service" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "strconv" +) + +type AddressBookCollection struct { +} + +// Detail 地址簿集合 +// @AddressBookCollections 地址簿集合 +// @Summary 地址簿集合详情 +// @Description 地址簿集合详情 +// @Accept json +// @Produce json +// @Param id path int true "ID" +// @Success 200 {object} response.Response{data=model.AddressBookCollection} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection/detail/{id} [get] +// @Security token +func (abc *AddressBookCollection) Detail(c *gin.Context) { + id := c.Param("id") + iid, _ := strconv.Atoi(id) + t := service.AllService.AddressBookService.CollectionInfoById(uint(iid)) + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { + response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) + return + } + if t.Id > 0 { + response.Success(c, t) + return + } + response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound")) + return +} + +// Create 创建地址簿集合 +// @AddressBookCollections 地址簿集合 +// @Summary 创建地址簿集合 +// @Description 创建地址簿集合 +// @Accept json +// @Produce json +// @Param body body model.AddressBookCollection true "地址簿集合信息" +// @Success 200 {object} response.Response{data=model.AddressBookCollection} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection/create [post] +// @Security token +func (abc *AddressBookCollection) Create(c *gin.Context) { + f := &model.AddressBookCollection{} + 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 + } + //t := f.ToAddressBookCollection() + t := f + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 { + t.UserId = u.Id + } + err := service.AllService.AddressBookService.CreateCollection(t) + if err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Success(c, nil) +} + +// List 列表 +// @AddressBookCollections 地址簿集合 +// @Summary 地址簿集合列表 +// @Description 地址簿集合列表 +// @Accept json +// @Produce json +// @Param page query int false "页码" +// @Param page_size query int false "页大小" +// @Param is_my query int false "是否是我的" +// @Param user_id query int false "用户id" +// @Success 200 {object} response.Response{data=model.AddressBookCollectionList} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection/list [get] +// @Security token +func (abc *AddressBookCollection) List(c *gin.Context) { + query := &admin.AddressBookCollectionQuery{} + if err := c.ShouldBindQuery(query); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 { + query.UserId = int(u.Id) + } + res := service.AllService.AddressBookService.ListCollection(query.Page, query.PageSize, func(tx *gorm.DB) { + if query.UserId > 0 { + tx.Where("user_id = ?", query.UserId) + } + }) + response.Success(c, res) +} + +// Update 编辑 +// @AddressBookCollections 地址簿集合 +// @Summary 地址簿集合编辑 +// @Description 地址簿集合编辑 +// @Accept json +// @Produce json +// @Param body body model.AddressBookCollection true "地址簿集合信息" +// @Success 200 {object} response.Response{data=model.AddressBookCollection} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection/update [post] +// @Security token +func (abc *AddressBookCollection) Update(c *gin.Context) { + f := &model.AddressBookCollection{} + 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 + } + if f.Id == 0 { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")) + return + } + t := f //f.ToAddressBookCollection() + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { + response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) + return + } + err := service.AllService.AddressBookService.UpdateCollection(t) + if err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Success(c, nil) +} + +// Delete 删除 +// @AddressBookCollections 地址簿集合 +// @Summary 地址簿集合删除 +// @Description 地址簿集合删除 +// @Accept json +// @Produce json +// @Param body body model.AddressBookCollection true "地址簿集合信息" +// @Success 200 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection/delete [post] +// @Security token +func (abc *AddressBookCollection) Delete(c *gin.Context) { + f := &model.AddressBookCollection{} + 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 + } + t := service.AllService.AddressBookService.CollectionInfoById(f.Id) + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { + response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) + return + } + if u.Id > 0 { + err := service.AllService.AddressBookService.DeleteCollection(t) + 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/admin/addressBookCollectionRule.go b/http/controller/admin/addressBookCollectionRule.go new file mode 100644 index 0000000..7d84e09 --- /dev/null +++ b/http/controller/admin/addressBookCollectionRule.go @@ -0,0 +1,251 @@ +package admin + +import ( + "Gwen/global" + "Gwen/http/request/admin" + "Gwen/http/response" + "Gwen/model" + "Gwen/service" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "strconv" +) + +type AddressBookCollectionRule struct { +} + +// List 列表 +// @AddressBookCollectionRule 地址簿集合规则 +// @Summary 地址簿集合规则列表 +// @Description 地址簿集合规则列表 +// @Accept json +// @Produce json +// @Param page query int false "页码" +// @Param page_size query int false "页大小" +// @Param is_my query int false "是否是我的" +// @Param user_id query int false "用户id" +// @Param collection_id query int false "地址簿集合id" +// @Success 200 {object} response.Response{data=model.AddressBookCollectionList} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection_rule/list [get] +// @Security token +func (abcr *AddressBookCollectionRule) List(c *gin.Context) { + query := &admin.AddressBookCollectionRuleQuery{} + if err := c.ShouldBindQuery(query); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 { + query.UserId = int(u.Id) + } + + res := service.AllService.AddressBookService.ListRules(query.Page, query.PageSize, func(tx *gorm.DB) { + if query.UserId > 0 { + tx.Where("user_id = ?", query.UserId) + } + if query.CollectionId > 0 { + tx.Where("collection_id = ?", query.CollectionId) + } + }) + response.Success(c, res) +} + +// Detail 地址簿集合规则 +// @AddressBookCollectionRule 地址簿集合规则 +// @Summary 地址簿集合规则详情 +// @Description 地址簿集合规则详情 +// @Accept json +// @Produce json +// @Param id path int true "ID" +// @Success 200 {object} response.Response{data=model.AddressBookCollectionRule} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection_rule/detail/{id} [get] +// @Security token +func (abcr *AddressBookCollectionRule) Detail(c *gin.Context) { + id := c.Param("id") + iid, _ := strconv.Atoi(id) + t := service.AllService.AddressBookService.RuleInfoById(uint(iid)) + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { + response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) + return + } + if t.Id > 0 { + response.Success(c, t) + return + } + response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound")) + return +} + +// Create 创建地址簿集合规则 +// @AddressBookCollectionRule 地址簿集合规则 +// @Summary 创建地址簿集合规则 +// @Description 创建地址簿集合规则 +// @Accept json +// @Produce json +// @Param body body model.AddressBookCollectionRule true "地址簿集合规则信息" +// @Success 200 {object} response.Response{data=model.AddressBookCollection} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection_rule/create [post] +// @Security token +func (abcr *AddressBookCollectionRule) Create(c *gin.Context) { + f := &model.AddressBookCollectionRule{} + 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 + } + if f.Type != model.ShareAddressBookRuleTypePersonal && f.Type != model.ShareAddressBookRuleTypeGroup { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")) + return + } + //t := f.ToAddressBookCollection() + t := f + u := service.AllService.UserService.CurUser(c) + if t.UserId == 0 { + t.UserId = u.Id + } + msg, res := abcr.CheckForm(u, t) + if !res { + response.Fail(c, 101, response.TranslateMsg(c, msg)) + return + } + err := service.AllService.AddressBookService.CreateRule(t) + if err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Success(c, nil) +} + +func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.AddressBookCollectionRule) (string, bool) { + if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { + return "NoAccess", false + } + if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) { + return "ParamsError", false + } + + //check to_id + if t.Type == model.ShareAddressBookRuleTypePersonal { + if t.ToId == t.UserId { + return "ParamsError", false + } + tou := service.AllService.UserService.InfoById(t.ToId) + if tou.Id == 0 { + return "ItemNotFound", false + } + //非管理员不能分享给非本组织用户 + if tou.GroupId != u.GroupId && !service.AllService.UserService.IsAdmin(u) { + return "NoAccess", false + } + } else if t.Type == model.ShareAddressBookRuleTypeGroup { + if t.ToId != u.GroupId && !service.AllService.UserService.IsAdmin(u) { + return "NoAccess", false + } + + tog := service.AllService.GroupService.InfoById(t.ToId) + if tog.Id == 0 { + return "ItemNotFound", false + } + } else { + return "ParamsError", false + } + // 重复检查 + ex := service.AllService.AddressBookService.RulePersonalInfoByToIdAndCid(t.ToId, t.CollectionId) + if t.Id == 0 && ex.Id > 0 { + return "ItemExists", false + } + if t.Id > 0 && ex.Id > 0 && t.Id != ex.Id { + return "ItemExists", false + } + return "", true +} + +// Update 编辑 +// @AddressBookCollectionRule 地址簿集合规则 +// @Summary 地址簿集合规则编辑 +// @Description 地址簿集合规则编辑 +// @Accept json +// @Produce json +// @Param body body model.AddressBookCollectionRule true "地址簿集合规则信息" +// @Success 200 {object} response.Response{data=model.AddressBookCollection} +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection_rule/update [post] +// @Security token +func (abcr *AddressBookCollectionRule) Update(c *gin.Context) { + f := &model.AddressBookCollectionRule{} + 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 + } + if f.Id == 0 { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")) + return + } + t := f //f.ToAddressBookCollection() + u := service.AllService.UserService.CurUser(c) + msg, res := abcr.CheckForm(u, t) + if !res { + response.Fail(c, 101, response.TranslateMsg(c, msg)) + return + } + err := service.AllService.AddressBookService.UpdateRule(t) + if err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) + return + } + response.Success(c, nil) +} + +// Delete 删除 +// @AddressBookCollectionRule 地址簿集合规则 +// @Summary 地址簿集合规则删除 +// @Description 地址簿集合规则删除 +// @Accept json +// @Produce json +// @Param body body model.AddressBookCollectionRule true "地址簿集合规则信息" +// @Success 200 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /admin/address_book_collection_rule/delete [post] +// @Security token +func (abcr *AddressBookCollectionRule) Delete(c *gin.Context) { + f := &model.AddressBookCollectionRule{} + 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 + } + t := service.AllService.AddressBookService.RuleInfoById(f.Id) + u := service.AllService.UserService.CurUser(c) + if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id { + response.Fail(c, 101, response.TranslateMsg(c, "NoAccess")) + return + } + if t.Id > 0 { + err := service.AllService.AddressBookService.DeleteRule(t) + 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/admin/audit.go b/http/controller/admin/audit.go index b771cea..cb56ddb 100644 --- a/http/controller/admin/audit.go +++ b/http/controller/admin/audit.go @@ -40,6 +40,7 @@ func (a *Audit) ConnList(c *gin.Context) { if query.FromPeer != "" { tx.Where("from_peer like ?", "%"+query.FromPeer+"%") } + tx.Order("id desc") }) response.Success(c, res) } @@ -107,6 +108,7 @@ func (a *Audit) FileList(c *gin.Context) { if query.FromPeer != "" { tx.Where("from_peer like ?", "%"+query.FromPeer+"%") } + tx.Order("id desc") }) response.Success(c, res) } diff --git a/http/controller/admin/group.go b/http/controller/admin/group.go index 2b189ee..0466f17 100644 --- a/http/controller/admin/group.go +++ b/http/controller/admin/group.go @@ -63,7 +63,7 @@ func (ct *Group) Create(c *gin.Context) { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) return } - response.Success(c, u) + response.Success(c, nil) } // List 列表 diff --git a/http/controller/admin/loginLog.go b/http/controller/admin/loginLog.go index f653c17..f6daf1c 100644 --- a/http/controller/admin/loginLog.go +++ b/http/controller/admin/loginLog.go @@ -64,6 +64,7 @@ func (ct *LoginLog) List(c *gin.Context) { if query.UserId > 0 { tx.Where("user_id = ?", query.UserId) } + tx.Order("id desc") }) response.Success(c, res) } diff --git a/http/controller/admin/oauth.go b/http/controller/admin/oauth.go index 8a569a1..a3571f2 100644 --- a/http/controller/admin/oauth.go +++ b/http/controller/admin/oauth.go @@ -202,7 +202,7 @@ func (o *Oauth) Create(c *gin.Context) { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) return } - response.Success(c, u) + response.Success(c, nil) } // List 列表 diff --git a/http/controller/admin/peer.go b/http/controller/admin/peer.go index ba0c850..806eaae 100644 --- a/http/controller/admin/peer.go +++ b/http/controller/admin/peer.go @@ -59,13 +59,13 @@ func (ct *Peer) Create(c *gin.Context) { response.Fail(c, 101, errList[0]) return } - u := f.ToPeer() - err := service.AllService.PeerService.Create(u) + p := f.ToPeer() + err := service.AllService.PeerService.Create(p) if err != nil { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) return } - response.Success(c, u) + response.Success(c, nil) } // List 列表 diff --git a/http/controller/admin/tag.go b/http/controller/admin/tag.go index 4956f07..a41e1e4 100644 --- a/http/controller/admin/tag.go +++ b/http/controller/admin/tag.go @@ -73,7 +73,7 @@ func (ct *Tag) Create(c *gin.Context) { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) return } - response.Success(c, u) + response.Success(c, nil) } // List 列表 @@ -101,9 +101,15 @@ func (ct *Tag) List(c *gin.Context) { query.UserId = int(u.Id) } res := service.AllService.TagService.List(query.Page, query.PageSize, func(tx *gorm.DB) { + tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB { + return txc.Select("id,name") + }) if query.UserId > 0 { tx.Where("user_id = ?", query.UserId) } + if query.CollectionId != nil && *query.CollectionId >= 0 { + tx.Where("collection_id = ?", query.CollectionId) + } }) response.Success(c, res) } diff --git a/http/controller/admin/user.go b/http/controller/admin/user.go index 82a6d64..9f7415c 100644 --- a/http/controller/admin/user.go +++ b/http/controller/admin/user.go @@ -65,7 +65,7 @@ func (ct *User) Create(c *gin.Context) { response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error()) return } - response.Success(c, u) + response.Success(c, nil) } // List 列表 @@ -293,3 +293,33 @@ func (ct *User) MyOauth(c *gin.Context) { } response.Success(c, res) } + +// groupUsers +func (ct *User) GroupUsers(c *gin.Context) { + q := &admin.GroupUsersQuery{} + if err := c.ShouldBindJSON(q); err != nil { + response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error()) + return + } + u := service.AllService.UserService.CurUser(c) + gid := u.GroupId + uid := u.Id + if service.AllService.UserService.IsAdmin(u) && q.UserId > 0 { + nu := service.AllService.UserService.InfoById(q.UserId) + gid = nu.GroupId + uid = q.UserId + } + res := service.AllService.UserService.List(1, 999, func(tx *gorm.DB) { + tx.Where("group_id = ?", gid) + }) + var data []*adResp.GroupUsersPayload + for _, _u := range res.Users { + gup := &adResp.GroupUsersPayload{} + gup.FromUser(_u) + if _u.Id == uid { + gup.Status = 0 + } + data = append(data, gup) + } + response.Success(c, data) +} diff --git a/http/controller/api/ab.go b/http/controller/api/ab.go index 3bdf4d3..6509ba7 100644 --- a/http/controller/api/ab.go +++ b/http/controller/api/ab.go @@ -7,10 +7,13 @@ import ( "Gwen/http/response/api" "Gwen/model" "Gwen/service" + "Gwen/utils" "encoding/json" + "errors" "github.com/gin-gonic/gin" "net/http" "strconv" + "strings" ) type Ab struct { @@ -112,6 +115,35 @@ func (a *Ab) Tags(c *gin.Context) { c.JSON(http.StatusOK, tags.Tags) } +// PTags +// @Tags 地址[Personal] +// @Summary 标签 +// @Description 标签 +// @Accept json +// @Produce json +// @Param guid path string true "guid" +// @Success 200 {object} model.TagList +// @Failure 500 {object} response.ErrorResponse +// @Router /ab/tags/{guid} [post] +// @Security BearerAuth +func (a *Ab) PTags(c *gin.Context) { + u := service.AllService.UserService.CurUser(c) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserReadPrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + tags := service.AllService.TagService.ListByUserIdAndCollectionId(uid, cid) + c.JSON(http.StatusOK, tags.Tags) +} + // TagAdd // @Tags 地址[Personal] // @Summary 标签添加 @@ -124,19 +156,35 @@ func (a *Ab) Tags(c *gin.Context) { // @Router /ab/tag/add/{guid} [post] // @Security BearerAuth func (a *Ab) TagAdd(c *gin.Context) { + t := &model.Tag{} err := c.ShouldBindJSON(t) if err != nil { 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) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + + tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.Name, cid) if tag != nil && tag.Id != 0 { response.Error(c, response.TranslateMsg(c, "ItemExists")) return } - t.UserId = u.Id + t.UserId = uid + t.CollectionId = cid err = service.AllService.TagService.Create(t) if err != nil { response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error()) @@ -157,6 +205,7 @@ func (a *Ab) TagAdd(c *gin.Context) { // @Router /ab/tag/rename/{guid} [put] // @Security BearerAuth func (a *Ab) TagRename(c *gin.Context) { + t := &requstform.TagRenameForm{} err := c.ShouldBindJSON(t) if err != nil { @@ -164,12 +213,25 @@ func (a *Ab) TagRename(c *gin.Context) { return } u := service.AllService.UserService.CurUser(c) - tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Old) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + + tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.Old, cid) if tag == nil || tag.Id == 0 { response.Error(c, response.TranslateMsg(c, "ItemNotFound")) return } - ntag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.New) + ntag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.New, cid) if ntag != nil && ntag.Id != 0 { response.Error(c, response.TranslateMsg(c, "ItemExists")) return @@ -202,7 +264,20 @@ func (a *Ab) TagUpdate(c *gin.Context) { return } u := service.AllService.UserService.CurUser(c) - tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + + tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.Name, cid) if tag == nil || tag.Id == 0 { response.Error(c, response.TranslateMsg(c, "ItemNotFound")) return @@ -228,6 +303,7 @@ func (a *Ab) TagUpdate(c *gin.Context) { // @Router /ab/tag/{guid} [delete] // @Security BearerAuth func (a *Ab) TagDel(c *gin.Context) { + t := &[]string{} err := c.ShouldBind(t) if err != nil { @@ -236,8 +312,21 @@ func (a *Ab) TagDel(c *gin.Context) { } //fmt.Println(t) u := service.AllService.UserService.CurUser(c) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserFullControlPrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + for _, name := range *t { - tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, name) + tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, name, cid) if tag == nil || tag.Id == 0 { response.Error(c, response.TranslateMsg(c, "ItemNotFound")) return @@ -272,7 +361,7 @@ func (a *Ab) Personal(c *gin.Context) { rule = json['rule'] ?? 0; */ if global.Config.Rustdesk.Personal == 1 { - guid := strconv.Itoa(int(user.GroupId)) + "-" + strconv.Itoa(int(user.Id)) + guid := a.ComposeGuid(user.GroupId, user.Id, 0) //如果返回了guid,后面的请求会有变化 c.JSON(http.StatusOK, gin.H{ "guid": guid, @@ -315,38 +404,139 @@ func (a *Ab) Settings(c *gin.Context) { // @Router /ab/shared/profiles [post] // @Security BearerAuth func (a *Ab) SharedProfiles(c *gin.Context) { - //AbProfile.fromJson(Map json) - //: guid = json['guid'] ?? '', - // name = json['name'] ?? '', - // owner = json['owner'] ?? '', - // note = json['note'] ?? '', - // rule = json['rule'] ?? 0; - //暂时没必要返回数据,可能是为了共享地址簿 - /*item := map[string]interface{}{ - "guid": "1", - "name": "admin", - "owner": "admin", - "note": "admin11", - "rule": 3, + + var res []*api.SharedProfilesPayload + + user := service.AllService.UserService.CurUser(c) + myAbCollectionList := service.AllService.AddressBookService.ListCollectionByUserId(user.Id) + for _, ab := range myAbCollectionList.AddressBookCollection { + res = append(res, &api.SharedProfilesPayload{ + Guid: a.ComposeGuid(user.GroupId, user.Id, ab.Id), + Name: ab.Name, + Owner: user.Username, + Rule: model.ShareAddressBookRuleRuleFullControl, + }) } - item2 := map[string]interface{}{ - "guid": "2", - "name": "admin2", - "owner": "admin2", - "note": "admin22", - "rule": 2, + + allAbIds := make(map[uint]int) //用map去重,并保留最大Rule + allUserIds := make(map[uint]*model.User) + rules := service.AllService.AddressBookService.CollectionReadRules(user) + for _, rule := range rules { + //先判断是否存在 + r, ok := allAbIds[rule.CollectionId] + if ok { + //再判断权限大小 + if r < rule.Rule { + allAbIds[rule.CollectionId] = rule.Rule + } + } else { + allAbIds[rule.CollectionId] = rule.Rule + allUserIds[rule.UserId] = nil + } + + } + abids := utils.Keys(allAbIds) + collections := service.AllService.AddressBookService.ListCollectionByIds(abids) + + ids := utils.Keys(allUserIds) + allUsers := service.AllService.UserService.ListByIds(ids) + for _, u := range allUsers { + allUserIds[u.Id] = u + } + + for _, collection := range collections { + _u, ok := allUserIds[collection.UserId] + if !ok { + continue + } + res = append(res, &api.SharedProfilesPayload{ + Guid: a.ComposeGuid(_u.GroupId, _u.Id, collection.Id), + Name: collection.Name, + Owner: _u.Username, + Rule: allAbIds[collection.Id], + }) } - c.JSON(http.StatusOK, gin.H{ - "total": 2, - "data": []interface{}{item, item2}, - })*/ c.JSON(http.StatusOK, gin.H{ - "total": 0, - "data": nil, + "total": 0, //len(res), + "data": res, }) } +// ParseGuid +func (a *Ab) ParseGuid(guid string) (gid, uid, cid uint) { + //用-切割 guid + guids := strings.Split(guid, "-") + if len(guids) < 2 { + return 0, 0, 0 + } + if len(guids) != 3 { + cid = 0 + } else { + s, err := strconv.Atoi(guids[2]) + if err != nil { + return 0, 0, 0 + } + cid = uint(s) + } + g, err := strconv.Atoi(guids[0]) + if err != nil { + return 0, 0, 0 + } + gid = uint(g) + u, err := strconv.Atoi(guids[1]) + if err != nil { + return 0, 0, 0 + } + uid = uint(u) + return +} + +// ComposeGuid +func (a *Ab) ComposeGuid(gid, uid, cid uint) string { + return strconv.Itoa(int(gid)) + "-" + strconv.Itoa(int(uid)) + "-" + strconv.Itoa(int(cid)) +} + +// CheckGuid +func (a *Ab) CheckGuid(cu *model.User, guid string) (gid, uid, cid uint, err error) { + gid, uid, cid = a.ParseGuid(guid) + err = nil + if gid == 0 || uid == 0 { + err = errors.New("ParamsError") + return + } + u := &model.User{} + if cu.Id == uid { + u = cu + } else { + u = service.AllService.UserService.InfoById(uid) + } + if u == nil || u.Id == 0 { + err = errors.New("ParamsError") + return + } + if u.GroupId != gid { + err = errors.New("ParamsError") + return + } + if cid == 0 && cu.Id != uid { + err = errors.New("ParamsError") + return + } + if cid > 0 { + c := service.AllService.AddressBookService.CollectionInfoById(cid) + if c == nil || c.Id == 0 { + err = errors.New("ParamsError") + return + } + if c.UserId != uid { + err = errors.New("ParamsError") + return + } + } + return +} + // Peers // @Tags 地址[Personal] // @Summary 地址列表 @@ -361,8 +551,21 @@ func (a *Ab) SharedProfiles(c *gin.Context) { // @Router /ab/peers [post] // @Security BearerAuth func (a *Ab) Peers(c *gin.Context) { - user := service.AllService.UserService.CurUser(c) - al := service.AllService.AddressBookService.ListByUserId(user.Id, 1, 1000) + u := service.AllService.UserService.CurUser(c) + guid := c.Query("ab") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserReadPrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + + al := service.AllService.AddressBookService.ListByUserIdAndCollectionId(uid, cid, 1, 1000) c.JSON(http.StatusOK, gin.H{ "total": al.Total, "data": al.AddressBooks, @@ -370,24 +573,6 @@ func (a *Ab) Peers(c *gin.Context) { }) } -// PTags -// @Tags 地址[Personal] -// @Summary 标签 -// @Description 标签 -// @Accept json -// @Produce json -// @Param guid path string true "guid" -// @Success 200 {object} model.TagList -// @Failure 500 {object} response.ErrorResponse -// @Router /ab/tags/{guid} [post] -// @Security BearerAuth -func (a *Ab) PTags(c *gin.Context) { - user := service.AllService.UserService.CurUser(c) - - tags := service.AllService.TagService.ListByUserId(user.Id) - c.JSON(http.StatusOK, tags.Tags) -} - // PeerAdd // @Tags 地址[Personal] // @Summary 添加地址 @@ -402,18 +587,31 @@ 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 { response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error()) return } - //fmt.Println(f) - u := service.AllService.UserService.CurUser(c) - f.UserId = u.Id - ab := f.ToAddressBook() + u := service.AllService.UserService.CurUser(c) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + + //fmt.Println(f) + f.UserId = uid + ab := f.ToAddressBook() + ab.CollectionId = cid if ab.Platform == "" || ab.Username == "" || ab.Hostname == "" { peer := service.AllService.PeerService.FindById(ab.Id) if peer.RowId != 0 { @@ -450,8 +648,21 @@ func (a *Ab) PeerDel(c *gin.Context) { return } u := service.AllService.UserService.CurUser(c) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserFullControlPrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + for _, id := range *f { - ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, id) + ab := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(uid, id, cid) if ab == nil || ab.RowId == 0 { response.Error(c, response.TranslateMsg(c, "ItemNotFound")) return @@ -485,10 +696,23 @@ func (a *Ab) PeerUpdate(c *gin.Context) { response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error()) return } + u := service.AllService.UserService.CurUser(c) + guid := c.Param("guid") + _, uid, cid, err := a.CheckGuid(u, guid) + if err != nil { + response.Error(c, response.TranslateMsg(c, err.Error())) + return + } + + //check privileges + if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) { + response.Error(c, response.TranslateMsg(c, "NoAccess")) + return + } + //fmt.Println(f) //return - u := service.AllService.UserService.CurUser(c) - ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, f.Id) + ab := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(uid, f.Id, cid) if ab == nil || ab.RowId == 0 { response.Error(c, response.TranslateMsg(c, "ItemNotFound")) return diff --git a/http/controller/api/index.go b/http/controller/api/index.go index 7f780dd..cb82009 100644 --- a/http/controller/api/index.go +++ b/http/controller/api/index.go @@ -50,7 +50,7 @@ func (i *Index) Heartbeat(c *gin.Context) { return } peer := service.AllService.PeerService.FindByUuid(info.Uuid) - if peer == nil { + if peer == nil || peer.RowId == 0 { c.JSON(http.StatusOK, gin.H{}) return } diff --git a/http/request/admin/addressBook.go b/http/request/admin/addressBook.go index 168c14b..615a666 100644 --- a/http/request/admin/addressBook.go +++ b/http/request/admin/addressBook.go @@ -23,6 +23,7 @@ type AddressBookForm struct { Online bool `json:"online"` LoginName string `json:"loginName" ` SameServer bool `json:"sameServer"` + CollectionId uint `json:"collection_id"` } func (a AddressBookForm) ToAddressBook() *model.AddressBook { @@ -46,6 +47,7 @@ func (a AddressBookForm) ToAddressBook() *model.AddressBook { Online: a.Online, LoginName: a.LoginName, SameServer: a.SameServer, + CollectionId: a.CollectionId, } } @@ -72,17 +74,19 @@ func (a AddressBookForm) ToAddressBooks() []*model.AddressBook { Online: a.Online, LoginName: a.LoginName, SameServer: a.SameServer, + CollectionId: a.CollectionId, }) } return abs } type AddressBookQuery struct { - UserId int `form:"user_id"` - IsMy int `form:"is_my"` - Username string `form:"username"` - Hostname string `form:"hostname"` - Id string `form:"id"` + UserId int `form:"user_id"` + CollectionId *int `form:"collection_id"` + IsMy int `form:"is_my"` + Username string `form:"username"` + Hostname string `form:"hostname"` + Id string `form:"id"` PageQuery } @@ -102,3 +106,19 @@ func (sbwcf ShareByWebClientForm) ToShareRecord() *model.ShareRecord { Expire: sbwcf.Expire, } } + +type AddressBookCollectionQuery struct { + UserId int `form:"user_id"` + IsMy int `form:"is_my"` + PageQuery +} + +type AddressBookCollectionSimpleListQuery struct { + UserIds []uint `form:"user_ids"` +} +type AddressBookCollectionRuleQuery struct { + UserId int `form:"user_id"` + CollectionId int `form:"collection_id"` + IsMy int `form:"is_my"` + PageQuery +} diff --git a/http/request/admin/tag.go b/http/request/admin/tag.go index dc088c8..7ecc2f5 100644 --- a/http/request/admin/tag.go +++ b/http/request/admin/tag.go @@ -3,10 +3,11 @@ package admin import "Gwen/model" type TagForm struct { - Id uint `json:"id"` - Name string `json:"name" validate:"required"` - Color uint `json:"color" validate:"required"` - UserId uint `json:"user_id"` + Id uint `json:"id"` + Name string `json:"name" validate:"required"` + Color uint `json:"color" validate:"required"` + UserId uint `json:"user_id"` + CollectionId uint `json:"collection_id"` } func (f *TagForm) FromTag(group *model.Tag) *TagForm { @@ -14,6 +15,7 @@ func (f *TagForm) FromTag(group *model.Tag) *TagForm { f.Name = group.Name f.Color = group.Color f.UserId = group.UserId + f.CollectionId = group.CollectionId return f } @@ -23,11 +25,13 @@ func (f *TagForm) ToTag() *model.Tag { i.Name = f.Name i.Color = f.Color i.UserId = f.UserId + i.CollectionId = f.CollectionId return i } type TagQuery struct { - UserId int `form:"user_id"` - IsMy int `form:"is_my"` + UserId int `form:"user_id"` + IsMy int `form:"is_my"` + CollectionId *int `form:"collection_id"` PageQuery } diff --git a/http/request/admin/user.go b/http/request/admin/user.go index 405d8b4..b1b1719 100644 --- a/http/request/admin/user.go +++ b/http/request/admin/user.go @@ -55,3 +55,7 @@ type ChangeCurPasswordForm struct { OldPassword string `json:"old_password" validate:"required,gte=4,lte=20"` NewPassword string `json:"new_password" validate:"required,gte=4,lte=20"` } +type GroupUsersQuery struct { + IsMy int `json:"is_my"` + UserId uint `json:"user_id"` +} diff --git a/http/response/admin/user.go b/http/response/admin/user.go index 488ebe9..d3941e8 100644 --- a/http/response/admin/user.go +++ b/http/response/admin/user.go @@ -1,5 +1,7 @@ package admin +import "Gwen/model" + type LoginPayload struct { Username string `json:"username"` Token string `json:"token"` @@ -8,7 +10,7 @@ type LoginPayload struct { } var UserRouteNames = []string{ - "MyTagList", "MyAddressBookList", "MyInfo", + "MyTagList", "MyAddressBookList", "MyInfo", "MyAddressBookCollection", } var AdminRouteNames = []string{"*"} @@ -16,3 +18,15 @@ type UserOauthItem struct { ThirdType string `json:"third_type"` Status int `json:"status"` } + +type GroupUsersPayload struct { + Id uint `json:"id"` + Username string `json:"username"` + Status int `json:"status"` +} + +func (g *GroupUsersPayload) FromUser(user *model.User) { + g.Id = user.Id + g.Username = user.Username + g.Status = 1 +} diff --git a/http/response/api/ab.go b/http/response/api/ab.go index 47134e0..31db349 100644 --- a/http/response/api/ab.go +++ b/http/response/api/ab.go @@ -7,3 +7,11 @@ type AbList struct { Tags []string `json:"tags,omitempty"` TagColors string `json:"tag_colors,omitempty"` } + +type SharedProfilesPayload struct { + Guid string `json:"guid"` + Name string `json:"name"` + Owner string `json:"owner"` + Note string `json:"note"` + Rule int `json:"rule"` +} diff --git a/http/router/admin.go b/http/router/admin.go index de8718b..5cf6c3b 100644 --- a/http/router/admin.go +++ b/http/router/admin.go @@ -28,6 +28,8 @@ func Init(g *gin.Engine) { OauthBind(adg) LoginLogBind(adg) AuditBind(adg) + AddressBookCollectionBind(adg) + AddressBookCollectionRuleBind(adg) rs := &admin.Rustdesk{} adg.GET("/server-config", rs.ServerConfig) adg.GET("/app-config", rs.AppConfig) @@ -48,6 +50,7 @@ func UserBind(rg *gin.RouterGroup) { aR.GET("/current", cont.Current) aR.POST("/changeCurPwd", cont.ChangeCurPwd) aR.POST("/myOauth", cont.MyOauth) + aR.POST("/groupUsers", cont.GroupUsers) } aRP := rg.Group("/user").Use(middleware.AdminPrivilege()) { @@ -152,6 +155,29 @@ func AuditBind(rg *gin.RouterGroup) { afR.GET("/list", cont.FileList) afR.POST("/delete", cont.FileDelete) } +func AddressBookCollectionBind(rg *gin.RouterGroup) { + aR := rg.Group("/address_book_collection") + { + cont := &admin.AddressBookCollection{} + 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 AddressBookCollectionRuleBind(rg *gin.RouterGroup) { + aR := rg.Group("/address_book_collection_rule") + { + cont := &admin.AddressBookCollectionRule{} + 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 FileBind(rg *gin.RouterGroup) { diff --git a/model/addressBook.go b/model/addressBook.go index 6750398..8a26903 100644 --- a/model/addressBook.go +++ b/model/addressBook.go @@ -19,22 +19,24 @@ import "Gwen/model/custom_types" // AddressBook 有些字段是Personal才会上传的 type AddressBook struct { - RowId uint `gorm:"primaryKey" json:"row_id"` - Id string `json:"id" gorm:"default:0;not null;index"` - Username string `json:"username" gorm:"default:'';not null;"` - Password string `json:"password" gorm:"default:'';not null;"` - Hostname string `json:"hostname" gorm:"default:'';not null;"` - Alias string `json:"alias" gorm:"default:'';not null;"` - Platform string `json:"platform" gorm:"default:'';not null;"` - Tags custom_types.AutoJson `json:"tags" gorm:"not null;" swaggertype:"array,string"` - Hash string `json:"hash" gorm:"default:'';not null;"` - UserId uint `json:"user_id" gorm:"default:0;not null;index"` - ForceAlwaysRelay bool `json:"forceAlwaysRelay" gorm:"default:0;not null;"` - RdpPort string `json:"rdpPort" gorm:"default:'';not null;"` - RdpUsername string `json:"rdpUsername" gorm:"default:'';not null;"` - Online bool `json:"online" gorm:"default:0;not null;"` - LoginName string `json:"loginName" gorm:"default:'';not null;"` - SameServer bool `json:"sameServer" gorm:"default:0;not null;"` + RowId uint `gorm:"primaryKey" json:"row_id"` + Id string `json:"id" gorm:"default:0;not null;index"` + Username string `json:"username" gorm:"default:'';not null;"` + Password string `json:"password" gorm:"default:'';not null;"` + Hostname string `json:"hostname" gorm:"default:'';not null;"` + Alias string `json:"alias" gorm:"default:'';not null;"` + Platform string `json:"platform" gorm:"default:'';not null;"` + Tags custom_types.AutoJson `json:"tags" gorm:"not null;" swaggertype:"array,string"` + Hash string `json:"hash" gorm:"default:'';not null;"` + UserId uint `json:"user_id" gorm:"default:0;not null;index"` + ForceAlwaysRelay bool `json:"forceAlwaysRelay" gorm:"default:0;not null;"` + RdpPort string `json:"rdpPort" gorm:"default:'';not null;"` + RdpUsername string `json:"rdpUsername" gorm:"default:'';not null;"` + Online bool `json:"online" gorm:"default:0;not null;"` + LoginName string `json:"loginName" gorm:"default:'';not null;"` + SameServer bool `json:"sameServer" gorm:"default:0;not null;"` + CollectionId uint `json:"collection_id" gorm:"default:0;not null;index"` + Collection *AddressBookCollection `json:"collection,omitempty"` TimeModel } @@ -42,3 +44,37 @@ type AddressBookList struct { AddressBooks []*AddressBook `json:"list"` Pagination } + +type AddressBookCollection struct { + IdModel + UserId uint `json:"user_id" gorm:"default:0;not null;index"` + Name string `json:"name" gorm:"default:'';not null;" validate:"required"` + TimeModel +} +type AddressBookCollectionList struct { + AddressBookCollection []*AddressBookCollection `json:"list"` + Pagination +} +type AddressBookCollectionRule struct { + IdModel + UserId uint `json:"user_id" gorm:"default:0;not null;"` + CollectionId uint `json:"collection_id" gorm:"default:0;not null;index" validate:"required"` + Rule int `json:"rule" gorm:"default:0;not null;" validate:"required,gte=1,lte=3"` // 0: 无 1: 读 2: 读写 3: 完全控制 + Type int `json:"type" gorm:"default:1;not null;" validate:"required,gte=1,lte=2"` // 1: 个人 2: 群组 + ToId uint `json:"to_id" gorm:"default:0;not null;" validate:"required,gt=0"` + TimeModel +} +type AddressBookCollectionRuleList struct { + AddressBookCollectionRule []*AddressBookCollectionRule `json:"list"` + Pagination +} + +const ( + ShareAddressBookRuleTypePersonal = 1 + ShareAddressBookRuleTypeGroup = 2 +) +const ( + ShareAddressBookRuleRuleRead = 1 + ShareAddressBookRuleRuleReadWrite = 2 + ShareAddressBookRuleRuleFullControl = 3 +) diff --git a/model/tag.go b/model/tag.go index ccc9bfc..db1f8a7 100644 --- a/model/tag.go +++ b/model/tag.go @@ -2,9 +2,11 @@ package model type Tag struct { IdModel - Name string `json:"name" gorm:"default:'';not null;"` - UserId uint `json:"user_id" gorm:"default:0;not null;index"` - Color uint `json:"color" gorm:"default:0;not null;"` //color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba + Name string `json:"name" gorm:"default:'';not null;"` + UserId uint `json:"user_id" gorm:"default:0;not null;index"` + Color uint `json:"color" gorm:"default:0;not null;"` //color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba + CollectionId uint `json:"collection_id" gorm:"default:0;not null;index"` + Collection *AddressBookCollection `json:"collection,omitempty"` TimeModel } diff --git a/service/addressBook.go b/service/addressBook.go index a23e97b..902d167 100644 --- a/service/addressBook.go +++ b/service/addressBook.go @@ -22,6 +22,12 @@ func (s *AddressBookService) InfoByUserIdAndId(userid uint, id string) *model.Ad global.DB.Where("user_id = ? and id = ?", userid, id).First(p) return p } + +func (s *AddressBookService) InfoByUserIdAndIdAndCid(userid uint, id string, cid uint) *model.AddressBook { + p := &model.AddressBook{} + global.DB.Where("user_id = ? and id = ? and collection_id = ?", userid, id, cid).First(p) + return p +} func (s *AddressBookService) InfoByRowId(id uint) *model.AddressBook { p := &model.AddressBook{} global.DB.Where("row_id = ?", id).First(p) @@ -96,7 +102,7 @@ func (s *AddressBookService) UpdateAddressBook(abs []*model.AddressBook, userId } -func (t *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AddressBookList) { +func (s *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AddressBookList) { res = &model.AddressBookList{} res.Page = int64(page) res.PageSize = int64(pageSize) @@ -111,34 +117,34 @@ func (t *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB)) } // Create 创建 -func (t *AddressBookService) Create(u *model.AddressBook) error { +func (s *AddressBookService) Create(u *model.AddressBook) error { res := global.DB.Create(u).Error return res } -func (t *AddressBookService) Delete(u *model.AddressBook) error { +func (s *AddressBookService) Delete(u *model.AddressBook) error { return global.DB.Delete(u).Error } // Update 更新 -func (t *AddressBookService) Update(u *model.AddressBook) error { - return global.DB.Model(u).Updates(u).Error +func (s *AddressBookService) Update(u *model.AddressBook) error { + return global.DB.Model(u).Select("*").Omit("created_at").Updates(u).Error } // ShareByWebClient 分享 -func (t *AddressBookService) ShareByWebClient(m *model.ShareRecord) error { +func (s *AddressBookService) ShareByWebClient(m *model.ShareRecord) error { m.ShareToken = uuid.New().String() return global.DB.Create(m).Error } // SharedPeer -func (t *AddressBookService) SharedPeer(shareToken string) *model.ShareRecord { +func (s *AddressBookService) SharedPeer(shareToken string) *model.ShareRecord { m := &model.ShareRecord{} global.DB.Where("share_token = ?", shareToken).First(m) return m } // PlatformFromOs -func (t *AddressBookService) PlatformFromOs(os string) string { +func (s *AddressBookService) PlatformFromOs(os string) string { if strings.Contains(os, "Android") || strings.Contains(os, "android") { return "Android" } @@ -153,3 +159,152 @@ func (t *AddressBookService) PlatformFromOs(os string) string { } return "" } +func (s *AddressBookService) ListByUserIdAndCollectionId(userId, cid, page, pageSize uint) (res *model.AddressBookList) { + res = s.List(page, pageSize, func(tx *gorm.DB) { + tx.Where("user_id = ? and collection_id = ?", userId, cid) + }) + return +} +func (s *AddressBookService) ListCollection(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AddressBookCollectionList) { + res = &model.AddressBookCollectionList{} + res.Page = int64(page) + res.PageSize = int64(pageSize) + tx := global.DB.Model(&model.AddressBookCollection{}) + if where != nil { + where(tx) + } + tx.Count(&res.Total) + tx.Scopes(Paginate(page, pageSize)) + tx.Find(&res.AddressBookCollection) + return +} +func (s *AddressBookService) ListCollectionByIds(ids []uint) (res []*model.AddressBookCollection) { + global.DB.Where("id in ?", ids).Find(&res) + return res +} + +func (s *AddressBookService) ListCollectionByUserId(userId uint) (res *model.AddressBookCollectionList) { + res = s.ListCollection(1, 100, func(tx *gorm.DB) { + tx.Where("user_id = ?", userId) + }) + return +} +func (s *AddressBookService) CollectionInfoById(id uint) *model.AddressBookCollection { + p := &model.AddressBookCollection{} + global.DB.Where("id = ?", id).First(p) + return p +} + +func (s *AddressBookService) CollectionReadRules(user *model.User) (res []*model.AddressBookCollectionRule) { + // personalRules + var personalRules []*model.AddressBookCollectionRule + tx2 := global.DB.Model(&model.AddressBookCollectionRule{}) + tx2.Where("type = ? and to_id = ? and rule > 0", model.ShareAddressBookRuleTypePersonal, user.Id).Find(&personalRules) + res = append(res, personalRules...) + + //group + var groupRules []*model.AddressBookCollectionRule + tx3 := global.DB.Model(&model.AddressBookCollectionRule{}) + tx3.Where("type = ? and to_id = ? and rule > 0", model.ShareAddressBookRuleTypeGroup, user.GroupId).Find(&groupRules) + res = append(res, groupRules...) + return +} + +func (s *AddressBookService) UserMaxRule(user *model.User, uid, cid uint) int { + // ismy? + if user.Id == uid { + return model.ShareAddressBookRuleRuleFullControl + } + max := 0 + personalRules := &model.AddressBookCollectionRule{} + tx := global.DB.Model(personalRules) + tx.Where("type = ? and collection_id = ? and to_id = ?", model.ShareAddressBookRuleTypePersonal, cid, user.Id).First(&personalRules) + if personalRules.Id != 0 { + max = personalRules.Rule + if max == model.ShareAddressBookRuleRuleFullControl { + return max + } + } + + groupRules := &model.AddressBookCollectionRule{} + tx2 := global.DB.Model(groupRules) + tx2.Where("type = ? and collection_id = ? and to_id = ?", model.ShareAddressBookRuleTypeGroup, cid, user.GroupId).First(&groupRules) + if groupRules.Id != 0 { + if groupRules.Rule > max { + max = groupRules.Rule + } + if max == model.ShareAddressBookRuleRuleFullControl { + return max + } + } + return max +} + +func (s *AddressBookService) CheckUserReadPrivilege(user *model.User, uid, cid uint) bool { + return s.UserMaxRule(user, uid, cid) >= model.ShareAddressBookRuleRuleRead +} +func (s *AddressBookService) CheckUserWritePrivilege(user *model.User, uid, cid uint) bool { + return s.UserMaxRule(user, uid, cid) >= model.ShareAddressBookRuleRuleReadWrite +} +func (s *AddressBookService) CheckUserFullControlPrivilege(user *model.User, uid, cid uint) bool { + return s.UserMaxRule(user, uid, cid) >= model.ShareAddressBookRuleRuleFullControl +} + +func (s *AddressBookService) CreateCollection(t *model.AddressBookCollection) error { + return global.DB.Create(t).Error +} + +func (s *AddressBookService) UpdateCollection(t *model.AddressBookCollection) error { + return global.DB.Model(t).Updates(t).Error +} + +func (s *AddressBookService) DeleteCollection(t *model.AddressBookCollection) error { + //删除集合下的所有规则、地址簿,再删除集合 + tx := global.DB.Begin() + tx.Where("collection_id = ?", t.Id).Delete(&model.AddressBookCollectionRule{}) + tx.Where("collection_id = ?", t.Id).Delete(&model.AddressBook{}) + tx.Delete(t) + return tx.Commit().Error +} + +func (s *AddressBookService) RuleInfoById(u uint) *model.AddressBookCollectionRule { + p := &model.AddressBookCollectionRule{} + global.DB.Where("id = ?", u).First(p) + return p +} +func (s *AddressBookService) RulePersonalInfoByToIdAndCid(toid, cid uint) *model.AddressBookCollectionRule { + p := &model.AddressBookCollectionRule{} + global.DB.Where("type = ? and to_id = ? and collection_id = ?", model.ShareAddressBookRuleTypePersonal, toid, cid).First(p) + return p +} +func (s *AddressBookService) CreateRule(t *model.AddressBookCollectionRule) error { + return global.DB.Create(t).Error +} + +func (s *AddressBookService) ListRules(page uint, size uint, f func(tx *gorm.DB)) *model.AddressBookCollectionRuleList { + res := &model.AddressBookCollectionRuleList{} + res.Page = int64(page) + res.PageSize = int64(size) + tx := global.DB.Model(&model.AddressBookCollectionRule{}) + if f != nil { + f(tx) + } + tx.Count(&res.Total) + tx.Scopes(Paginate(page, size)) + tx.Find(&res.AddressBookCollectionRule) + return res +} + +func (s *AddressBookService) UpdateRule(t *model.AddressBookCollectionRule) error { + return global.DB.Model(t).Updates(t).Error +} + +func (s *AddressBookService) DeleteRule(t *model.AddressBookCollectionRule) error { + return global.DB.Delete(t).Error +} + +// CheckCollectionOwner 检查Collection的所有者 +func (s *AddressBookService) CheckCollectionOwner(uid uint, cid uint) bool { + p := s.CollectionInfoById(cid) + return p.UserId == uid +} diff --git a/service/tag.go b/service/tag.go index b4ba77a..e9fc089 100644 --- a/service/tag.go +++ b/service/tag.go @@ -14,9 +14,9 @@ func (s *TagService) Info(id uint) *model.Tag { global.DB.Where("id = ?", id).First(p) return p } -func (s *TagService) InfoByUserIdAndName(userid uint, name string) *model.Tag { +func (s *TagService) InfoByUserIdAndNameAndCollectionId(userid uint, name string, cid uint) *model.Tag { p := &model.Tag{} - global.DB.Where("user_id = ? and name = ?", userid, name).First(p) + global.DB.Where("user_id = ? and name = ? and collection_id = ?", userid, name, cid).First(p) return p } @@ -26,7 +26,12 @@ func (s *TagService) ListByUserId(userId uint) (res *model.TagList) { }) return } - +func (s *TagService) ListByUserIdAndCollectionId(userId, cid uint) (res *model.TagList) { + res = s.List(1, 1000, func(tx *gorm.DB) { + tx.Where("user_id = ? and collection_id = ?", userId, cid) + }) + return +} func (s *TagService) UpdateTags(userId uint, tags map[string]uint) { tx := global.DB.Begin() //先查询所有tag @@ -58,13 +63,13 @@ func (s *TagService) UpdateTags(userId uint, tags map[string]uint) { } // InfoById 根据用户id取用户信息 -func (t *TagService) InfoById(id uint) *model.Tag { +func (s *TagService) InfoById(id uint) *model.Tag { u := &model.Tag{} global.DB.Where("id = ?", id).First(u) return u } -func (t *TagService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.TagList) { +func (s *TagService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.TagList) { res = &model.TagList{} res.Page = int64(page) res.PageSize = int64(pageSize) @@ -79,15 +84,15 @@ func (t *TagService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *mo } // Create 创建 -func (t *TagService) Create(u *model.Tag) error { +func (s *TagService) Create(u *model.Tag) error { res := global.DB.Create(u).Error return res } -func (t *TagService) Delete(u *model.Tag) error { +func (s *TagService) Delete(u *model.Tag) error { return global.DB.Delete(u).Error } // Update 更新 -func (t *TagService) Update(u *model.Tag) error { - return global.DB.Model(u).Updates(u).Error +func (s *TagService) Update(u *model.Tag) error { + return global.DB.Model(u).Select("*").Omit("created_at").Updates(u).Error } diff --git a/service/user.go b/service/user.go index c38fce3..d62a4eb 100644 --- a/service/user.go +++ b/service/user.go @@ -101,6 +101,11 @@ func (us *UserService) List(page, pageSize uint, where func(tx *gorm.DB)) (res * return } +func (us *UserService) ListByIds(ids []uint) (res []*model.User) { + global.DB.Where("id in ?", ids).Find(&res) + return res +} + // ListByGroupId 根据组id取用户列表 func (us *UserService) ListByGroupId(groupId, page, pageSize uint) (res *model.UserList) { res = us.List(page, pageSize, func(tx *gorm.DB) { diff --git a/utils/tools.go b/utils/tools.go index fcb69ba..cba1034 100644 --- a/utils/tools.go +++ b/utils/tools.go @@ -73,3 +73,21 @@ func RandomString(n int) string { } return string(b) } + +// Keys 泛型函数,K 是键类型,V 是值类型 +func Keys[K comparable, V any](m map[K]V) []K { + keys := make([]K, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + return keys +} + +// Values 泛型函数,K 是键类型,V 是值类型 +func Values[K comparable, V any](m map[K]V) []V { + values := make([]V, 0, len(m)) + for _, v := range m { + values = append(values, v) + } + return values +}