1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-01-26 05:27:33 +02:00

150 lines
4.1 KiB
Go

// Package render is responsible for loading and rendering authboss templates.
package render
//go:generate go-bindata -pkg=render -prefix=templates templates
import (
"bytes"
"errors"
"html/template"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"gopkg.in/authboss.v0"
)
var (
// ErrTemplateNotFound should be returned from Get when the view is not found
ErrTemplateNotFound = errors.New("Template not found")
funcMap = template.FuncMap{
"title": strings.Title,
"mountpathed": func(location string) string {
if authboss.Cfg.MountPath == "/" {
return location
}
return path.Join(authboss.Cfg.MountPath, location)
},
}
)
// Templates is a map depicting the forms a template needs wrapped within the specified layout
type Templates map[string]*template.Template
// LoadTemplates parses all specified files located in path. Each template is wrapped
// in a unique clone of layout. All templates are expecting {{authboss}} handlebars
// for parsing. It will check the override directory specified in the config, replacing any
// templates as necessary.
func LoadTemplates(layout *template.Template, path string, files ...string) (Templates, error) {
m := make(Templates)
for _, file := range files {
b, err := ioutil.ReadFile(filepath.Join(path, file))
if exists := !os.IsNotExist(err); err != nil && exists {
return nil, err
} else if !exists {
b, err = Asset(file)
if err != nil {
return nil, err
}
}
clone, err := layout.Clone()
if err != nil {
return nil, err
}
_, err = clone.New("authboss").Funcs(funcMap).Parse(string(b))
if err != nil {
return nil, err
}
m[file] = clone
}
return m, nil
}
// Render renders a view with xsrf and flash attributes.
func (t Templates) Render(ctx *authboss.Context, w http.ResponseWriter, r *http.Request, name string, data authboss.HTMLData) error {
tpl, ok := t[name]
if !ok {
return authboss.RenderErr{tpl.Name(), data, ErrTemplateNotFound}
}
data.MergeKV("xsrfName", template.HTML(authboss.Cfg.XSRFName), "xsrfToken", template.HTML(authboss.Cfg.XSRFMaker(w, r)))
if authboss.Cfg.LayoutDataMaker != nil {
data.Merge(authboss.Cfg.LayoutDataMaker(w, r))
}
if flash, ok := ctx.SessionStorer.Get(authboss.FlashSuccessKey); ok {
ctx.SessionStorer.Del(authboss.FlashSuccessKey)
data.MergeKV(authboss.FlashSuccessKey, flash)
}
if flash, ok := ctx.SessionStorer.Get(authboss.FlashErrorKey); ok {
ctx.SessionStorer.Del(authboss.FlashErrorKey)
data.MergeKV(authboss.FlashErrorKey, flash)
}
buffer := &bytes.Buffer{}
err := tpl.ExecuteTemplate(buffer, tpl.Name(), data)
if err != nil {
return authboss.RenderErr{tpl.Name(), data, err}
}
_, err = io.Copy(w, buffer)
if err != nil {
return authboss.RenderErr{tpl.Name(), data, err}
}
return nil
}
// RenderEmail renders the html and plaintext views for an email and sends it
func RenderEmail(email authboss.Email, htmlTpls Templates, nameHTML string, textTpls Templates, namePlain string, data interface{}) error {
tplHTML, ok := htmlTpls[nameHTML]
if !ok {
return authboss.RenderErr{tplHTML.Name(), data, ErrTemplateNotFound}
}
tplPlain, ok := textTpls[namePlain]
if !ok {
return authboss.RenderErr{tplPlain.Name(), data, ErrTemplateNotFound}
}
htmlBuffer := &bytes.Buffer{}
if err := tplHTML.ExecuteTemplate(htmlBuffer, tplHTML.Name(), data); err != nil {
return authboss.RenderErr{tplHTML.Name(), data, err}
}
email.HTMLBody = htmlBuffer.String()
plainBuffer := &bytes.Buffer{}
if err := tplPlain.ExecuteTemplate(plainBuffer, tplPlain.Name(), data); err != nil {
return authboss.RenderErr{tplPlain.Name(), data, err}
}
email.TextBody = plainBuffer.String()
if err := authboss.Cfg.Mailer.Send(email); err != nil {
return err
}
return nil
}
// Redirect sets any flash messages given and redirects the user.
func Redirect(ctx *authboss.Context, w http.ResponseWriter, r *http.Request, path, flashSuccess, flashError string) {
if len(flashSuccess) > 0 {
ctx.SessionStorer.Put(authboss.FlashSuccessKey, flashSuccess)
}
if len(flashError) > 0 {
ctx.SessionStorer.Put(authboss.FlashErrorKey, flashError)
}
http.Redirect(w, r, path, http.StatusFound)
}