Refector: setting

pull/24/head
zijiren233 2 years ago
parent 20ca7352b5
commit 12b90a15f2

@ -1,47 +0,0 @@
package setting
import (
"fmt"
"github.com/spf13/cobra"
"github.com/synctv-org/synctv/internal/bootstrap"
"github.com/synctv-org/synctv/internal/settings"
)
var FixCmd = &cobra.Command{
Use: "fix",
Short: "fix setting",
Long: `fix setting`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return bootstrap.New(bootstrap.WithContext(cmd.Context())).Add(
bootstrap.InitDiscardLog,
bootstrap.InitConfig,
bootstrap.InitDatabase,
bootstrap.InitSetting,
).Run()
},
RunE: func(cmd *cobra.Command, args []string) error {
count := 0
errorCount := 0
for k, s := range settings.Settings {
_, err := s.Interface()
if err != nil {
fmt.Printf("setting %s, interface error: %v\n", k, err)
err = s.SetRaw(s.DefaultRaw())
if err != nil {
errorCount++
fmt.Printf("setting %s fix error: %v\n", k, err)
} else {
count++
fmt.Printf("setting %s fix success\n", k)
}
}
}
fmt.Printf("fix success: %d, fix error: %d\n", count, errorCount)
return nil
},
}
func init() {
SettingCmd.AddCommand(FixCmd)
}

