feat(plugin): add connector API

This commit is contained in:
LinkinStar 2023-01-13 12:50:20 +08:00
parent 3199693d44
commit 29aa3f7ef2
18 changed files with 1587 additions and 74 deletions

View File

@ -206,7 +206,8 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService)
activityController := controller.NewActivityController(activityCommon, activityService)
roleController := controller_admin.NewRoleController(roleService)
answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_adminReportController, userAdminController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController, roleController)
pluginController := controller_admin.NewPluginController()
answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_adminReportController, userAdminController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController, roleController, pluginController)
swaggerRouter := router.NewSwaggerRouter(swaggerConf)
uiRouter := router.NewUIRouter(siteinfoController, siteInfoCommonService)
authUserMiddleware := middleware.NewAuthUserMiddleware(authService, siteInfoCommonService)

View File

@ -183,6 +183,185 @@ const docTemplate = `{
}
}
},
"/answer/admin/api/plugin/config": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get plugin config",
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "get plugin config",
"parameters": [
{
"type": "string",
"description": "plugin_slug_name",
"name": "plugin_slug_name",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/schema.GetPluginConfigResp"
}
}
}
]
}
}
}
},
"put": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "update plugin config",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "update plugin config",
"parameters": [
{
"description": "UpdatePluginConfigReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.UpdatePluginConfigReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
}
},
"/answer/admin/api/plugin/status": {
"put": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "update plugin status",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "update plugin status",
"parameters": [
{
"description": "UpdatePluginStatusReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.UpdatePluginStatusReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
}
},
"/answer/admin/api/plugins": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get plugin list",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "get plugin list",
"parameters": [
{
"type": "string",
"description": "status: active/inactive",
"name": "status",
"in": "query"
},
{
"type": "boolean",
"description": "have config",
"name": "have_config",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.GetPluginListResp"
}
}
}
}
]
}
}
}
}
},
"/answer/admin/api/question/page": {
"get": {
"security": [
@ -2127,7 +2306,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Plugin"
"PluginConnector"
],
"summary": "external login binding user send email",
"parameters": [
@ -2163,6 +2342,125 @@ const docTemplate = `{
}
}
},
"/answer/api/v1/connector/info": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get all enabled connectors",
"produces": [
"application/json"
],
"tags": [
"PluginConnector"
],
"summary": "get all enabled connectors",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.ConnectorInfoResp"
}
}
}
}
]
}
}
}
}
},
"/answer/api/v1/connector/user/info": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get all connectors info about user",
"produces": [
"application/json"
],
"tags": [
"PluginConnector"
],
"summary": "get all connectors info about user",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.ConnectorUserInfoResp"
}
}
}
}
]
}
}
}
}
},
"/answer/api/v1/connector/user/unbinding": {
"delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "unbind external user login",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"PluginConnector"
],
"summary": "unbind external user login",
"parameters": [
{
"description": "ExternalLoginUnbindingReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.ExternalLoginUnbindingReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
}
},
"/answer/api/v1/file": {
"post": {
"security": [
@ -5699,6 +5997,63 @@ const docTemplate = `{
}
}
},
"schema.ConfigFields": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"required": {
"type": "boolean"
},
"title": {
"type": "string"
},
"type": {
"type": "string"
},
"ui_widget": {
"$ref": "#/definitions/schema.UIWidget"
},
"value": {
"type": "string"
}
}
},
"schema.ConnectorInfoResp": {
"type": "object",
"properties": {
"icon": {
"type": "string"
},
"link": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"schema.ConnectorUserInfoResp": {
"type": "object",
"properties": {
"binding": {
"type": "boolean"
},
"external_id": {
"type": "string"
},
"icon": {
"type": "string"
},
"link": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"schema.ExternalLoginBindingUserSendEmailReq": {
"type": "object",
"required": [
@ -5731,6 +6086,18 @@ const docTemplate = `{
}
}
},
"schema.ExternalLoginUnbindingReq": {
"type": "object",
"required": [
"external_id"
],
"properties": {
"external_id": {
"type": "string",
"maxLength": 128
}
}
},
"schema.FollowReq": {
"type": "object",
"required": [
@ -6014,6 +6381,53 @@ const docTemplate = `{
}
}
},
"schema.GetPluginConfigResp": {
"type": "object",
"properties": {
"config_fields": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.ConfigFields"
}
},
"description": {
"type": "string"
},
"name": {
"description": "ConfigFields []plugin.ConfigField ` + "`" + `json:\"config_fields\"` + "`" + `",
"type": "string"
},
"slug_name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"schema.GetPluginListResp": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"have_config": {
"type": "boolean"
},
"name": {
"type": "string"
},
"slug_name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"schema.GetRankPersonalWithPageResp": {
"type": "object",
"properties": {
@ -7398,6 +7812,17 @@ const docTemplate = `{
}
}
},
"schema.UIWidget": {
"type": "object",
"properties": {
"placeholder": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"schema.UnreviewedRevisionInfoInfo": {
"type": "object",
"properties": {
@ -7495,6 +7920,37 @@ const docTemplate = `{
}
}
},
"schema.UpdatePluginConfigReq": {
"type": "object",
"required": [
"plugin_slug_name"
],
"properties": {
"config_fields": {
"type": "object",
"additionalProperties": {}
},
"plugin_slug_name": {
"type": "string",
"maxLength": 100
}
}
},
"schema.UpdatePluginStatusReq": {
"type": "object",
"required": [
"plugin_slug_name"
],
"properties": {
"enabled": {
"type": "boolean"
},
"plugin_slug_name": {
"type": "string",
"maxLength": 100
}
}
},
"schema.UpdateSMTPConfigReq": {
"type": "object",
"properties": {

View File

@ -171,6 +171,185 @@
}
}
},
"/answer/admin/api/plugin/config": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get plugin config",
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "get plugin config",
"parameters": [
{
"type": "string",
"description": "plugin_slug_name",
"name": "plugin_slug_name",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/schema.GetPluginConfigResp"
}
}
}
]
}
}
}
},
"put": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "update plugin config",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "update plugin config",
"parameters": [
{
"description": "UpdatePluginConfigReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.UpdatePluginConfigReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
}
},
"/answer/admin/api/plugin/status": {
"put": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "update plugin status",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "update plugin status",
"parameters": [
{
"description": "UpdatePluginStatusReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.UpdatePluginStatusReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
}
},
"/answer/admin/api/plugins": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get plugin list",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"AdminPlugin"
],
"summary": "get plugin list",
"parameters": [
{
"type": "string",
"description": "status: active/inactive",
"name": "status",
"in": "query"
},
{
"type": "boolean",
"description": "have config",
"name": "have_config",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.GetPluginListResp"
}
}
}
}
]
}
}
}
}
},
"/answer/admin/api/question/page": {
"get": {
"security": [
@ -2115,7 +2294,7 @@
"application/json"
],
"tags": [
"Plugin"
"PluginConnector"
],
"summary": "external login binding user send email",
"parameters": [
@ -2151,6 +2330,125 @@
}
}
},
"/answer/api/v1/connector/info": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get all enabled connectors",
"produces": [
"application/json"
],
"tags": [
"PluginConnector"
],
"summary": "get all enabled connectors",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.ConnectorInfoResp"
}
}
}
}
]
}
}
}
}
},
"/answer/api/v1/connector/user/info": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get all connectors info about user",
"produces": [
"application/json"
],
"tags": [
"PluginConnector"
],
"summary": "get all connectors info about user",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/handler.RespBody"
},
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.ConnectorUserInfoResp"
}
}
}
}
]
}
}
}
}
},
"/answer/api/v1/connector/user/unbinding": {
"delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "unbind external user login",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"PluginConnector"
],
"summary": "unbind external user login",
"parameters": [
{
"description": "ExternalLoginUnbindingReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.ExternalLoginUnbindingReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
}
},
"/answer/api/v1/file": {
"post": {
"security": [
@ -5687,6 +5985,63 @@
}
}
},
"schema.ConfigFields": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"required": {
"type": "boolean"
},
"title": {
"type": "string"
},
"type": {
"type": "string"
},
"ui_widget": {
"$ref": "#/definitions/schema.UIWidget"
},
"value": {
"type": "string"
}
}
},
"schema.ConnectorInfoResp": {
"type": "object",
"properties": {
"icon": {
"type": "string"
},
"link": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"schema.ConnectorUserInfoResp": {
"type": "object",
"properties": {
"binding": {
"type": "boolean"
},
"external_id": {
"type": "string"
},
"icon": {
"type": "string"
},
"link": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"schema.ExternalLoginBindingUserSendEmailReq": {
"type": "object",
"required": [
@ -5719,6 +6074,18 @@
}
}
},
"schema.ExternalLoginUnbindingReq": {
"type": "object",
"required": [
"external_id"
],
"properties": {
"external_id": {
"type": "string",
"maxLength": 128
}
}
},
"schema.FollowReq": {
"type": "object",
"required": [
@ -6002,6 +6369,53 @@
}
}
},
"schema.GetPluginConfigResp": {
"type": "object",
"properties": {
"config_fields": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.ConfigFields"
}
},
"description": {
"type": "string"
},
"name": {
"description": "ConfigFields []plugin.ConfigField `json:\"config_fields\"`",
"type": "string"
},
"slug_name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"schema.GetPluginListResp": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"have_config": {
"type": "boolean"
},
"name": {
"type": "string"
},
"slug_name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"schema.GetRankPersonalWithPageResp": {
"type": "object",
"properties": {
@ -7386,6 +7800,17 @@
}
}
},
"schema.UIWidget": {
"type": "object",
"properties": {
"placeholder": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"schema.UnreviewedRevisionInfoInfo": {
"type": "object",
"properties": {
@ -7483,6 +7908,37 @@
}
}
},
"schema.UpdatePluginConfigReq": {
"type": "object",
"required": [
"plugin_slug_name"
],
"properties": {
"config_fields": {
"type": "object",
"additionalProperties": {}
},
"plugin_slug_name": {
"type": "string",
"maxLength": 100
}
}
},
"schema.UpdatePluginStatusReq": {
"type": "object",
"required": [
"plugin_slug_name"
],
"properties": {
"enabled": {
"type": "boolean"
},
"plugin_slug_name": {
"type": "string",
"maxLength": 100
}
}
},
"schema.UpdateSMTPConfigReq": {
"type": "object",
"properties": {

View File

@ -293,6 +293,43 @@ definitions:
switch:
type: boolean
type: object
schema.ConfigFields:
properties:
description:
type: string
required:
type: boolean
title:
type: string
type:
type: string
ui_widget:
$ref: '#/definitions/schema.UIWidget'
value:
type: string
type: object
schema.ConnectorInfoResp:
properties:
icon:
type: string
link:
type: string
name:
type: string
type: object
schema.ConnectorUserInfoResp:
properties:
binding:
type: boolean
external_id:
type: string
icon:
type: string
link:
type: string
name:
type: string
type: object
schema.ExternalLoginBindingUserSendEmailReq:
properties:
binding_key:
@ -317,6 +354,14 @@ definitions:
email_exist_and_must_be_confirmed:
type: boolean
type: object
schema.ExternalLoginUnbindingReq:
properties:
external_id:
maxLength: 128
type: string
required:
- external_id
type: object
schema.FollowReq:
properties:
is_cancel:
@ -524,6 +569,37 @@ definitions:
info:
$ref: '#/definitions/schema.GetOtherUserInfoByUsernameResp'
type: object
schema.GetPluginConfigResp:
properties:
config_fields:
items:
$ref: '#/definitions/schema.ConfigFields'
type: array
description:
type: string
name:
description: ConfigFields []plugin.ConfigField `json:"config_fields"`
type: string
slug_name:
type: string
version:
type: string
type: object
schema.GetPluginListResp:
properties:
description:
type: string
enabled:
type: boolean
have_config:
type: boolean
name:
type: string
slug_name:
type: string
version:
type: string
type: object
schema.GetRankPersonalWithPageResp:
properties:
answer_id:
@ -1509,6 +1585,13 @@ definitions:
value:
type: string
type: object
schema.UIWidget:
properties:
placeholder:
type: string
type:
type: string
type: object
schema.UnreviewedRevisionInfoInfo:
properties:
content:
@ -1578,6 +1661,27 @@ definitions:
required:
- display_name
type: object
schema.UpdatePluginConfigReq:
properties:
config_fields:
additionalProperties: {}
type: object
plugin_slug_name:
maxLength: 100
type: string
required:
- plugin_slug_name
type: object
schema.UpdatePluginStatusReq:
properties:
enabled:
type: boolean
plugin_slug_name:
maxLength: 100
type: string
required:
- plugin_slug_name
type: object
schema.UpdateSMTPConfigReq:
properties:
encryption:
@ -2016,6 +2120,112 @@ paths:
summary: Get language options
tags:
- Lang
/answer/admin/api/plugin/config:
get:
description: get plugin config
parameters:
- description: plugin_slug_name
in: query
name: plugin_slug_name
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/handler.RespBody'
- properties:
data:
$ref: '#/definitions/schema.GetPluginConfigResp'
type: object
security:
- ApiKeyAuth: []
summary: get plugin config
tags:
- AdminPlugin
put:
consumes:
- application/json
description: update plugin config
parameters:
- description: UpdatePluginConfigReq
in: body
name: data
required: true
schema:
$ref: '#/definitions/schema.UpdatePluginConfigReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.RespBody'
security:
- ApiKeyAuth: []
summary: update plugin config
tags:
- AdminPlugin
/answer/admin/api/plugin/status:
put:
consumes:
- application/json
description: update plugin status
parameters:
- description: UpdatePluginStatusReq
in: body
name: data
required: true
schema:
$ref: '#/definitions/schema.UpdatePluginStatusReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.RespBody'
security:
- ApiKeyAuth: []
summary: update plugin status
tags:
- AdminPlugin
/answer/admin/api/plugins:
get:
consumes:
- application/json
description: get plugin list
parameters:
- description: 'status: active/inactive'
in: query
name: status
type: string
- description: have config
in: query
name: have_config
type: boolean
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/handler.RespBody'
- properties:
data:
items:
$ref: '#/definitions/schema.GetPluginListResp'
type: array
type: object
security:
- ApiKeyAuth: []
summary: get plugin list
tags:
- AdminPlugin
/answer/admin/api/question/page:
get:
consumes:
@ -3201,7 +3411,75 @@ paths:
type: object
summary: external login binding user send email
tags:
- Plugin
- PluginConnector
/answer/api/v1/connector/info:
get:
description: get all enabled connectors
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/handler.RespBody'
- properties:
data:
items:
$ref: '#/definitions/schema.ConnectorInfoResp'
type: array
type: object
security:
- ApiKeyAuth: []
summary: get all enabled connectors
tags:
- PluginConnector
/answer/api/v1/connector/user/info:
get:
description: get all connectors info about user
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/handler.RespBody'
- properties:
data:
items:
$ref: '#/definitions/schema.ConnectorUserInfoResp'
type: array
type: object
security:
- ApiKeyAuth: []
summary: get all connectors info about user
tags:
- PluginConnector
/answer/api/v1/connector/user/unbinding:
delete:
consumes:
- application/json
description: unbind external user login
parameters:
- description: ExternalLoginUnbindingReq
in: body
name: data
required: true
schema:
$ref: '#/definitions/schema.ExternalLoginUnbindingReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.RespBody'
security:
- ApiKeyAuth: []
summary: unbind external user login
tags:
- PluginConnector
/answer/api/v1/file:
post:
consumes:

View File

@ -65,6 +65,7 @@ func NewHTTPServer(debug bool,
templateRouter.RegisterTemplateRouter(rootGroup)
// plugin routes
pluginAPIRouter.RegisterConnector(r)
pluginAPIRouter.RegisterUnAuthConnectorRouter(mustUnAuthV1)
pluginAPIRouter.RegisterAuthConnectorRouter(authV1)
return r
}

View File

@ -5,6 +5,7 @@ import (
"net/http"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/middleware"
"github.com/answerdev/answer/internal/plugin"
_ "github.com/answerdev/answer/internal/plugin/connector"
"github.com/answerdev/answer/internal/schema"
@ -16,8 +17,9 @@ import (
)
const (
ConnectorLoginRouterPrefix = "/answer/api/v1/connector/login/"
ConnectorRedirectRouterPrefix = "/answer/api/v1/connector/redirect/"
commonRouterPrefix = "/answer/api/v1"
ConnectorLoginRouterPrefix = "/connector/login/"
ConnectorRedirectRouterPrefix = "/connector/redirect/"
)
// ConnectorController comment controller
@ -49,7 +51,8 @@ func (cc *ConnectorController) ConnectorLogin(connector plugin.Connector) (fn fu
return
}
receiverURL := fmt.Sprintf("%s%s%s", general.SiteUrl, ConnectorRedirectRouterPrefix, connector.ConnectorSlugName())
receiverURL := fmt.Sprintf("%s%s%s%s", general.SiteUrl,
commonRouterPrefix, ConnectorRedirectRouterPrefix, connector.ConnectorSlugName())
redirectURL := connector.ConnectorSender(ctx, receiverURL)
if len(redirectURL) > 0 {
ctx.Redirect(http.StatusFound, redirectURL)
@ -76,8 +79,8 @@ func (cc *ConnectorController) ConnectorRedirect(connector plugin.Connector) (fn
Provider: connector.ConnectorSlugName(),
ExternalID: userInfo.ExternalID,
Name: userInfo.Name,
//Email: userInfo.Email,
MetaInfo: userInfo.MetaInfo,
Email: userInfo.Email,
MetaInfo: userInfo.MetaInfo,
}
resp, err := cc.userExternalService.ExternalLogin(ctx, u)
if err != nil {
@ -95,33 +98,38 @@ func (cc *ConnectorController) ConnectorRedirect(connector plugin.Connector) (fn
}
}
// ConnectorsInfo get all enabled connectors
// @Summary get all enabled connectors
// @Description get all enabled connectors
// @Tags PluginConnector
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {object} handler.RespBody{data=[]schema.ConnectorInfoResp}
// @Router /answer/api/v1/connector/info [get]
func (cc *ConnectorController) ConnectorsInfo(ctx *gin.Context) {
general, err := cc.siteInfoService.GetSiteGeneral(ctx)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
//general, err := cc.siteInfoService.GetSiteGeneral(ctx)
//if err != nil {
// handler.HandleResponse(ctx, err, nil)
// return
//}
resp := make([]*schema.ConnectorInfoResp, 0)
err = plugin.CallConnector(func(fn plugin.Connector) error {
_ = plugin.CallConnector(func(fn plugin.Connector) error {
resp = append(resp, &schema.ConnectorInfoResp{
Name: fn.ConnectorSlugName(),
Name: fn.ConnectorName(),
Icon: fn.ConnectorLogoSVG(),
Link: fmt.Sprintf("%s%s%s", general.SiteUrl, ConnectorLoginRouterPrefix, fn.ConnectorSlugName()),
Link: fmt.Sprintf("%s%s%s%s", "http://10.0.20.88:8080",
commonRouterPrefix, ConnectorLoginRouterPrefix, fn.ConnectorSlugName()),
})
return nil
})
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
handler.HandleResponse(ctx, nil, resp)
}
// ExternalLoginBindingUserSendEmail external login binding user send email
// @Summary external login binding user send email
// @Description external login binding user send email
// @Tags Plugin
// @Tags PluginConnector
// @Accept json
// @Produce json
// @Param data body schema.ExternalLoginBindingUserSendEmailReq true "external login binding user send email"
@ -136,3 +144,68 @@ func (cc *ConnectorController) ExternalLoginBindingUserSendEmail(ctx *gin.Contex
resp, err := cc.userExternalService.ExternalLoginBindingUserSendEmail(ctx, req)
handler.HandleResponse(ctx, err, resp)
}
// ConnectorsUserInfo get all connectors info about user
// @Summary get all connectors info about user
// @Description get all connectors info about user
// @Tags PluginConnector
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {object} handler.RespBody{data=[]schema.ConnectorUserInfoResp}
// @Router /answer/api/v1/connector/user/info [get]
func (cc *ConnectorController) ConnectorsUserInfo(ctx *gin.Context) {
general, err := cc.siteInfoService.GetSiteGeneral(ctx)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
userID := middleware.GetLoginUserIDFromContext(ctx)
userInfoList, err := cc.userExternalService.GetExternalLoginUserInfoList(ctx, userID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
userExternalLoginMapping := make(map[string]string)
for _, userInfo := range userInfoList {
userExternalLoginMapping[userInfo.Provider] = userInfo.ExternalID
}
resp := make([]*schema.ConnectorUserInfoResp, 0)
_ = plugin.CallConnector(func(fn plugin.Connector) error {
externalID := userExternalLoginMapping[fn.ConnectorSlugName()]
resp = append(resp, &schema.ConnectorUserInfoResp{
Name: fn.ConnectorName(),
Icon: fn.ConnectorLogoSVG(),
Link: fmt.Sprintf("%s%s%s%s", general.SiteUrl,
commonRouterPrefix, ConnectorLoginRouterPrefix, fn.ConnectorSlugName()),
Binding: len(externalID) > 0,
ExternalID: externalID,
})
return nil
})
handler.HandleResponse(ctx, nil, resp)
}
// ExternalLoginUnbinding unbind external user login
// @Summary unbind external user login
// @Description unbind external user login
// @Tags PluginConnector
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param data body schema.ExternalLoginUnbindingReq true "ExternalLoginUnbindingReq"
// @Success 200 {object} handler.RespBody{}
// @Router /answer/api/v1/connector/user/unbinding [delete]
func (cc *ConnectorController) ExternalLoginUnbinding(ctx *gin.Context) {
req := &schema.ExternalLoginUnbindingReq{}
if handler.BindAndCheck(ctx, req) {
return
}
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
err := cc.userExternalService.ExternalLoginUnbinding(ctx, req)
handler.HandleResponse(ctx, err, nil)
}

View File

@ -9,4 +9,5 @@ var ProviderSetController = wire.NewSet(
NewThemeController,
NewSiteInfoController,
NewRoleController,
NewPluginController,
)

View File

@ -1,57 +1,104 @@
package controller_admin
import (
"encoding/json"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/plugin"
"github.com/answerdev/answer/internal/schema"
service "github.com/answerdev/answer/internal/service/role"
"github.com/gin-gonic/gin"
)
// PluginController role controller
type PluginController struct {
roleService *service.RoleService
}
// NewPluginController new controller
func NewPluginController(roleService *service.RoleService) *PluginController {
return &PluginController{roleService: roleService}
func NewPluginController() *PluginController {
return &PluginController{}
}
// GetPluginList get plugin list
// @Summary get plugin list
// @Description get plugin list
// @Tags admin
// @Tags AdminPlugin
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Success 200 {object} handler.RespBody{data=[]schema.GetCommentResp}
// @Param status query string false "status: active/inactive"
// @Param have_config query boolean false "have config"
// @Success 200 {object} handler.RespBody{data=[]schema.GetPluginListResp}
// @Router /answer/admin/api/plugins [get]
func (pc *PluginController) GetPluginList(ctx *gin.Context) {
req := &schema.GetPluginListReq{}
if handler.BindAndCheck(ctx, req) {
return
}
pluginConfigMapping := make(map[string]bool)
_ = plugin.CallConfig(func(fn plugin.Config) error {
if len(fn.ConfigFields()) > 0 {
pluginConfigMapping[fn.Info().SlugName] = true
}
return nil
})
resp := make([]*schema.GetPluginListResp, 0)
_ = plugin.CallBase(func(base plugin.Base) error {
info := base.Info()
resp = append(resp, &schema.GetPluginListResp{
Name: info.Name,
SlugName: info.SlugName,
Description: info.Description,
Version: info.Version,
Enabled: plugin.StatusManager.IsEnabled(info.SlugName),
HaveConfig: pluginConfigMapping[info.SlugName],
})
return nil
})
if len(req.Status) > 0 {
resp = pc.filterPluginByStatus(resp, req.Status)
}
if req.HaveConfig {
resp = pc.filterNoConfigPlugin(resp)
}
handler.HandleResponse(ctx, nil, resp)
}
func (pc *PluginController) filterNoConfigPlugin(list []*schema.GetPluginListResp) []*schema.GetPluginListResp {
resp := make([]*schema.GetPluginListResp, 0)
for _, t := range list {
if t.HaveConfig {
resp = append(resp, t)
}
}
return resp
}
func (pc *PluginController) filterPluginByStatus(list []*schema.GetPluginListResp, status schema.PluginStatus,
) []*schema.GetPluginListResp {
resp := make([]*schema.GetPluginListResp, 0)
for _, t := range list {
if status == schema.PluginStatusActive && t.Enabled {
resp = append(resp, t)
} else if status == schema.PluginStatusInactive && !t.Enabled {
resp = append(resp, t)
}
}
return resp
}
// UpdatePluginStatus update plugin status
// @Summary update plugin status
// @Description update plugin status
// @Tags admin
// @Tags AdminPlugin
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param data body schema.UpdatePluginStatusReq true "UpdatePluginStatusReq"
// @Success 200 {object} handler.RespBody
// @Router /answer/api/v1/question/status [put]
// @Router /answer/admin/api/plugin/status [put]
func (pc *PluginController) UpdatePluginStatus(ctx *gin.Context) {
req := &schema.UpdatePluginStatusReq{}
if handler.BindAndCheck(ctx, req) {
@ -63,23 +110,81 @@ func (pc *PluginController) UpdatePluginStatus(ctx *gin.Context) {
}
// GetPluginConfig get plugin config
// @Summary get plugin config
// @Description get plugin config
// @Tags AdminPlugin
// @Security ApiKeyAuth
// @Produce json
// @Param plugin_slug_name query string true "plugin_slug_name"
// @Success 200 {object} handler.RespBody{data=schema.GetPluginConfigResp}
// @Router /answer/admin/api/plugin/config [get]
func (pc *PluginController) GetPluginConfig(ctx *gin.Context) {
req := &schema.GetPluginConfigReq{}
if handler.BindAndCheck(ctx, req) {
return
}
resp, err := pc.roleService.GetRoleList(ctx)
handler.HandleResponse(ctx, err, resp)
resp := &schema.GetPluginConfigResp{}
_ = plugin.CallBase(func(base plugin.Base) error {
if base.Info().SlugName != req.PluginSlugName {
return nil
}
info := base.Info()
resp.Name = info.Name
resp.SlugName = info.SlugName
resp.Description = info.Description
resp.Version = info.Version
return nil
})
_ = plugin.CallConfig(func(fn plugin.Config) error {
if fn.Info().SlugName != req.PluginSlugName {
return nil
}
// resp.ConfigFields = fn.ConfigFields()
configFields := fn.ConfigFields()
resp.ConfigFields = make([]*schema.ConfigField, 0)
for _, field := range configFields {
resp.ConfigFields = append(resp.ConfigFields, &schema.ConfigField{
Name: field.Items[0].Name,
Type: schema.TEXT,
Title: field.Name,
Description: field.Description,
Required: field.Required,
UIOptions: schema.UIOptions{
Placeholder: field.Items[0].PlaceHolder,
Type: string(schema.TEXT),
},
Value: field.Items[0].Value,
})
}
return nil
})
handler.HandleResponse(ctx, nil, resp)
}
// UpdatePluginConfig get plugin config
// UpdatePluginConfig update plugin config
// @Summary update plugin config
// @Description update plugin config
// @Tags AdminPlugin
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param data body schema.UpdatePluginConfigReq true "UpdatePluginConfigReq"
// @Success 200 {object} handler.RespBody
// @Router /answer/admin/api/plugin/config [put]
func (pc *PluginController) UpdatePluginConfig(ctx *gin.Context) {
req := &schema.GetPluginConfigReq{}
req := &schema.UpdatePluginConfigReq{}
if handler.BindAndCheck(ctx, req) {
return
}
resp, err := pc.roleService.GetRoleList(ctx)
handler.HandleResponse(ctx, err, resp)
configFields, _ := json.Marshal(req.ConfigFields)
err := plugin.CallConfig(func(fn plugin.Config) error {
if fn.Info().SlugName == req.PluginSlugName {
return fn.ConfigReceiver(configFields)
}
return nil
})
handler.HandleResponse(ctx, err, nil)
}

View File

@ -10,19 +10,19 @@ const (
)
type ConfigField struct {
Name string
Description string
Required bool
Type ConfigType
Items []ConfigFieldItem
Name string `json:"name"`
Description string `json:"description"`
Required bool `json:"required"`
Type ConfigType `json:"type"`
Items []ConfigFieldItem `json:"items"`
}
type ConfigFieldItem struct {
Name string
Label string
Value string
PlaceHolder string
Selected bool
Name string `json:"name"`
Label string `json:"label"`
Value string `json:"value"`
PlaceHolder string `json:"place_holder"`
Selected bool `json:"selected"`
}
type Config interface {

View File

@ -7,42 +7,40 @@ import (
"os"
"github.com/answerdev/answer/internal/plugin"
"github.com/go-resty/resty/v2"
"github.com/google/go-github/v48/github"
"golang.org/x/oauth2"
oauth2GitHub "golang.org/x/oauth2/github"
)
type GitHub struct {
ClientID string
ClientSecret string
Config *GitHubConfig
}
type GitHubConfig struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
}
func init() {
plugin.Register(&GitHub{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
Config: &GitHubConfig{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
},
})
}
func (g *GitHub) Info() plugin.Info {
return plugin.Info{
Name: "github connector",
SlugName: "github_connector",
Description: "github connector plugin",
Version: "0.0.1",
}
}
func (g *GitHub) ConnectorLogo() []byte {
response, err := resty.New().R().Get("https://cdn-icons-png.flaticon.com/32/25/25231.png")
if err != nil {
return nil
}
return response.Body()
}
func (g *GitHub) ConnectorLogoContentType() string {
return "image/png"
func (g *GitHub) ConnectorLogoSVG() string {
return `M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z`
}
func (g *GitHub) ConnectorName() string {
@ -55,8 +53,8 @@ func (g *GitHub) ConnectorSlugName() string {
func (g *GitHub) ConnectorSender(ctx *plugin.GinContext, receiverURL string) (redirectURL string) {
oauth2Config := &oauth2.Config{
ClientID: g.ClientID,
ClientSecret: g.ClientSecret,
ClientID: g.Config.ClientID,
ClientSecret: g.Config.ClientSecret,
Endpoint: oauth2GitHub.Endpoint,
RedirectURL: receiverURL,
Scopes: nil,
@ -68,8 +66,8 @@ func (g *GitHub) ConnectorReceiver(ctx *plugin.GinContext) (userInfo plugin.Exte
code := ctx.Query("code")
// Exchange code for token
oauth2Config := &oauth2.Config{
ClientID: g.ClientID,
ClientSecret: g.ClientSecret,
ClientID: g.Config.ClientID,
ClientSecret: g.Config.ClientSecret,
Endpoint: oauth2GitHub.Endpoint,
}
token, err := oauth2Config.Exchange(context.Background(), code)
@ -95,3 +93,41 @@ func (g *GitHub) ConnectorReceiver(ctx *plugin.GinContext) (userInfo plugin.Exte
}
return userInfo, nil
}
func (g *GitHub) ConfigFields() []plugin.ConfigField {
return []plugin.ConfigField{
{
Name: "ClientID",
Description: "Client ID of your GitHub application.",
Required: true,
Type: plugin.ConfigTypeInput,
Items: []plugin.ConfigFieldItem{
{
Name: "client_id",
Label: "ClientID",
Value: g.Config.ClientID,
},
},
},
{
Name: "ClientSecret",
Description: "Client secret of your GitHub application.",
Required: true,
Type: plugin.ConfigTypeInput,
Items: []plugin.ConfigFieldItem{
{
Name: "client_secret",
Label: "ClientSecret",
Value: g.Config.ClientSecret,
},
},
},
}
}
func (g *GitHub) ConfigReceiver(config []byte) error {
c := &GitHubConfig{}
_ = json.Unmarshal(config, c)
g.Config = c
return nil
}

View File

@ -30,6 +30,7 @@ func init() {
func (g *Google) Info() plugin.Info {
return plugin.Info{
Name: "google connector",
SlugName: "google_connector",
Description: "google connector plugin",
Version: "0.0.1",
}

View File

@ -53,6 +53,27 @@ func (ur *userExternalLoginRepo) GetByExternalID(ctx context.Context, externalID
return
}
// GetUserExternalLoginList get by external ID
func (ur *userExternalLoginRepo) GetUserExternalLoginList(ctx context.Context, userID string) (
resp []*entity.UserExternalLogin, err error) {
resp = make([]*entity.UserExternalLogin, 0)
err = ur.data.DB.Where("user_id = ?", userID).Find(&resp)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}
// DeleteUserExternalLogin delete external user login info
func (ur *userExternalLoginRepo) DeleteUserExternalLogin(ctx context.Context, userID, externalID string) (err error) {
cond := &entity.UserExternalLogin{}
_, err = ur.data.DB.Where("user_id = ? AND external_id = ?", userID, externalID).Delete(cond)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}
// SetCacheUserExternalLoginInfo cache user info for external login
func (ur *userExternalLoginRepo) SetCacheUserExternalLoginInfo(
ctx context.Context, key string, info *schema.ExternalLoginUserInfoCache) (err error) {

View File

@ -31,6 +31,7 @@ type AnswerAPIRouter struct {
uploadController *controller.UploadController
activityController *controller.ActivityController
roleController *controller_admin.RoleController
pluginController *controller_admin.PluginController
}
func NewAnswerAPIRouter(
@ -58,6 +59,7 @@ func NewAnswerAPIRouter(
uploadController *controller.UploadController,
activityController *controller.ActivityController,
roleController *controller_admin.RoleController,
pluginController *controller_admin.PluginController,
) *AnswerAPIRouter {
return &AnswerAPIRouter{
langController: langController,
@ -84,6 +86,7 @@ func NewAnswerAPIRouter(
uploadController: uploadController,
activityController: activityController,
roleController: roleController,
pluginController: pluginController,
}
}
@ -279,4 +282,10 @@ func (a *AnswerAPIRouter) RegisterAnswerAdminAPIRouter(r *gin.RouterGroup) {
// roles
r.GET("/roles", a.roleController.GetRoleList)
// plugin
r.GET("/plugins", a.pluginController.GetPluginList)
r.PUT("/plugin/status", a.pluginController.UpdatePluginStatus)
r.GET("/plugin/config", a.pluginController.GetPluginConfig)
r.PUT("/plugin/config", a.pluginController.UpdatePluginConfig)
}

View File

@ -18,7 +18,7 @@ func NewPluginAPIRouter(
}
}
func (pr *PluginAPIRouter) RegisterConnector(r *gin.Engine) {
func (pr *PluginAPIRouter) RegisterUnAuthConnectorRouter(r *gin.RouterGroup) {
connectorController := pr.connectorController
_ = plugin.CallConnector(func(connector plugin.Connector) error {
connectorSlugName := connector.ConnectorSlugName()
@ -26,6 +26,12 @@ func (pr *PluginAPIRouter) RegisterConnector(r *gin.Engine) {
r.GET(controller.ConnectorRedirectRouterPrefix+connectorSlugName, connectorController.ConnectorRedirect(connector))
return nil
})
r.GET("/answer/api/v1/connector/info", connectorController.ConnectorsInfo)
r.POST("/answer/api/v1/connector/binding/email", connectorController.ExternalLoginBindingUserSendEmail)
r.GET("/connector/info", connectorController.ConnectorsInfo)
r.POST("/connector/binding/email", connectorController.ExternalLoginBindingUserSendEmail)
}
func (pr *PluginAPIRouter) RegisterAuthConnectorRouter(r *gin.RouterGroup) {
connectorController := pr.connectorController
r.GET("/connector/user/info", connectorController.ConnectorsUserInfo)
r.DELETE("/connector/user/unbinding", connectorController.ExternalLoginUnbinding)
}

View File

@ -5,3 +5,11 @@ type ConnectorInfoResp struct {
Icon string `json:"icon"`
Link string `json:"link"`
}
type ConnectorUserInfoResp struct {
Name string `json:"name"`
Icon string `json:"icon"`
Link string `json:"link"`
Binding bool `json:"binding"`
ExternalID string `json:"external_id"`
}

View File

@ -1,7 +1,5 @@
package schema
import "github.com/answerdev/answer/internal/plugin"
const (
PluginStatusActive PluginStatus = "active"
PluginStatusInactive PluginStatus = "inactive"
@ -9,11 +7,18 @@ const (
type PluginStatus string
type GetPluginListReq struct {
Status PluginStatus `form:"status"`
HaveConfig bool `form:"have_config"`
}
type GetPluginListResp struct {
Name string `json:"name"`
SlugName string `json:"slug_name"`
Description string `json:"description"`
Version string `json:"version"`
Enabled bool `json:"enabled"`
HaveConfig bool `json:"have_config"`
}
type UpdatePluginStatusReq struct {
@ -22,13 +27,48 @@ type UpdatePluginStatusReq struct {
}
type GetPluginConfigReq struct {
PluginSlugName string `validate:"required,gt=1,lte=100" json:"plugin_slug_name"`
PluginSlugName string `validate:"required,gt=1,lte=100" form:"plugin_slug_name"`
}
type GetPluginConfigResp struct {
ConfigFields []plugin.ConfigField
//ConfigFields []plugin.ConfigField `json:"config_fields"`
Name string `json:"name"`
SlugName string `json:"slug_name"`
Description string `json:"description"`
Version string `json:"version"`
ConfigFields []*ConfigField `json:"config_fields"`
}
const (
TEXT ConfigFieldType = "text"
Select ConfigFieldType = "select"
Checkbox ConfigFieldType = "checkbox"
)
type ConfigFieldType string
type ConfigField struct {
Name string `json:"name"`
Type ConfigFieldType `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Required bool `json:"required"`
Value string `json:"value"`
UIOptions UIOptions `json:"ui_options"`
Options []Option `json:"options"`
}
type UIOptions struct {
Placeholder string `json:"placeholder"`
Type string `json:"type"`
}
type Option struct {
Label string `json:"label"`
Value string `json:"value"`
}
type UpdatePluginConfigReq struct {
PluginSlugName string `validate:"required,gt=1,lte=100" json:"plugin_slug_name"`
PluginSlugName string `validate:"required,gt=1,lte=100" json:"plugin_slug_name"`
ConfigFields map[string]any `json:"config_fields"`
}

View File

@ -46,3 +46,9 @@ type ExternalLoginUserInfoCache struct {
// optional. The original user information provided by the third-party login platform
MetaInfo string
}
// ExternalLoginUnbindingReq external login unbinding user
type ExternalLoginUnbindingReq struct {
ExternalID string `validate:"required,gt=0,lte=128" json:"external_id"`
UserID string `json:"-"`
}

View File

@ -23,6 +23,9 @@ type UserExternalLoginRepo interface {
AddUserExternalLogin(ctx context.Context, user *entity.UserExternalLogin) (err error)
UpdateInfo(ctx context.Context, userInfo *entity.UserExternalLogin) (err error)
GetByExternalID(ctx context.Context, externalID string) (userInfo *entity.UserExternalLogin, exist bool, err error)
GetUserExternalLoginList(ctx context.Context, userID string) (
resp []*entity.UserExternalLogin, err error)
DeleteUserExternalLogin(ctx context.Context, userID, externalID string) (err error)
SetCacheUserExternalLoginInfo(ctx context.Context, key string, info *schema.ExternalLoginUserInfoCache) (err error)
GetCacheUserExternalLoginInfo(ctx context.Context, key string) (info *schema.ExternalLoginUserInfoCache, err error)
}
@ -218,3 +221,15 @@ func (us *UserExternalLoginService) ExternalLoginBindingUser(
}
return us.bindOldUser(ctx, externalLoginInfo, oldUserInfo)
}
// GetExternalLoginUserInfoList get external login user info list
func (us *UserExternalLoginService) GetExternalLoginUserInfoList(
ctx context.Context, userID string) (resp []*entity.UserExternalLogin, err error) {
return us.userExternalLoginRepo.GetUserExternalLoginList(ctx, userID)
}
// ExternalLoginUnbinding external login unbinding
func (us *UserExternalLoginService) ExternalLoginUnbinding(
ctx context.Context, req *schema.ExternalLoginUnbindingReq) (err error) {
return us.userExternalLoginRepo.DeleteUserExternalLogin(ctx, req.UserID, req.ExternalID)
}