Skip to content

Add importer plugin type #1122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

181 changes: 181 additions & 0 deletions internal/service/importer/importer_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package importer

import (
"context"
"fmt"

"github.com/apache/incubator-answer/internal/base/handler"
"github.com/apache/incubator-answer/internal/base/reason"
"github.com/apache/incubator-answer/internal/base/translator"
"github.com/apache/incubator-answer/internal/base/validator"
"github.com/apache/incubator-answer/internal/schema"
"github.com/apache/incubator-answer/internal/service/content"
"github.com/apache/incubator-answer/internal/service/permission"
"github.com/apache/incubator-answer/internal/service/rank"
usercommon "github.com/apache/incubator-answer/internal/service/user_common"
"github.com/apache/incubator-answer/plugin"
"github.com/gin-gonic/gin"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
)

// ImporterService importer service
type ImporterService struct {
questionService *content.QuestionService
rankService *rank.RankService
userCommon *usercommon.UserCommon
}

// NewRankService new rank service
func NewImporterService(
questionService *content.QuestionService,
rankService *rank.RankService,
userCommon *usercommon.UserCommon) *ImporterService {
return &ImporterService{
questionService: questionService,
rankService: rankService,
userCommon: userCommon,
}
}

type ImporterFunc struct {
importerService *ImporterService
}

func (ipfunc *ImporterFunc) AddQuestion(ctx context.Context, questionInfo plugin.QuestionImporterInfo) {
println("Hello, World123!")
ipfunc.importerService.AddQuestion123(ctx, questionInfo)
}

func (ip *ImporterService) NewImporterFunc() plugin.ImporterFunc {
return &ImporterFunc{importerService: ip}
}

func (ip *ImporterService) AddQuestion123(ctx context.Context, questionInfo plugin.QuestionImporterInfo) {
fmt.Println("Call from func (ip *ImporterService) AddQuestion123(*****)")
// body, err := io.ReadAll(ctx.Request.Body)
// ctx.Request.Body = io.NopCloser(bytes.NewBuffer(body))
fmt.Println("ImportPush")

// if err != nil {
// log.Errorf("error: %v", err)
// return
// }
req := &schema.QuestionAdd{}
errFields := make([]*validator.FormErrorField, 0)
// reject, rejectKey := ipc.rateLimitMiddleware.DuplicateRequestRejection(ctx, req)
// if reject {
// return
// }
user_info, exist, err := ip.userCommon.GetByEmail(ctx, questionInfo.UserEmail)
if err != nil {
log.Errorf("error: %v", err)
return
}
if !exist {
log.Errorf("error: User Email not found")
return
}

// defer func() {
// // If status is not 200 means that the bad request has been returned, so the record should be cleared
// if ctx.Writer.Status() != http.StatusOK {
// ipc.rateLimitMiddleware.DuplicateRequestClear(ctx, rejectKey)
// }
// }()
req.UserID = user_info.ID
req.Title = questionInfo.Title
req.Content = questionInfo.Content
req.HTML = "<p>" + questionInfo.Content + "</p>"
req.Tags = make([]*schema.TagItem, len(questionInfo.Tags))
for i, tag := range questionInfo.Tags {
req.Tags[i] = &schema.TagItem{
SlugName: tag,
DisplayName: tag,
}
}
canList, requireRanks, err := ip.rankService.CheckOperationPermissionsForRanks(ctx, req.UserID, []string{
permission.QuestionAdd,
permission.QuestionEdit,
permission.QuestionDelete,
permission.QuestionClose,
permission.QuestionReopen,
permission.TagUseReservedTag,
permission.TagAdd,
permission.LinkUrlLimit,
})
if err != nil {
log.Errorf("error: %v", err)
return
}
req.CanAdd = canList[0]
req.CanEdit = canList[1]
req.CanDelete = canList[2]
req.CanClose = canList[3]
req.CanReopen = canList[4]
req.CanUseReservedTag = canList[5]
req.CanAddTag = canList[6]
if !req.CanAdd {
log.Errorf("error: %v", err)
return
}
hasNewTag, err := ip.questionService.HasNewTag(ctx.(*gin.Context), req.Tags)
if err != nil {
log.Errorf("error: %v", err)
return
}
if !req.CanAddTag && hasNewTag {
lang := handler.GetLang(ctx.(*gin.Context))
msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: requireRanks[6]})
log.Errorf("error: %v", msg)
return
}

