Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: courier templates fs support #2164

Merged
merged 6 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 25 additions & 20 deletions courier/template/load_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import (
"embed"
htemplate "html/template"
"io"
"os"
"path"
"io/fs"
"path/filepath"
"text/template"

Expand All @@ -24,16 +23,16 @@ type Template interface {
Execute(wr io.Writer, data interface{}) error
}

func loadBuiltInTemplate(osdir, name string, html bool) (Template, error) {
func loadBuiltInTemplate(filesytem fs.FS, name string, html bool) (Template, error) {
if t, found := cache.Get(name); found {
return t.(Template), nil
}

file, err := os.DirFS(osdir).Open(name)
file, err := filesytem.Open(name)
if err != nil {
// try to fallback to bundled templates
var fallbackErr error
file, fallbackErr = templates.Open(path.Join("courier/builtin/templates", name))
file, fallbackErr = templates.Open(filepath.Join("courier/builtin/templates", name))
if fallbackErr != nil {
// return original error from os.DirFS
return nil, errors.WithStack(err)
Expand Down Expand Up @@ -66,35 +65,37 @@ func loadBuiltInTemplate(osdir, name string, html bool) (Template, error) {
return tpl, nil
}

func loadTemplate(osdir, name, pattern string, html bool) (Template, error) {
func loadTemplate(filesystem fs.FS, name, pattern string, html bool) (Template, error) {
if t, found := cache.Get(name); found {
return t.(Template), nil
}

// make sure osdir and template name exists, otherwise fallback to built in templates
f, _ := filepath.Glob(path.Join(osdir, name))
if f == nil {
return loadBuiltInTemplate(osdir, name, html)
matches, _ := fs.Glob(filesystem, name)
// make sure the file exists in the fs, otherwise fallback to built in templates
if matches == nil {
return loadBuiltInTemplate(filesystem, name, html)
}

// if pattern is defined, use it for glob
var glob string = name
glob := name
if pattern != "" {
m, _ := filepath.Glob(path.Join(osdir, pattern))
if m != nil {
// pattern matching is used when we have more than one gotmpl for different use cases, such as i18n support
// e.g. some_template/template_name* will match some_template/template_name.body.en_US.gotmpl
matches, _ = fs.Glob(filesystem, pattern)
// set the glob string to match patterns
if matches != nil {
glob = pattern
}
}

var tpl Template
if html {
t, err := htemplate.New(filepath.Base(name)).Funcs(sprig.HtmlFuncMap()).ParseGlob(path.Join(osdir, glob))
t, err := htemplate.New(filepath.Base(name)).Funcs(sprig.HtmlFuncMap()).ParseFS(filesystem, glob)
if err != nil {
return nil, errors.WithStack(err)
}
tpl = t
} else {
t, err := template.New(filepath.Base(name)).Funcs(sprig.TxtFuncMap()).ParseGlob(path.Join(osdir, glob))
t, err := template.New(filepath.Base(name)).Funcs(sprig.TxtFuncMap()).ParseFS(filesystem, glob)
if err != nil {
return nil, errors.WithStack(err)
}
Expand All @@ -105,23 +106,27 @@ func loadTemplate(osdir, name, pattern string, html bool) (Template, error) {
return tpl, nil
}

func LoadTextTemplate(osdir, name, pattern string, model interface{}) (string, error) {
t, err := loadTemplate(osdir, name, pattern, false)
func LoadTextTemplate(filesystem fs.FS, name, pattern string, model interface{}) (string, error) {
t, err := loadTemplate(filesystem, name, pattern, false)

if err != nil {
return "", err
}

var b bytes.Buffer
if err := t.Execute(&b, model); err != nil {
return "", err
}
return b.String(), nil
}

func LoadHTMLTemplate(osdir, name, pattern string, model interface{}) (string, error) {
t, err := loadTemplate(osdir, name, pattern, true)
func LoadHTMLTemplate(filesystem fs.FS, name, pattern string, model interface{}) (string, error) {
t, err := loadTemplate(filesystem, name, pattern, true)

if err != nil {
return "", err
}

var b bytes.Buffer
if err := t.Execute(&b, model); err != nil {
return "", err
Expand Down
4 changes: 2 additions & 2 deletions courier/template/load_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import (

func TestLoadTextTemplate(t *testing.T) {
var executeTextTemplate = func(t *testing.T, dir, name, pattern string, model map[string]interface{}) string {
tp, err := LoadTextTemplate(dir, name, pattern, model)
tp, err := LoadTextTemplate(os.DirFS(dir), name, pattern, model)
require.NoError(t, err)
return tp
}

var executeHTMLTemplate = func(t *testing.T, dir, name, pattern string, model map[string]interface{}) string {
tp, err := LoadHTMLTemplate(dir, name, pattern, model)
tp, err := LoadHTMLTemplate(os.DirFS(dir), name, pattern, model)
require.NoError(t, err)
return tp
}
Expand Down
7 changes: 4 additions & 3 deletions courier/template/recovery_invalid.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template

import (
"encoding/json"
"os"
)

type (
Expand All @@ -23,15 +24,15 @@ func (t *RecoveryInvalid) EmailRecipient() (string, error) {
}

func (t *RecoveryInvalid) EmailSubject() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "recovery/invalid/email.subject.gotmpl", "recovery/invalid/email.subject*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "recovery/invalid/email.subject.gotmpl", "recovery/invalid/email.subject*", t.m)
}

func (t *RecoveryInvalid) EmailBody() (string, error) {
return LoadHTMLTemplate(t.c.CourierTemplatesRoot(), "recovery/invalid/email.body.gotmpl", "recovery/invalid/email.body*", t.m)
return LoadHTMLTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "recovery/invalid/email.body.gotmpl", "recovery/invalid/email.body*", t.m)
}

func (t *RecoveryInvalid) EmailBodyPlaintext() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "recovery/invalid/email.body.plaintext.gotmpl", "recovery/invalid/email.body.plaintext*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "recovery/invalid/email.body.plaintext.gotmpl", "recovery/invalid/email.body.plaintext*", t.m)
}

func (t *RecoveryInvalid) MarshalJSON() ([]byte, error) {
Expand Down
7 changes: 4 additions & 3 deletions courier/template/recovery_valid.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template

import (
"encoding/json"
"os"
)

type (
Expand All @@ -25,15 +26,15 @@ func (t *RecoveryValid) EmailRecipient() (string, error) {
}

func (t *RecoveryValid) EmailSubject() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "recovery/valid/email.subject.gotmpl", "recovery/valid/email.subject*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "recovery/valid/email.subject.gotmpl", "recovery/valid/email.subject*", t.m)
}

func (t *RecoveryValid) EmailBody() (string, error) {
return LoadHTMLTemplate(t.c.CourierTemplatesRoot(), "recovery/valid/email.body.gotmpl", "recovery/valid/email.body*", t.m)
return LoadHTMLTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "recovery/valid/email.body.gotmpl", "recovery/valid/email.body*", t.m)
}

func (t *RecoveryValid) EmailBodyPlaintext() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "recovery/valid/email.body.plaintext.gotmpl", "recovery/valid/email.body.plaintext*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "recovery/valid/email.body.plaintext.gotmpl", "recovery/valid/email.body.plaintext*", t.m)
}

func (t *RecoveryValid) MarshalJSON() ([]byte, error) {
Expand Down
7 changes: 4 additions & 3 deletions courier/template/stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template

import (
"encoding/json"
"os"
)

type TestStub struct {
Expand All @@ -24,15 +25,15 @@ func (t *TestStub) EmailRecipient() (string, error) {
}

func (t *TestStub) EmailSubject() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "test_stub/email.subject.gotmpl", "test_stub/email.subject*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "test_stub/email.subject.gotmpl", "test_stub/email.subject*", t.m)
}

func (t *TestStub) EmailBody() (string, error) {
return LoadHTMLTemplate(t.c.CourierTemplatesRoot(), "test_stub/email.body.gotmpl", "test_stub/email.body*", t.m)
return LoadHTMLTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "test_stub/email.body.gotmpl", "test_stub/email.body*", t.m)
}

func (t *TestStub) EmailBodyPlaintext() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "test_stub/email.body.plaintext.gotmpl", "test_stub/email.body.plaintext*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "test_stub/email.body.plaintext.gotmpl", "test_stub/email.body.plaintext*", t.m)
}

func (t *TestStub) MarshalJSON() ([]byte, error) {
Expand Down
7 changes: 4 additions & 3 deletions courier/template/verification_invalid.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template

import (
"encoding/json"
"os"
)

type (
Expand All @@ -23,15 +24,15 @@ func (t *VerificationInvalid) EmailRecipient() (string, error) {
}

func (t *VerificationInvalid) EmailSubject() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "verification/invalid/email.subject.gotmpl", "verification/invalid/email.subject*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "verification/invalid/email.subject.gotmpl", "verification/invalid/email.subject*", t.m)
}

func (t *VerificationInvalid) EmailBody() (string, error) {
return LoadHTMLTemplate(t.c.CourierTemplatesRoot(), "verification/invalid/email.body.gotmpl", "verification/invalid/email.body*", t.m)
return LoadHTMLTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "verification/invalid/email.body.gotmpl", "verification/invalid/email.body*", t.m)
}

func (t *VerificationInvalid) EmailBodyPlaintext() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "verification/invalid/email.body.plaintext.gotmpl", "verification/invalid/email.body.plaintext*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "verification/invalid/email.body.plaintext.gotmpl", "verification/invalid/email.body.plaintext*", t.m)
}

func (t *VerificationInvalid) MarshalJSON() ([]byte, error) {
Expand Down
7 changes: 4 additions & 3 deletions courier/template/verification_valid.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template

import (
"encoding/json"
"os"
)

type (
Expand All @@ -25,15 +26,15 @@ func (t *VerificationValid) EmailRecipient() (string, error) {
}

func (t *VerificationValid) EmailSubject() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "verification/valid/email.subject.gotmpl", "verification/valid/email.subject*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "verification/valid/email.subject.gotmpl", "verification/valid/email.subject*", t.m)
}

func (t *VerificationValid) EmailBody() (string, error) {
return LoadHTMLTemplate(t.c.CourierTemplatesRoot(), "verification/valid/email.body.gotmpl", "verification/valid/email.body*", t.m)
return LoadHTMLTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "verification/valid/email.body.gotmpl", "verification/valid/email.body*", t.m)
}

func (t *VerificationValid) EmailBodyPlaintext() (string, error) {
return LoadTextTemplate(t.c.CourierTemplatesRoot(), "verification/valid/email.body.plaintext.gotmpl", "verification/valid/email.body.plaintext*", t.m)
return LoadTextTemplate(os.DirFS(t.c.CourierTemplatesRoot()), "verification/valid/email.body.plaintext.gotmpl", "verification/valid/email.body.plaintext*", t.m)
}

func (t *VerificationValid) MarshalJSON() ([]byte, error) {
Expand Down