82 lines
2.5 KiB
Go
82 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"gitea.zheromiku.top/Weknora/dobotai-platform/internal/dingtalkconfig"
|
|
"gitea.zheromiku.top/Weknora/dobotai-platform/internal/questiontable"
|
|
"gitea.zheromiku.top/Weknora/dobotai-platform/internal/secretstore"
|
|
"gitea.zheromiku.top/Weknora/dobotai-platform/internal/settings"
|
|
)
|
|
|
|
type candidateConfigRepository interface {
|
|
CandidateDingTalkConfig(context.Context, string) (string, string, error)
|
|
ActivateDingTalkCandidate(context.Context, string, string) error
|
|
}
|
|
|
|
type candidateCredentialVerifier interface {
|
|
Verify(context.Context, string, string) dingtalkconfig.Result
|
|
}
|
|
|
|
var (
|
|
candidateTokenURL = ""
|
|
candidateTableBaseURL = ""
|
|
)
|
|
|
|
type dingTalkCandidateActivator struct {
|
|
tenant string
|
|
repo candidateConfigRepository
|
|
secrets *secretstore.Store
|
|
verifier candidateCredentialVerifier
|
|
bindings map[string]settings.ResourceBinding
|
|
restart func()
|
|
}
|
|
|
|
func (a *dingTalkCandidateActivator) ActivateCandidate(ctx context.Context) error {
|
|
if a == nil || a.repo == nil || a.secrets == nil || a.verifier == nil || a.restart == nil {
|
|
return errors.New("candidate_activation_unavailable")
|
|
}
|
|
clientID, secretRef, err := a.repo.CandidateDingTalkConfig(ctx, a.tenant)
|
|
if err != nil {
|
|
return errors.New("candidate_not_found")
|
|
}
|
|
secret, err := a.secrets.Get(secretRef)
|
|
if err != nil {
|
|
return errors.New("candidate_secret_unavailable")
|
|
}
|
|
if result := a.verifier.Verify(ctx, clientID, secret); !result.OK {
|
|
return errors.New("candidate_oauth_failed")
|
|
}
|
|
for _, kind := range []string{"question_table", "faq_table"} {
|
|
binding, ok := a.bindings[kind]
|
|
if !ok {
|
|
continue
|
|
}
|
|
client, err := questiontable.NewClient(questiontable.Config{ClientID: clientID, Secret: secret, BaseID: binding.BaseID, SheetID: binding.SheetID, OperatorID: binding.OperatorID, TokenURL: candidateTokenURL, BaseURL: candidateTableBaseURL}, nil)
|
|
if err != nil {
|
|
return errors.New("candidate_table_config_failed")
|
|
}
|
|
fields, err := client.ReadFields(ctx)
|
|
if err != nil {
|
|
return errors.New("candidate_table_probe_failed")
|
|
}
|
|
required := questiontable.QuestionSchema()
|
|
if kind == "faq_table" {
|
|
required = questiontable.FAQSchema()
|
|
}
|
|
if _, err = questiontable.MapRequiredFields(fields, required); err != nil {
|
|
return errors.New("candidate_table_schema_failed")
|
|
}
|
|
}
|
|
if err := a.repo.ActivateDingTalkCandidate(ctx, a.tenant, secretRef); err != nil {
|
|
return errors.New("candidate_database_activation_failed")
|
|
}
|
|
go func() {
|
|
time.Sleep(300 * time.Millisecond)
|
|
a.restart()
|
|
}()
|
|
return nil
|
|
}
|