captcha: fix missing images

The captcha library's data struct wasn't being serialized/deserialized
fully, meaning the image was never stored. I never really wanted it to
be stored anyway, but as a compromise, the invite daemon now deletes
captcha images from the DB 20 minutes after generation.
pull/298/head
Harvey Tindall 1 year ago
parent 4607a30e6a
commit a0f1cd5814
No known key found for this signature in database
GPG Key ID: BBC65952848FB1A2

@ -13,9 +13,26 @@ import (
"github.com/timshannon/badgerhold/v4" "github.com/timshannon/badgerhold/v4"
) )
const (
CAPTCHA_VALIDITY = 20 * 60 // Seconds
)
func (app *appContext) checkInvites() { func (app *appContext) checkInvites() {
currentTime := time.Now() currentTime := time.Now()
for _, data := range app.storage.GetInvites() { for _, data := range app.storage.GetInvites() {
captchas := data.Captchas
captchasExpired := false
for key, capt := range data.Captchas {
if time.Now().After(capt.Generated.Add(CAPTCHA_VALIDITY * time.Second)) {
delete(captchas, key)
captchasExpired = true
}
}
if captchasExpired {
data.Captchas = captchas
app.storage.SetInvitesKey(data.Code, data)
}
if data.IsReferral { if data.IsReferral {
continue continue
} }

@ -11,7 +11,6 @@ import (
"time" "time"
"github.com/hrfee/mediabrowser" "github.com/hrfee/mediabrowser"
"github.com/steambap/captcha"
"github.com/timshannon/badgerhold/v4" "github.com/timshannon/badgerhold/v4"
) )
@ -501,12 +500,18 @@ type Invite struct {
Notify map[string]map[string]bool `json:"notify"` Notify map[string]map[string]bool `json:"notify"`
Profile string `json:"profile"` Profile string `json:"profile"`
Label string `json:"label,omitempty"` Label string `json:"label,omitempty"`
Captchas map[string]*captcha.Data // Map of Captcha IDs to answers Captchas map[string]Captcha // Map of Captcha IDs to images & answers
IsReferral bool `json:"is_referral" badgerhold:"index"` IsReferral bool `json:"is_referral" badgerhold:"index"`
ReferrerJellyfinID string `json:"referrer_id"` ReferrerJellyfinID string `json:"referrer_id"`
ReferrerTemplateForProfile string ReferrerTemplateForProfile string
} }
type Captcha struct {
Answer string
Image []byte // image/png
Generated time.Time
}
type Lang struct { type Lang struct {
AdminPath string AdminPath string
chosenAdminLang string chosenAdminLang string

@ -1,6 +1,8 @@
package main package main
import ( import (
"bufio"
"bytes"
"encoding/json" "encoding/json"
"html/template" "html/template"
"io" "io"
@ -372,20 +374,16 @@ func (app *appContext) GetCaptcha(gc *gin.Context) {
"contactMessage": app.config.Section("ui").Key("contact_message").String(), "contactMessage": app.config.Section("ui").Key("contact_message").String(),
}) })
} }
var capt *captcha.Data var capt Captcha
ok = true
if inv.Captchas != nil { if inv.Captchas != nil {
capt = inv.Captchas[captchaID] capt, ok = inv.Captchas[captchaID]
} }
if capt == nil { if !ok {
respondBool(400, false, gc) respondBool(400, false, gc)
return return
} }
if err := capt.WriteImage(gc.Writer); err != nil { gc.Data(200, "image/png", capt.Image)
app.err.Printf("Failed to write CAPTCHA image: %v", err)
respondBool(500, false, gc)
return
}
gc.Status(200)
return return
} }
@ -414,10 +412,20 @@ func (app *appContext) GenCaptcha(gc *gin.Context) {
return return
} }
if inv.Captchas == nil { if inv.Captchas == nil {
inv.Captchas = map[string]*captcha.Data{} inv.Captchas = map[string]Captcha{}
} }
captchaID := genAuthToken() captchaID := genAuthToken()
inv.Captchas[captchaID] = capt var buf bytes.Buffer
if err := capt.WriteImage(bufio.NewWriter(&buf)); err != nil {
app.err.Printf("Failed to render captcha: %v", err)
respondBool(500, false, gc)
return
}
inv.Captchas[captchaID] = Captcha{
Answer: capt.Text,
Image: buf.Bytes(),
Generated: time.Now(),
}
app.storage.SetInvitesKey(code, inv) app.storage.SetInvitesKey(code, inv)
gc.JSON(200, genCaptchaDTO{captchaID}) gc.JSON(200, genCaptchaDTO{captchaID})
return return
@ -437,7 +445,7 @@ func (app *appContext) verifyCaptcha(code, id, text string) bool {
app.debug.Printf("Couldn't find Captcha \"%s\"", id) app.debug.Printf("Couldn't find Captcha \"%s\"", id)
return false return false
} }
return strings.ToLower(c.Text) == strings.ToLower(text) return strings.ToLower(c.Answer) == strings.ToLower(text)
} }
// reCAPTCHA // reCAPTCHA
@ -504,15 +512,15 @@ func (app *appContext) VerifyCaptcha(gc *gin.Context) {
}) })
return return
} }
var capt *captcha.Data var capt Captcha
if inv.Captchas != nil { if inv.Captchas != nil {
capt = inv.Captchas[captchaID] capt, ok = inv.Captchas[captchaID]
} }
if capt == nil { if !ok {
respondBool(400, false, gc) respondBool(400, false, gc)
return return
} }
if strings.ToLower(capt.Text) != strings.ToLower(text) { if strings.ToLower(capt.Answer) != strings.ToLower(text) {
respondBool(400, false, gc) respondBool(400, false, gc)
return return
} }

Loading…
Cancel
Save