mirror of
https://github.com/volatiletech/authboss.git
synced 2025-01-26 05:27:33 +02:00
150 lines
4.1 KiB
Go
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)
|
|
}
|