Browse Source

Export Context

This allows plugins to access it.
master
Simon Ser 4 years ago
parent
commit
d8f411176f
No known key found for this signature in database GPG Key ID: FDE7BE0E88F5E48
3 changed files with 34 additions and 29 deletions
  1. +14
    -14
      handlers.go
  2. +14
    -9
      server.go
  3. +6
    -6
      template.go

+ 14
- 14
handlers.go View File

@@ -25,7 +25,7 @@ type MailboxRenderData struct {
} }


func handleGetMailbox(ectx echo.Context) error { func handleGetMailbox(ectx echo.Context) error {
ctx := ectx.(*context)
ctx := ectx.(*Context)


mboxName, err := url.PathUnescape(ctx.Param("mbox")) mboxName, err := url.PathUnescape(ctx.Param("mbox"))
if err != nil { if err != nil {
@@ -43,7 +43,7 @@ func handleGetMailbox(ectx echo.Context) error {
var mailboxes []*imap.MailboxInfo var mailboxes []*imap.MailboxInfo
var msgs []imapMessage var msgs []imapMessage
var mbox *imap.MailboxStatus var mbox *imap.MailboxStatus
err = ctx.session.Do(func(c *imapclient.Client) error {
err = ctx.Session.Do(func(c *imapclient.Client) error {
var err error var err error
if mailboxes, err = listMailboxes(c); err != nil { if mailboxes, err = listMailboxes(c); err != nil {
return err return err
@@ -77,12 +77,12 @@ func handleGetMailbox(ectx echo.Context) error {
} }


func handleLogin(ectx echo.Context) error { func handleLogin(ectx echo.Context) error {
ctx := ectx.(*context)
ctx := ectx.(*Context)


username := ctx.FormValue("username") username := ctx.FormValue("username")
password := ctx.FormValue("password") password := ctx.FormValue("password")
if username != "" && password != "" { if username != "" && password != "" {
s, err := ctx.server.sessions.Put(username, password)
s, err := ctx.Server.sessions.Put(username, password)
if err != nil { if err != nil {
if _, ok := err.(AuthError); ok { if _, ok := err.(AuthError); ok {
return ctx.Render(http.StatusOK, "login.html", nil) return ctx.Render(http.StatusOK, "login.html", nil)
@@ -98,9 +98,9 @@ func handleLogin(ectx echo.Context) error {
} }


func handleLogout(ectx echo.Context) error { func handleLogout(ectx echo.Context) error {
ctx := ectx.(*context)
ctx := ectx.(*Context)


ctx.session.Close()
ctx.Session.Close()
ctx.setToken("") ctx.setToken("")
return ctx.Redirect(http.StatusFound, "/login") return ctx.Redirect(http.StatusFound, "/login")
} }
@@ -114,7 +114,7 @@ type MessageRenderData struct {
MailboxPage int MailboxPage int
} }


func handleGetPart(ctx *context, raw bool) error {
func handleGetPart(ctx *Context, raw bool) error {
mboxName, uid, err := parseMboxAndUid(ctx.Param("mbox"), ctx.Param("uid")) mboxName, uid, err := parseMboxAndUid(ctx.Param("mbox"), ctx.Param("uid"))
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
@@ -128,7 +128,7 @@ func handleGetPart(ctx *context, raw bool) error {
var msg *imapMessage var msg *imapMessage
var part *message.Entity var part *message.Entity
var mbox *imap.MailboxStatus var mbox *imap.MailboxStatus
err = ctx.session.Do(func(c *imapclient.Client) error {
err = ctx.Session.Do(func(c *imapclient.Client) error {
var err error var err error
msg, part, err = getMessagePart(c, mboxName, uid, partPath) msg, part, err = getMessagePart(c, mboxName, uid, partPath)
mbox = c.Mailbox() mbox = c.Mailbox()
@@ -188,11 +188,11 @@ type ComposeRenderData struct {
} }


func handleCompose(ectx echo.Context) error { func handleCompose(ectx echo.Context) error {
ctx := ectx.(*context)
ctx := ectx.(*Context)


var msg OutgoingMessage var msg OutgoingMessage
if strings.ContainsRune(ctx.session.username, '@') {
msg.From = ctx.session.username
if strings.ContainsRune(ctx.Session.username, '@') {
msg.From = ctx.Session.username
} }


if ctx.Request().Method == http.MethodGet && ctx.Param("uid") != "" { if ctx.Request().Method == http.MethodGet && ctx.Param("uid") != "" {
@@ -208,7 +208,7 @@ func handleCompose(ectx echo.Context) error {


var inReplyTo *imapMessage var inReplyTo *imapMessage
var part *message.Entity var part *message.Entity
err = ctx.session.Do(func(c *imapclient.Client) error {
err = ctx.Session.Do(func(c *imapclient.Client) error {
var err error var err error
inReplyTo, part, err = getMessagePart(c, mboxName, uid, partPath) inReplyTo, part, err = getMessagePart(c, mboxName, uid, partPath)
return err return err
@@ -257,13 +257,13 @@ func handleCompose(ectx echo.Context) error {
msg.Text = ctx.FormValue("text") msg.Text = ctx.FormValue("text")
msg.InReplyTo = ctx.FormValue("in_reply_to") msg.InReplyTo = ctx.FormValue("in_reply_to")


c, err := ctx.server.connectSMTP()
c, err := ctx.Server.connectSMTP()
if err != nil { if err != nil {
return err return err
} }
defer c.Close() defer c.Close()


auth := sasl.NewPlainClient("", ctx.session.username, ctx.session.password)
auth := sasl.NewPlainClient("", ctx.Session.username, ctx.Session.password)
if err := c.Auth(auth); err != nil { if err := c.Auth(auth); err != nil {
return echo.NewHTTPError(http.StatusForbidden, err) return echo.NewHTTPError(http.StatusForbidden, err)
} }


+ 14
- 9
server.go View File

@@ -91,15 +91,20 @@ func newServer(imapURL, smtpURL string) (*Server, error) {
return s, nil return s, nil
} }


type context struct {
// Context is the context used by HTTP handlers.
//
// Use a type assertion to get it from a echo.Context:
//
// ctx := ectx.(*koushin.Context)
type Context struct {
echo.Context echo.Context
server *Server
session *Session
Server *Server
Session *Session
} }


var aLongTimeAgo = time.Unix(233431200, 0) var aLongTimeAgo = time.Unix(233431200, 0)


func (c *context) setToken(token string) {
func (c *Context) setToken(token string) {
cookie := http.Cookie{ cookie := http.Cookie{
Name: cookieName, Name: cookieName,
Value: token, Value: token,
@@ -151,7 +156,7 @@ func New(e *echo.Echo, options *Options) error {


e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(ectx echo.Context) error { return func(ectx echo.Context) error {
ctx := &context{Context: ectx, server: s}
ctx := &Context{Context: ectx, Server: s}
ctx.Set("context", ctx) ctx.Set("context", ctx)


cookie, err := ctx.Cookie(cookieName) cookie, err := ctx.Cookie(cookieName)
@@ -166,14 +171,14 @@ func New(e *echo.Echo, options *Options) error {
return err return err
} }


ctx.session, err = ctx.server.sessions.Get(cookie.Value)
ctx.Session, err = ctx.Server.sessions.Get(cookie.Value)
if err == ErrSessionExpired { if err == ErrSessionExpired {
ctx.setToken("") ctx.setToken("")
return ctx.Redirect(http.StatusFound, "/login") return ctx.Redirect(http.StatusFound, "/login")
} else if err != nil { } else if err != nil {
return err return err
} }
ctx.session.Ping()
ctx.Session.Ping()


return next(ctx) return next(ctx)
} }
@@ -182,11 +187,11 @@ func New(e *echo.Echo, options *Options) error {
e.GET("/mailbox/:mbox", handleGetMailbox) e.GET("/mailbox/:mbox", handleGetMailbox)


e.GET("/message/:mbox/:uid", func(ectx echo.Context) error { e.GET("/message/:mbox/:uid", func(ectx echo.Context) error {
ctx := ectx.(*context)
ctx := ectx.(*Context)
return handleGetPart(ctx, false) return handleGetPart(ctx, false)
}) })
e.GET("/message/:mbox/:uid/raw", func(ectx echo.Context) error { e.GET("/message/:mbox/:uid/raw", func(ectx echo.Context) error {
ctx := ectx.(*context)
ctx := ectx.(*Context)
return handleGetPart(ctx, true) return handleGetPart(ctx, true)
}) })




+ 6
- 6
template.go View File

@@ -31,12 +31,12 @@ type RenderData struct {
Extra map[string]interface{} Extra map[string]interface{}
} }


func NewRenderData(ctx *context) *RenderData {
func NewRenderData(ctx *Context) *RenderData {
global := GlobalRenderData{Extra: make(map[string]interface{})} global := GlobalRenderData{Extra: make(map[string]interface{})}


if ctx.session != nil {
if ctx.Session != nil {
global.LoggedIn = true global.LoggedIn = true
global.Username = ctx.session.username
global.Username = ctx.Session.username
} }


return &RenderData{ return &RenderData{
@@ -52,10 +52,10 @@ type renderer struct {
} }


func (r *renderer) Render(w io.Writer, name string, data interface{}, ectx echo.Context) error { func (r *renderer) Render(w io.Writer, name string, data interface{}, ectx echo.Context) error {
// ectx is the raw *echo.context, not our own *context
ctx := ectx.Get("context").(*context)
// ectx is the raw *echo.context, not our own *Context
ctx := ectx.Get("context").(*Context)


for _, plugin := range ctx.server.plugins {
for _, plugin := range ctx.Server.plugins {
if err := plugin.Inject(name, data); err != nil { if err := plugin.Inject(name, data); err != nil {
return fmt.Errorf("failed to run plugin '%v': %v", plugin.Name(), err) return fmt.Errorf("failed to run plugin '%v': %v", plugin.Name(), err)
} }


Loading…
Cancel
Save