diff --git a/api-users.go b/api-users.go index 3b2e934..b73f591 100644 --- a/api-users.go +++ b/api-users.go @@ -242,12 +242,17 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc success = false return } - inv, _ := app.storage.GetInvitesKey(req.Code) - if inv.ConfirmationKeys == nil { - inv.ConfirmationKeys = map[string]newUserDTO{} + if app.ConfirmationKeys == nil { + app.ConfirmationKeys = map[string]map[string]newUserDTO{} } - inv.ConfirmationKeys[key] = req - app.storage.SetInvitesKey(req.Code, inv) + cKeys, ok := app.ConfirmationKeys[req.Code] + if !ok { + cKeys = map[string]newUserDTO{} + } + cKeys[key] = req + app.confirmationKeysLock.Lock() + app.ConfirmationKeys[req.Code] = cKeys + app.confirmationKeysLock.Unlock() f = func(gc *gin.Context) { app.debug.Printf("%s: Email confirmation required", req.Code) respond(401, "confirmEmail", gc) diff --git a/main.go b/main.go index 40ce405..79643cd 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" "syscall" "time" @@ -90,27 +91,29 @@ type appContext struct { adminUsers []User invalidTokens []string // Keeping jf name because I can't think of a better one - jf *mediabrowser.MediaBrowser - authJf *mediabrowser.MediaBrowser - ombi *ombi.Ombi - datePattern string - timePattern string - storage Storage - validator Validator - email *Emailer - telegram *TelegramDaemon - discord *DiscordDaemon - matrix *MatrixDaemon - info, debug, err *logger.Logger - host string - port int - version string - URLBase string - updater *Updater - newUpdate bool // Whether whatever's in update is new. - tag Tag - update Update - internalPWRs map[string]InternalPWR + jf *mediabrowser.MediaBrowser + authJf *mediabrowser.MediaBrowser + ombi *ombi.Ombi + datePattern string + timePattern string + storage Storage + validator Validator + email *Emailer + telegram *TelegramDaemon + discord *DiscordDaemon + matrix *MatrixDaemon + info, debug, err *logger.Logger + host string + port int + version string + URLBase string + updater *Updater + newUpdate bool // Whether whatever's in update is new. + tag Tag + update Update + internalPWRs map[string]InternalPWR + ConfirmationKeys map[string]map[string]newUserDTO // Map of invite code to jwt to request + confirmationKeysLock sync.Mutex } func generateSecret(length int) (string, error) { diff --git a/storage.go b/storage.go index 415c798..873d6c4 100644 --- a/storage.go +++ b/storage.go @@ -274,12 +274,11 @@ type Invite struct { UserMinutes int `json:"user-minutes,omitempty"` SendTo string `json:"email"` // Used to be stored as formatted time, now as Unix. - UsedBy [][]string `json:"used-by"` - Notify map[string]map[string]bool `json:"notify"` - Profile string `json:"profile"` - Label string `json:"label,omitempty"` - ConfirmationKeys map[string]newUserDTO `json:"-"` // map of JWT confirmation keys to their original requests - Captchas map[string]*captcha.Data // Map of Captcha IDs to answers + UsedBy [][]string `json:"used-by"` + Notify map[string]map[string]bool `json:"notify"` + Profile string `json:"profile"` + Label string `json:"label,omitempty"` + Captchas map[string]*captcha.Data // Map of Captcha IDs to answers } type Lang struct { diff --git a/views.go b/views.go index 8ce557b..5a20ae2 100644 --- a/views.go +++ b/views.go @@ -512,7 +512,6 @@ func (app *appContext) InviteProxy(gc *gin.Context) { return } if key := gc.Query("key"); key != "" && app.config.Section("email_confirmation").Key("enabled").MustBool(false) { - req, ok := inv.ConfirmationKeys[key] fail := func() { gcHTML(gc, 404, "404.html", gin.H{ "cssClass": app.cssClass, @@ -520,6 +519,18 @@ func (app *appContext) InviteProxy(gc *gin.Context) { "contactMessage": app.config.Section("ui").Key("contact_message").String(), }) } + var req newUserDTO + if app.ConfirmationKeys == nil { + fail() + return + } + + invKeys, ok := app.ConfirmationKeys[code] + if !ok { + fail() + return + } + req, ok = invKeys[key] if !ok { fail() return @@ -537,8 +548,11 @@ func (app *appContext) InviteProxy(gc *gin.Context) { app.debug.Printf("Invalid key") return } - _, success := app.newUser(req, true) + f, success := app.newUser(req, true) if !success { + app.err.Printf("Failed to create new user") + // Not meant for us. Calling this will be a mess, but at least it might give us some information. + f(gc) fail() return } @@ -554,11 +568,10 @@ func (app *appContext) InviteProxy(gc *gin.Context) { "jfLink": jfLink, }) } - inv, ok := app.storage.GetInvitesKey(code) - if ok { - delete(inv.ConfirmationKeys, key) - app.storage.SetInvitesKey(code, inv) - } + delete(invKeys, key) + app.confirmationKeysLock.Lock() + app.ConfirmationKeys[code] = invKeys + app.confirmationKeysLock.Unlock() return } email := ""