|
|
|
package bootstrap
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"slices"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-hclog"
|
|
|
|
"github.com/maruel/natural"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/synctv-org/synctv/cmd/flags"
|
|
|
|
"github.com/synctv-org/synctv/internal/conf"
|
|
|
|
"github.com/synctv-org/synctv/internal/model"
|
|
|
|
"github.com/synctv-org/synctv/internal/provider"
|
|
|
|
"github.com/synctv-org/synctv/internal/provider/plugins"
|
|
|
|
"github.com/synctv-org/synctv/internal/provider/providers"
|
|
|
|
"github.com/synctv-org/synctv/internal/settings"
|
|
|
|
"github.com/synctv-org/synctv/utils"
|
|
|
|
"github.com/zijiren233/gencontainer/refreshcache"
|
|
|
|
)
|
|
|
|
|
|
|
|
var ProviderGroupSettings = make(map[model.SettingGroup]*ProviderGroupSetting)
|
|
|
|
|
|
|
|
type ProviderGroupSetting struct {
|
|
|
|
Enabled settings.BoolSetting
|
|
|
|
ClientID settings.StringSetting
|
|
|
|
ClientSecret settings.StringSetting
|
|
|
|
RedirectURL settings.StringSetting
|
|
|
|
DisableUserSignup settings.BoolSetting
|
|
|
|
SignupNeedReview settings.BoolSetting
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
Oauth2EnabledCache = refreshcache.NewRefreshCache[[]provider.OAuth2Provider](func(context.Context, ...any) ([]provider.OAuth2Provider, error) {
|
|
|
|
ps := providers.EnabledProvider()
|
|
|
|
r := make([]provider.OAuth2Provider, 0, ps.Len())
|
|
|
|
providers.EnabledProvider().Range(func(key provider.OAuth2Provider, value provider.ProviderInterface) bool {
|
|
|
|
r = append(r, key)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
slices.SortStableFunc(r, func(a, b provider.OAuth2Provider) int {
|
|
|
|
if a == b {
|
|
|
|
return 0
|
|
|
|
} else if natural.Less(string(a), string(b)) {
|
|
|
|
return -1
|
|
|
|
} else {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return r, nil
|
|
|
|
}, 0)
|
|
|
|
)
|
|
|
|
|
|
|
|
func InitProvider(ctx context.Context) (err error) {
|
|
|
|
logOur := log.StandardLogger().Writer()
|
|
|
|
logLevle := hclog.Info
|
|
|
|
if flags.Dev {
|
|
|
|
logLevle = hclog.Debug
|
|
|
|
}
|
|
|
|
for _, op := range conf.Conf.Oauth2Plugins {
|
|
|
|
op.PluginFile, err = utils.OptFilePath(op.PluginFile)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("oauth2 plugin file path error: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Infof("load oauth2 plugin: %s", op.PluginFile)
|
|
|
|
err := os.MkdirAll(filepath.Dir(op.PluginFile), 0755)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("create plugin dir: %s failed: %s", filepath.Dir(op.PluginFile), err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = plugins.InitProviderPlugins(op.PluginFile, op.Args, hclog.New(&hclog.LoggerOptions{
|
|
|
|
Name: op.PluginFile,
|
|
|
|
Level: logLevle,
|
|
|
|
Output: logOur,
|
|
|
|
Color: hclog.ForceColor,
|
|
|
|
}))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("load oauth2 plugin: %s failed: %s", op.PluginFile, err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for op, pi := range providers.AllProvider() {
|
|
|
|
op, pi := op, pi
|
|
|
|
group := model.SettingGroup(fmt.Sprintf("%s_%s", model.SettingGroupOauth2, op))
|
|
|
|
groupSettings := &ProviderGroupSetting{}
|
|
|
|
ProviderGroupSettings[group] = groupSettings
|
|
|
|
|
|
|
|
groupSettings.Enabled = settings.NewBoolSetting(fmt.Sprintf("%s_enabled", group), false, group, settings.WithBeforeInitBool(func(bs settings.BoolSetting, b bool) (bool, error) {
|
|
|
|
defer Oauth2EnabledCache.Refresh(ctx)
|
|
|
|
if b {
|
|
|
|
return b, providers.EnableProvider(op)
|
|
|
|
} else {
|
|
|
|
providers.DisableProvider(op)
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
}), settings.WithBeforeSetBool(func(bs settings.BoolSetting, b bool) (bool, error) {
|
|
|
|
defer Oauth2EnabledCache.Refresh(ctx)
|
|
|
|
if b {
|
|
|
|
return b, providers.EnableProvider(op)
|
|
|
|
} else {
|
|
|
|
providers.DisableProvider(op)
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
|
|
|
|
opt := provider.Oauth2Option{}
|
|
|
|
|
|
|
|
groupSettings.ClientID = settings.NewStringSetting(fmt.Sprintf("%s_client_id", group), opt.ClientID, group, settings.WithBeforeInitString(func(ss settings.StringSetting, s string) (string, error) {
|
|
|
|
opt.ClientID = s
|
|
|
|
pi.Init(opt)
|
|
|
|
return s, nil
|
|
|
|
}), settings.WithBeforeSetString(func(ss settings.StringSetting, s string) (string, error) {
|
|
|
|
opt.ClientID = s
|
|
|
|
pi.Init(opt)
|
|
|
|
return s, nil
|
|
|
|
}))
|
|
|
|
|
|
|
|
groupSettings.ClientSecret = settings.NewStringSetting(fmt.Sprintf("%s_client_secret", group), opt.ClientSecret, group, settings.WithBeforeInitString(func(ss settings.StringSetting, s string) (string, error) {
|
|
|
|
opt.ClientSecret = s
|
|
|
|
pi.Init(opt)
|
|
|
|
return s, nil
|
|
|
|
}), settings.WithBeforeSetString(func(ss settings.StringSetting, s string) (string, error) {
|
|
|
|
opt.ClientSecret = s
|
|
|
|
pi.Init(opt)
|
|
|
|
return s, nil
|
|
|
|
}))
|
|
|
|
|
|
|
|
groupSettings.RedirectURL = settings.NewStringSetting(fmt.Sprintf("%s_redirect_url", group), opt.RedirectURL, group, settings.WithBeforeInitString(func(ss settings.StringSetting, s string) (string, error) {
|
|
|
|
opt.RedirectURL = s
|
|
|
|
pi.Init(opt)
|
|
|
|
return s, nil
|
|
|
|
}), settings.WithBeforeSetString(func(ss settings.StringSetting, s string) (string, error) {
|
|
|
|
opt.RedirectURL = s
|
|
|
|
pi.Init(opt)
|
|
|
|
return s, nil
|
|
|
|
}))
|
|
|
|
|
|
|
|
groupSettings.DisableUserSignup = settings.NewBoolSetting(fmt.Sprintf("%s_disable_user_signup", group), false, group)
|
|
|
|
|
|
|
|
groupSettings.SignupNeedReview = settings.NewBoolSetting(fmt.Sprintf("%s_signup_need_review", group), false, group)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|