@ -35,7 +35,7 @@ var SetCmd = &cobra.Command{
s.SetRaw(current)
fmt.Printf("set setting %s error: %v\n", args[0], err)
}
if v, err := s.Interface(); err != nil {
if v := s.Interface(); err != nil {
s.SetRaw(current)
fmt.Printf("set setting %s error: %v\n", args[0], err)
} else {

@ -1,7 +1,6 @@
package setting
import (
"fmt"
"os"
"github.com/spf13/cobra"
@ -30,12 +29,7 @@ var ShowCmd = &cobra.Command{
m[g] = make(map[string]any)
}
for _, v := range s {
i, err := v.Interface()
if err != nil {
fmt.Printf("parse setting %s error: %v\ntry to fix setting\n", v.Name(), err)
return nil
}
m[g][v.Name()] = i
m[g][v.Name()] = v.Interface()
}
}
return yaml.NewEncoder(os.Stdout).Encode(m)

@ -2,17 +2,11 @@ package bootstrap
import (
"context"
"time"
"github.com/synctv-org/synctv/internal/conf"
"github.com/synctv-org/synctv/internal/op"
)
func InitOp(ctx context.Context) error {
d, err := time.ParseDuration(conf.Conf.Room.TTL)
if err != nil {
return err
}
op.Init(4096, d)
op.Init(4096)
return nil
}

@ -20,9 +20,6 @@ type Config struct {
// Proxy
Proxy ProxyConfig `yaml:"proxy" hc:"you can use proxy to proxy movie and live when custom headers or network is slow to connect to origin server"`
// Room
Room RoomConfig `yaml:"room"`
// Database
Database DatabaseConfig `yaml:"database"`
@ -54,9 +51,6 @@ func DefaultConfig() *Config {
// Proxy
Proxy: DefaultProxyConfig(),
// Room
Room: DefaultRoomConfig(),
// Database
Database: DefaultDatabaseConfig(),

@ -1,13 +0,0 @@
package conf
type RoomConfig struct {
MustPassword bool `yaml:"must_password" hc:"must input password to create room" env:"ROOM_MUST_PASSWORD"`
TTL string `yaml:"ttl" hc:"set how long the room will be inactive before the memory will be reclaimed"`
}
func DefaultRoomConfig() RoomConfig {
return RoomConfig{
MustPassword: false,
TTL: "48h",
}
}

@ -36,6 +36,12 @@ func WithRelations(relations []model.RoomUserRelation) CreateRoomConfig {
}
}
func WithStatus(status model.RoomStatus) CreateRoomConfig {
return func(r *model.Room) {
r.Status = status
}
}
func CreateRoom(name, password string, conf ...CreateRoomConfig) (*model.Room, error) {
var hashedPassword []byte
if password != "" {

@ -9,10 +9,20 @@ import (
"gorm.io/gorm"
)
type RoomStatus string
const (
RoomStatusBanned RoomStatus = "banned"
RoomStatusPending RoomStatus = "pending"
RoomStatusStopped RoomStatus = "stopped"
RoomStatusActive RoomStatus = "active"
)
type Room struct {
ID string `gorm:"not null;primaryKey;type:varchar(36)" json:"id"`
CreatedAt time.Time
UpdatedAt time.Time
Status RoomStatus `gorm:"not null;default:pending"`
Name string `gorm:"not null;uniqueIndex"`
Settings Settings `gorm:"embedded;embeddedPrefix:settings_"`
CreatorID string `gorm:"index"`

@ -25,7 +25,7 @@ type User struct {
UpdatedAt time.Time
Providers []UserProvider `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Username string `gorm:"not null;uniqueIndex"`
Role Role `gorm:"not null;default:user"`
Role Role `gorm:"not null;default:pending"`
GroupUserRelations []RoomUserRelation `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Rooms []Room `gorm:"foreignKey:CreatorID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Movies []Movie `gorm:"foreignKey:CreatorID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`

@ -7,8 +7,7 @@ import (
synccache "github.com/synctv-org/synctv/utils/syncCache"
)
func Init(size int, ttl time.Duration) error {
roomTTL = ttl
func Init(size int) error {
roomCache = synccache.NewSyncCache[string, *Room](time.Minute*5, synccache.WithDeletedCallback[string, *Room](func(v *Room) {
v.close()
}))

@ -7,11 +7,11 @@ import (
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/settings"
synccache "github.com/synctv-org/synctv/utils/syncCache"
"github.com/zijiren233/gencontainer/heap"
)
var roomTTL = time.Hour * 24 * 2
var roomCache *synccache.SyncCache[string, *Room]
func CreateRoom(name, password string, conf ...db.CreateRoomConfig) (*Room, error) {
@ -31,14 +31,16 @@ func InitRoom(room *model.Room) (*Room, error) {
roomID: room.ID,
},
}
i, loaded := roomCache.LoadOrStore(room.ID, r, roomTTL)
i, loaded := roomCache.LoadOrStore(room.ID, r, time.Duration(settings.RoomTTL.Get()))
if loaded {
return r, errors.New("room already init")
}
return i.Value(), nil
}
func LoadOrInitRoom(room *model.Room) (*Room, bool) {
func LoadOrInitRoom(room *model.Room) (*Room, error) {
t := time.Duration(settings.RoomTTL.Get())
i, loaded := roomCache.LoadOrStore(room.ID, &Room{
Room: *room,
version: crc32.ChecksumIEEE(room.HashedPassword),
@ -46,11 +48,19 @@ func LoadOrInitRoom(room *model.Room) (*Room, bool) {
movies: movies{
roomID: room.ID,
},
}, roomTTL)
}, t)
if loaded {
i.SetExpiration(time.Now().Add(roomTTL))
i.SetExpiration(time.Now().Add(t))
}
switch room.Status {
case model.RoomStatusBanned:
return nil, errors.New("room banned")
case model.RoomStatusPending:
return nil, errors.New("room pending, please wait for admin to approve")
case model.RoomStatusStopped:
return nil, errors.New("room stopped")
}
return i.Value(), loaded
return i.Value(), nil
}
func DeleteRoom(roomID string) error {
@ -72,7 +82,7 @@ func CloseRoom(roomID string) error {
func LoadRoomByID(id string) (*Room, error) {
r2, loaded := roomCache.Load(id)
if loaded {
r2.SetExpiration(time.Now().Add(roomTTL))
r2.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get())))
return r2.Value(), nil
}
return nil, errors.New("room not found")
@ -84,15 +94,14 @@ func LoadOrInitRoomByID(id string) (*Room, error) {
}
i, loaded := roomCache.Load(id)
if loaded {
i.SetExpiration(time.Now().Add(roomTTL))
i.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get())))
return i.Value(), nil
}
room, err := db.GetRoomByID(id)
if err != nil {
return nil, err
}
r, _ := LoadOrInitRoom(room)
return r, nil
return LoadOrInitRoom(room)
}
func ClientNum(roomID string) int64 {

@ -1,7 +1,9 @@
package settings
import (
log "github.com/sirupsen/logrus"
"fmt"
"strconv"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
)
@ -9,40 +11,54 @@ import (
type BoolSetting interface {
Setting
Set(bool) error
Get() (bool, error)
Get() bool
Default() bool
Parse(string) (bool, error)
Stringify(bool) string
}
var _ BoolSetting = (*Bool)(nil)
type Bool struct {
name string
value string
setting
defaultValue bool
group model.SettingGroup
value bool
}
func NewBool(name string, value bool, group model.SettingGroup) *Bool {
b := &Bool{
setting: setting{
name: name,
group: group,
},
defaultValue: value,
}
if value {
b.value = "1"
} else {
b.value = "0"
value: value,
}
return b
}
func (b *Bool) Name() string {
return b.name
func (b *Bool) Init(value string) error {
v, err := b.Parse(value)
if err != nil {
return err
}
b.value = v
return nil
}
func (b *Bool) Init(s string) {
if b.value == s {
return
func (b *Bool) Parse(value string) (bool, error) {
switch value {
case "1":
return true, nil
case "0":
return false, nil
default:
return strconv.ParseBool(value)
}
b.value = s
}
func (b *Bool) Stringify(value bool) string {
return strconv.FormatBool(value)
}
func (b *Bool) Default() bool {
@ -50,11 +66,11 @@ func (b *Bool) Default() bool {
}
func (b *Bool) DefaultRaw() string {
if b.defaultValue {
return "1"
} else {
return "0"
return b.Stringify(b.defaultValue)
}
func (b *Bool) Raw() string {
return b.Stringify(b.value)
}
func (b *Bool) DefaultInterface() any {
@ -62,51 +78,29 @@ func (b *Bool) DefaultInterface() any {
}
func (b *Bool) SetRaw(value string) error {
if b.value == value {
return nil
err := b.Init(value)
if err != nil {
return err
}
b.value = value
return db.UpdateSettingItemValue(b.name, value)
return db.UpdateSettingItemValue(b.Name(), b.Raw())
}
func (b *Bool) Set(value bool) error {
if value {
return b.SetRaw("1")
} else {
return b.SetRaw("0")
}
}
func (b *Bool) Get() (bool, error) {
return b.value == "1", nil
return b.SetRaw(b.Stringify(value))
}
func (b *Bool) Raw() string {
func (b *Bool) Get() bool {
return b.value
}
func (b *Bool) Type() model.SettingType {
return model.SettingTypeBool
}
func (b *Bool) Group() model.SettingGroup {
return b.group
}
func (b *Bool) Interface() (any, error) {
func (b *Bool) Interface() any {
return b.Get()
}
func newBoolSetting(k string, v bool, g model.SettingGroup) BoolSetting {
if Settings == nil {
Settings = make(map[string]Setting)
}
if GroupSettings == nil {
GroupSettings = make(map[model.SettingGroup][]Setting)
}
_, loaded := Settings[k]
if loaded {
log.Fatalf("setting %s already exists", k)
panic(fmt.Sprintf("setting %s already exists", k))
}
b := NewBool(k, v, g)
Settings[k] = b

@ -0,0 +1,102 @@
package settings
import (
"fmt"
"strconv"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
)
type Float64Setting interface {
Setting
Set(float64) error
Get() float64
Default() float64
Parse(string) (float64, error)
Stringify(float64) string
}
var _ Float64Setting = (*Float64)(nil)
type Float64 struct {
setting
defaultValue float64
value float64
}
func NewFloat64(name string, value float64, group model.SettingGroup) *Float64 {
f := &Float64{
setting: setting{
name: name,
group: group,
},
defaultValue: value,
value: value,
}
return f
}
func (f *Float64) Parse(value string) (float64, error) {
return strconv.ParseFloat(value, 64)
}
func (f *Float64) Stringify(value float64) string {
return strconv.FormatFloat(value, 'f', -1, 64)
}
func (f *Float64) Init(value string) error {
v, err := f.Parse(value)
if err != nil {
return err
}
f.value = v
return nil
}
func (f *Float64) Raw() string {
return f.Stringify(f.value)
}
func (f *Float64) Default() float64 {
return f.defaultValue
}
func (f *Float64) DefaultRaw() string {
return f.Stringify(f.defaultValue)
}
func (f *Float64) DefaultInterface() any {
return f.Default()
}
func (f *Float64) SetRaw(value string) error {
err := f.Init(value)
if err != nil {
return err
}
return db.UpdateSettingItemValue(f.Name(), f.Raw())
}
func (f *Float64) Set(value float64) error {
return f.SetRaw(f.Stringify(value))
}
func (f *Float64) Get() float64 {
return f.value
}
func (f *Float64) Interface() any {
return f.Get()
}
func newFloat64Setting(k string, v float64, g model.SettingGroup) *Float64 {
_, loaded := Settings[k]
if loaded {
panic(fmt.Sprintf("setting %s already exists", k))
}
f := NewFloat64(k, v, g)
Settings[k] = f
GroupSettings[g] = append(GroupSettings[g], f)
return f
}

@ -0,0 +1,102 @@
package settings
import (
"fmt"
"strconv"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
)
type Int64Setting interface {
Setting
Set(int64) error
Get() int64
Default() int64
Parse(string) (int64, error)
Stringify(int64) string
}
var _ Int64Setting = (*Int64)(nil)
type Int64 struct {
setting
defaultValue int64
value int64
}
func NewInt64(name string, value int64, group model.SettingGroup) *Int64 {
i := &Int64{
setting: setting{
name: name,
group: group,
},
defaultValue: value,
value: value,
}
return i
}
func (i *Int64) Parse(value string) (int64, error) {
return strconv.ParseInt(value, 10, 64)
}
func (i *Int64) Stringify(value int64) string {
return strconv.FormatInt(value, 10)
}
func (i *Int64) Init(value string) error {
v, err := i.Parse(value)
if err != nil {
return err
}
i.value = v
return nil
}
func (i *Int64) Default() int64 {
return i.defaultValue
}
func (i *Int64) DefaultRaw() string {
return strconv.FormatInt(i.defaultValue, 10)
}
func (i *Int64) DefaultInterface() any {
return i.defaultValue
}
func (i *Int64) Raw() string {
return i.Stringify(i.value)
}
func (i *Int64) SetRaw(value string) error {
err := i.Init(value)
if err != nil {
return err
}
return db.UpdateSettingItemValue(i.Name(), i.Raw())
}
func (i *Int64) Set(value int64) error {
return i.SetRaw(strconv.FormatInt(value, 10))
}
func (i *Int64) Get() int64 {
return i.value
}
func (i *Int64) Interface() any {
return i.Get()
}
func newInt64Setting(k string, v int64, g model.SettingGroup) *Int64 {
_, loaded := Settings[k]
if loaded {
panic(fmt.Sprintf("setting %s already exists", k))
}
i := NewInt64(k, v, g)
Settings[k] = i
GroupSettings[g] = append(GroupSettings[g], i)
return i
}

@ -9,20 +9,20 @@ import (
)
var (
Settings map[string]Setting
GroupSettings map[model.SettingGroup][]Setting
Settings = make(map[string]Setting)
GroupSettings = make(map[model.SettingGroup][]Setting)
)
type Setting interface {
Name() string
Type() model.SettingType
Group() model.SettingGroup
Init(string)
Init(string) error
Raw() string
SetRaw(string) error
DefaultRaw() string
DefaultInterface() any
Interface() (any, error)
Interface() any
}
func SetValue(name string, value any) error {
@ -89,29 +89,31 @@ func ToSettings[s Setting](settings map[string]s) []Setting {
return ss
}
type Int64Setting interface {
Set(int64) error
Get() (int64, error)
Raw() string
func Init() error {
return initAndFixSettings(ToSettings(Settings)...)
}
type Float64Setting interface {
Set(float64) error
Get() (float64, error)
Raw() string
func initSettings(i ...Setting) error {
for _, b := range i {
s := &model.Setting{
Name: b.Name(),
Value: b.Raw(),
Type: b.Type(),
Group: b.Group(),
}
type StringSetting interface {
Set(string) error
Get() (string, error)
Raw() string
err := db.FirstOrCreateSettingItemValue(s)
if err != nil {
return err
}
err = b.Init(s.Value)
if err != nil {
return err
}
func Init() error {
return initSettings(ToSettings(Settings)...)
}
return nil
}
func initSettings(i ...Setting) error {
func initAndFixSettings(i ...Setting) error {
for _, b := range i {
s := &model.Setting{
Name: b.Name(),
@ -123,7 +125,31 @@ func initSettings(i ...Setting) error {
if err != nil {
return err
}
b.Init(s.Value)
err = b.Init(s.Value)
if err != nil {
// auto fix
err = b.SetRaw(b.DefaultRaw())
if err != nil {
return err
}
}
}
return nil
}
type setting struct {
name string
group model.SettingGroup
}
func (d *setting) Name() string {
return d.name
}
func (d *setting) Type() model.SettingType {
return model.SettingTypeString
}
func (d *setting) Group() model.SettingGroup {
return d.group
}

@ -0,0 +1,101 @@
package settings
import (
"fmt"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
)
type StringSetting interface {
Setting
Set(string) error
Get() string
Default() string
Parse(string) (string, error)
Stringify(string) string
}
var _ StringSetting = (*String)(nil)
type String struct {
setting
defaultValue string
value string
}
func NewString(name string, value string, group model.SettingGroup) *String {
s := &String{
setting: setting{
name: name,
group: group,
},
defaultValue: value,
value: value,
}
return s
}
func (s *String) Parse(value string) (string, error) {
return value, nil
}
func (s *String) Stringify(value string) string {
return value
}
func (s *String) Init(value string) error {
v, err := s.Parse(value)
if err != nil {
return err
}
s.value = v
return nil
}
func (s *String) Default() string {
return s.defaultValue
}
func (s *String) DefaultRaw() string {
return s.defaultValue
}
func (s *String) DefaultInterface() any {
return s.Default()
}
func (s *String) Raw() string {
return s.Stringify(s.value)
}
func (s *String) SetRaw(value string) error {
err := s.Init(value)
if err != nil {
return err
}
return db.UpdateSettingItemValue(s.Name(), s.Raw())
}
func (s *String) Set(value string) error {
return s.SetRaw(value)
}
func (s *String) Get() string {
return s.value
}
func (s *String) Interface() any {
return s.Get()
}
func newStringSetting(k string, v string, g model.SettingGroup) *String {
_, loaded := Settings[k]
if loaded {
panic(fmt.Sprintf("setting %s already exists", k))
}
s := NewString(k, v, g)
Settings[k] = s
GroupSettings[g] = append(GroupSettings[g], s)
return s
}

@ -1,9 +1,16 @@
package settings
import "github.com/synctv-org/synctv/internal/model"
import (
"time"
"github.com/synctv-org/synctv/internal/model"
)
var (
DisableCreateRoom = newBoolSetting("disable_create_room", false, model.SettingGroupRoom)
CreateRoomNeedPwd = newBoolSetting("create_room_need_pwd", false, model.SettingGroupRoom)
CreateRoomNeedReview = newBoolSetting("create_room_need_review", false, model.SettingGroupRoom)
RoomTTL = newInt64Setting("room_ttl", int64(time.Hour*48), model.SettingGroupRoom)
)
var (

@ -48,12 +48,7 @@ func AdminSettings(ctx *gin.Context) {
}
resp := make(gin.H, len(s))
for _, v := range s {
i, err := v.Interface()
if err != nil {
ctx.AbortWithError(http.StatusInternalServerError, err)
return
}
resp[v.Name()] = i
resp[v.Name()] = v.Interface()
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(resp))

@ -16,8 +16,5 @@ func Settings(ctx *gin.Context) {
"movieProxy": conf.Conf.Proxy.MovieProxy,
"liveProxy": conf.Conf.Proxy.LiveProxy,
},
"room": gin.H{
"mustPassword": conf.Conf.Room.MustPassword,
},
}))
}

@ -7,6 +7,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/synctv-org/synctv/internal/db"
dbModel "github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/op"
"github.com/synctv-org/synctv/internal/settings"
"github.com/synctv-org/synctv/server/middlewares"
@ -30,12 +31,7 @@ func (e FormatErrNotSupportPosition) Error() string {
func CreateRoom(ctx *gin.Context) {
user := ctx.MustGet("user").(*op.User)
v, err := settings.DisableCreateRoom.Get()
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
if v && !user.IsAdmin() {
if settings.DisableCreateRoom.Get() && !user.IsAdmin() {
ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("create room is disabled"))
return
}
@ -46,13 +42,23 @@ func CreateRoom(ctx *gin.Context) {
return
}
r, err := user.CreateRoom(req.RoomName, req.Password, db.WithSetting(req.Setting))
CreateRoomNeedReview := settings.CreateRoomNeedReview.Get()
var (
r *dbModel.Room
err error
)
if CreateRoomNeedReview {
r, err = user.CreateRoom(req.RoomName, req.Password, db.WithSetting(req.Setting), db.WithStatus(dbModel.RoomStatusPending))
} else {
r, err = user.CreateRoom(req.RoomName, req.Password, db.WithSetting(req.Setting), db.WithStatus(dbModel.RoomStatusActive))
}
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
room, _ := op.LoadOrInitRoom(r)
room, _ := op.LoadOrInitRoomByID(r.ID)
token, err := middlewares.NewAuthRoomToken(user, room)
if err != nil {

@ -6,8 +6,8 @@ import (
"regexp"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/conf"
"github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/settings"
"github.com/gin-gonic/gin"
)
@ -63,7 +63,7 @@ func (c *CreateRoomReq) Validate() error {
} else if !alnumPrintReg.MatchString(c.Password) {
return ErrPasswordHasInvalidChar
}
} else if conf.Conf.Room.MustPassword {
} else if settings.CreateRoomNeedPwd.Get() {
return FormatEmptyPasswordError("room")
}

@ -86,22 +86,11 @@ func OAuth2Callback(ctx *gin.Context) {
return
}
disable, err := settings.DisableUserSignup.Get()
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
var user *op.User
if disable {
if settings.DisableUserSignup.Get() {
user, err = op.GetUserByProvider(p, ui.ProviderUserID)
} else {
var review bool
review, err = settings.SignupNeedReview.Get()
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
if review {
if settings.SignupNeedReview.Get() {
user, err = op.CreateOrLoadUser(ui.Username, p, ui.ProviderUserID, db.WithRole(dbModel.RolePending))
} else {
user, err = op.CreateOrLoadUser(ui.Username, p, ui.ProviderUserID)
@ -153,13 +142,8 @@ func OAuth2CallbackApi(ctx *gin.Context) {
return
}
disable, err := settings.DisableUserSignup.Get()
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
var user *op.User
if disable {
if settings.DisableUserSignup.Get() {
user, err = op.GetUserByProvider(p, ui.ProviderUserID)
} else {
user, err = op.CreateOrLoadUser(ui.Username, p, ui.ProviderUserID)

Loading…
Cancel
Save