1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

webui: Remove sessions & securecookie

This commit is contained in:
James Hillyerd
2018-12-14 21:55:31 -08:00
parent d627da2038
commit 4894244d5c
9 changed files with 10 additions and 87 deletions

View File

@@ -32,7 +32,6 @@ variables it supports:
INBUCKET_WEB_GREETINGFILE ui/greeting.html Home page greeting HTML INBUCKET_WEB_GREETINGFILE ui/greeting.html Home page greeting HTML
INBUCKET_WEB_TEMPLATECACHE true Cache templates after first use? INBUCKET_WEB_TEMPLATECACHE true Cache templates after first use?
INBUCKET_WEB_MAILBOXPROMPT @inbucket Prompt next to mailbox input INBUCKET_WEB_MAILBOXPROMPT @inbucket Prompt next to mailbox input
INBUCKET_WEB_COOKIEAUTHKEY Session cipher key (text)
INBUCKET_WEB_MONITORVISIBLE true Show monitor tab in UI? INBUCKET_WEB_MONITORVISIBLE true Show monitor tab in UI?
INBUCKET_WEB_MONITORHISTORY 30 Monitor remembered messages INBUCKET_WEB_MONITORHISTORY 30 Monitor remembered messages
INBUCKET_WEB_PPROF false Expose profiling tools on /debug/pprof INBUCKET_WEB_PPROF false Expose profiling tools on /debug/pprof

3
go.mod
View File

@@ -3,10 +3,9 @@ module github.com/jhillyerd/inbucket
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/subcommands v0.0.0-20181012225330-46f0354f6315 github.com/google/subcommands v0.0.0-20181012225330-46f0354f6315
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/css v1.0.0 github.com/gorilla/css v1.0.0
github.com/gorilla/mux v1.6.2 github.com/gorilla/mux v1.6.2
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.1.3
github.com/gorilla/websocket v1.4.0 github.com/gorilla/websocket v1.4.0
github.com/jhillyerd/enmime v0.4.0 github.com/jhillyerd/enmime v0.4.0
github.com/jhillyerd/goldiff v0.1.0 github.com/jhillyerd/goldiff v0.1.0

4
go.sum
View File

@@ -12,10 +12,6 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.1.3 h1:uXoZdcdA5XdXF3QzuSlheVRUvjl+1rKY7zBXL68L9RU=
github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 h1:xqgexXAGQgY3HAjNPSaCqn5Aahbo5TKsmhp8VRfr1iQ= github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 h1:xqgexXAGQgY3HAjNPSaCqn5Aahbo5TKsmhp8VRfr1iQ=

View File