errList, err := ip.questionService.CheckAddQuestion(ctx, req)
if err != nil {
errlist, ok := errList.([]*validator.FormErrorField)
if ok {
errFields = append(errFields, errlist...)
}
}
if len(errFields) > 0 {
handler.HandleResponse(ctx.(*gin.Context), errors.BadRequest(reason.RequestFormatError), errFields)
log.Errorf("error: RequestFormat Error")
return
}
ginCtx := ctx.(*gin.Context)
req.UserAgent = ginCtx.GetHeader("User-Agent")
req.IP = ginCtx.ClientIP()
resp, err := ip.questionService.AddQuestion(ctx, req)
if err != nil {
errlist, ok := resp.([]*validator.FormErrorField)
if ok {
errFields = append(errFields, errlist...)
}
}

if len(errFields) > 0 {
log.Errorf("error: RequestFormatError")
return
}
log.Info("Add Question Successfully")
}
11 changes: 11 additions & 0 deletions internal/service/plugin_common/plugin_common_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package plugin_common
import (
"context"
"encoding/json"
"fmt"

"github.com/apache/incubator-answer/internal/base/data"
"github.com/apache/incubator-answer/internal/repo/search_sync"
Expand All @@ -34,6 +35,7 @@ import (
"github.com/apache/incubator-answer/internal/entity"
"github.com/apache/incubator-answer/internal/schema"
"github.com/apache/incubator-answer/internal/service/config"
"github.com/apache/incubator-answer/internal/service/importer"
"github.com/apache/incubator-answer/plugin"
)

Expand All @@ -56,6 +58,7 @@ type PluginCommonService struct {
pluginConfigRepo PluginConfigRepo
pluginUserConfigRepo PluginUserConfigRepo
data *data.Data
importerService *importer.ImporterService
}

// NewPluginCommonService new report service
Expand All @@ -64,13 +67,15 @@ func NewPluginCommonService(
pluginUserConfigRepo PluginUserConfigRepo,
configService *config.ConfigService,
data *data.Data,
importerService *importer.ImporterService,
) *PluginCommonService {

p := &PluginCommonService{
configService: configService,
pluginConfigRepo: pluginConfigRepo,
pluginUserConfigRepo: pluginUserConfigRepo,
data: data,
importerService: importerService,
}
p.initPluginData()
return p
Expand Down Expand Up @@ -99,6 +104,11 @@ func (ps *PluginCommonService) UpdatePluginConfig(ctx context.Context, req *sche
}
return nil
})
_ = plugin.CallImporter(func(importer plugin.Importer) error {
fmt.Println("更新时注册Importer")
importer.RegisterImporterFunc(ctx, ps.importerService.NewImporterFunc())
return nil
})
return nil
}

Expand Down Expand Up @@ -126,6 +136,7 @@ func (ps *PluginCommonService) GetUserPluginConfig(ctx context.Context, req *sch
}

func (ps *PluginCommonService) initPluginData() {
fmt.Println("init plugin data")
// init plugin status
pluginStatus, err := ps.configService.GetStringValue(context.TODO(), constant.PluginStatus)
if err != nil {
Expand Down
62 changes: 62 additions & 0 deletions plugin/importer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package plugin

import (
"context"
)

type QuestionImporterInfo struct {
Title string `json:"title"`
Content string `json:"content"`
Tags []string `json:"tags"`
UserEmail string `json:"user_email"`
}

type Importer interface {
Base
RegisterImporterFunc(ctx context.Context, importer ImporterFunc)
}

type ImporterFunc interface {
AddQuestion(ctx context.Context, questionInfo QuestionImporterInfo)
}

var (
// CallImporter is a function that calls all registered parsers
CallImporter,
registerImporter = MakePlugin[Importer](false)
)

func ImporterEnabled() (enabled bool) {
_ = CallImporter(func(fn Importer) error {
enabled = true
return nil
})
return
}
func GetImporter() (ip Importer, ok bool) {
_ = CallImporter(func(fn Importer) error {
ip = fn
ok = true
return nil
})
return
}
4 changes: 4 additions & 0 deletions plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ func Register(p Base) {
if _, ok := p.(CDN); ok {
registerCDN(p.(CDN))
}

if _, ok := p.(Importer); ok {
registerImporter(p.(Importer))
}
}

type Stack[T Base] struct {
Expand Down