@@ -97,7 +97,6 @@ type Web struct {
GreetingFile string `required:"true" default:"ui/greeting.html" desc:"Home page greeting HTML"` GreetingFile string `required:"true" default:"ui/greeting.html" desc:"Home page greeting HTML"`
TemplateCache bool `required:"true" default:"true" desc:"Cache templates after first use?"` TemplateCache bool `required:"true" default:"true" desc:"Cache templates after first use?"`
MailboxPrompt string `required:"true" default:"@inbucket" desc:"Prompt next to mailbox input"` MailboxPrompt string `required:"true" default:"@inbucket" desc:"Prompt next to mailbox input"`
CookieAuthKey string `desc:"Session cipher key (text)"`
MonitorVisible bool `required:"true" default:"true" desc:"Show monitor tab in UI?"` MonitorVisible bool `required:"true" default:"true" desc:"Show monitor tab in UI?"`
MonitorHistory int `required:"true" default:"30" desc:"Monitor remembered messages"` MonitorHistory int `required:"true" default:"30" desc:"Monitor remembered messages"`
PProf bool `required:"true" default:"false" desc:"Expose profiling tools on /debug/pprof"` PProf bool `required:"true" default:"false" desc:"Expose profiling tools on /debug/pprof"`

View File

@@ -159,16 +159,16 @@ func ValidateDomainPart(domain string) bool {
// domain part is optional and not validated. // domain part is optional and not validated.
func parseEmailAddress(address string) (local string, domain string, err error) { func parseEmailAddress(address string) (local string, domain string, err error) {
if address == "" { if address == "" {
return "", "", fmt.Errorf("Empty address") return "", "", fmt.Errorf("empty address")
} }
if len(address) > 320 { if len(address) > 320 {
return "", "", fmt.Errorf("Address exceeds 320 characters") return "", "", fmt.Errorf("address exceeds 320 characters")
} }
if address[0] == '@' { if address[0] == '@' {
return "", "", fmt.Errorf("Address cannot start with @ symbol") return "", "", fmt.Errorf("address cannot start with @ symbol")
} }
if address[0] == '.' { if address[0] == '.' {
return "", "", fmt.Errorf("Address cannot start with a period") return "", "", fmt.Errorf("address cannot start with a period")
} }
// Loop over address parsing out local part. // Loop over address parsing out local part.
buf := new(bytes.Buffer) buf := new(bytes.Buffer)

View File

@@ -5,7 +5,6 @@ import (
"strings" "strings"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/gorilla/sessions"
"github.com/jhillyerd/inbucket/pkg/config" "github.com/jhillyerd/inbucket/pkg/config"
"github.com/jhillyerd/inbucket/pkg/message" "github.com/jhillyerd/inbucket/pkg/message"
"github.com/jhillyerd/inbucket/pkg/msghub" "github.com/jhillyerd/inbucket/pkg/msghub"
@@ -15,7 +14,6 @@ import (
// TODO remove redundant web config // TODO remove redundant web config
type Context struct { type Context struct {
Vars map[string]string Vars map[string]string
Session *sessions.Session
MsgHub *msghub.Hub MsgHub *msghub.Hub
Manager message.Manager Manager message.Manager
RootConfig *config.Root RootConfig *config.Root
@@ -48,24 +46,13 @@ func headerMatch(req *http.Request, name string, value string) bool {
// NewContext returns a Context for the given HTTP Request // NewContext returns a Context for the given HTTP Request
func NewContext(req *http.Request) (*Context, error) { func NewContext(req *http.Request) (*Context, error) {
vars := mux.Vars(req) vars := mux.Vars(req)
sess, err := sessionStore.Get(req, "inbucket")
if err != nil {
if sess == nil {
// No session, must fail
return nil, err
}
// The session cookie was probably signed by an old key, ignore it
// gorilla created an empty session for us
err = nil
}
ctx := &Context{ ctx := &Context{
Vars: vars, Vars: vars,
Session: sess,
MsgHub: msgHub, MsgHub: msgHub,
Manager: manager, Manager: manager,
RootConfig: rootConfig, RootConfig: rootConfig,
WebConfig: rootConfig.Web, WebConfig: rootConfig.Web,
IsJSON: headerMatch(req, "Accept", "application/json"), IsJSON: headerMatch(req, "Accept", "application/json"),
} }
return ctx, err return ctx, nil
} }

View File

@@ -11,8 +11,6 @@ import (
"time" "time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/gorilla/securecookie"
"github.com/gorilla/sessions"
"github.com/jhillyerd/inbucket/pkg/config" "github.com/jhillyerd/inbucket/pkg/config"
"github.com/jhillyerd/inbucket/pkg/message" "github.com/jhillyerd/inbucket/pkg/message"
"github.com/jhillyerd/inbucket/pkg/msghub" "github.com/jhillyerd/inbucket/pkg/msghub"
@@ -36,7 +34,6 @@ var (
rootConfig *config.Root rootConfig *config.Root
server *http.Server server *http.Server
listener net.Listener listener net.Listener
sessionStore sessions.Store
globalShutdown chan bool globalShutdown chan bool
// ExpWebSocketConnectsCurrent tracks the number of open WebSockets // ExpWebSocketConnectsCurrent tracks the number of open WebSockets
@@ -94,17 +91,6 @@ func Initialize(
http.StatusNotFound, "No route matches URI path") http.StatusNotFound, "No route matches URI path")
Router.MethodNotAllowedHandler = noMatchHandler( Router.MethodNotAllowedHandler = noMatchHandler(
http.StatusMethodNotAllowed, "Method not allowed for URI path") http.StatusMethodNotAllowed, "Method not allowed for URI path")
// Session cookie setup.
if conf.Web.CookieAuthKey == "" {
log.Info().Str("module", "web").Str("phase", "startup").
Msg("Generating random cookie.auth.key")
sessionStore = sessions.NewCookieStore(securecookie.GenerateRandomKey(64))
} else {
log.Info().Str("module", "web").Str("phase", "startup").
Msg("Using configured cookie.auth.key")
sessionStore = sessions.NewCookieStore([]byte(conf.Web.CookieAuthKey))
}
} }
// Start begins listening for HTTP requests // Start begins listening for HTTP requests

View File

@@ -1,6 +1,7 @@
package webui package webui
import ( import (
"errors"
"fmt" "fmt"
"html/template" "html/template"
"io" "io"
@@ -147,19 +148,13 @@ func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *web.Contex
// Don't have to validate these aren't empty, Gorilla returns 404 // Don't have to validate these aren't empty, Gorilla returns 404
name, err := ctx.Manager.MailboxForAddress(ctx.Vars["name"]) name, err := ctx.Manager.MailboxForAddress(ctx.Vars["name"])
if err != nil { if err != nil {
ctx.Session.AddFlash(err.Error(), "errors") return err
_ = ctx.Session.Save(req, w)
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
return nil
} }
id := ctx.Vars["id"] id := ctx.Vars["id"]
numStr := ctx.Vars["num"] numStr := ctx.Vars["num"]
num, err := strconv.ParseUint(numStr, 10, 32) num, err := strconv.ParseUint(numStr, 10, 32)
if err != nil { if err != nil {
ctx.Session.AddFlash("Attachment number must be unsigned numeric", "errors") return err
_ = ctx.Session.Save(req, w)
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
return nil
} }
msg, err := ctx.Manager.GetMessage(name, id) msg, err := ctx.Manager.GetMessage(name, id)
if err == storage.ErrNotExist { if err == storage.ErrNotExist {
@@ -171,10 +166,7 @@ func MailboxViewAttach(w http.ResponseWriter, req *http.Request, ctx *web.Contex
return fmt.Errorf("GetMessage(%q) failed: %v", id, err) return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
} }
if int(num) >= len(msg.Attachments()) { if int(num) >= len(msg.Attachments()) {
ctx.Session.AddFlash("Attachment number too high", "errors") return errors.New("requested attachment number does not exist")
_ = ctx.Session.Save(req, w)
http.Redirect(w, req, web.Reverse("RootIndex"), http.StatusSeeOther)
return nil
} }
// Output attachment // Output attachment
part := msg.Attachments()[num] part := msg.Attachments()[num]

View File

@@ -1,35 +0,0 @@
package webui
import (
"github.com/jhillyerd/inbucket/pkg/server/web"
)
const (
// maximum mailboxes to remember
maxRemembered = 8
// session value key; referenced in templates, do not change
mailboxKey = "recentMailboxes"
)
// RememberMailbox manages the list of recently accessed mailboxes stored in the session
func RememberMailbox(ctx *web.Context, mailbox string) {
recent := RecentMailboxes(ctx)
newRecent := make([]string, 1, maxRemembered)
newRecent[0] = mailbox
for _, recBox := range recent {
// Insert until newRecent is full, but don't repeat the new mailbox
if len(newRecent) < maxRemembered && mailbox != recBox {
newRecent = append(newRecent, recBox)
}
}
ctx.Session.Values[mailboxKey] = newRecent
}
// RecentMailboxes returns a slice of the most recently accessed mailboxes
func RecentMailboxes(ctx *web.Context) []string {
val := ctx.Session.Values[mailboxKey]
recent, _ := val.([]string)
return recent
}