Load custom templates from filesystem

This commit is contained in:
Melon 2023-10-09 20:31:41 +01:00
parent a8afddb02b
commit 34f0950851
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
7 changed files with 89 additions and 28 deletions

View File

@ -9,6 +9,8 @@ import (
"flag" "flag"
"fmt" "fmt"
"github.com/1f349/tulip/database" "github.com/1f349/tulip/database"
"github.com/1f349/tulip/mail/templates"
"github.com/1f349/tulip/pages"
"github.com/1f349/tulip/server" "github.com/1f349/tulip/server"
"github.com/1f349/violet/utils" "github.com/1f349/violet/utils"
"github.com/MrMelon54/exit-reload" "github.com/MrMelon54/exit-reload"
@ -82,6 +84,13 @@ func normalLoad(startUp startUpConfig, wd string) {
log.Fatal("[Tulip] Failed check:", err) log.Fatal("[Tulip] Failed check:", err)
} }
if err = pages.LoadPages(wd); err != nil {
log.Fatal("[Tulip] Failed to load page templates:", err)
}
if err := templates.LoadMailTemplates(wd); err != nil {
log.Fatal("[Tulip] Failed to load mail templates:", err)
}
srv := server.NewHttpServer(startUp.Listen, startUp.BaseUrl, startUp.OtpIssuer, startUp.ServiceName, startUp.Mail, db, key) srv := server.NewHttpServer(startUp.Listen, startUp.BaseUrl, startUp.OtpIssuer, startUp.ServiceName, startUp.Mail, db, key)
log.Printf("[Tulip] Starting HTTP server on '%s'\n", srv.Addr) log.Printf("[Tulip] Starting HTTP server on '%s'\n", srv.Addr)
go utils.RunBackgroundHttp("HTTP", srv) go utils.RunBackgroundHttp("HTTP", srv)

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.21.1
require ( require (
github.com/1f349/cache v0.0.2 github.com/1f349/cache v0.0.2
github.com/1f349/overlapfs v0.0.1
github.com/1f349/twofactor v1.0.4 github.com/1f349/twofactor v1.0.4
github.com/1f349/violet v0.0.9 github.com/1f349/violet v0.0.9
github.com/MrMelon54/exit-reload v0.0.1 github.com/MrMelon54/exit-reload v0.0.1

2
go.sum
View File

@ -1,6 +1,8 @@
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/1f349/cache v0.0.2 h1:27QD6zPd9xYyvh9V1qqWq+EAt5+N+qvyGWKfnjMrhP8= github.com/1f349/cache v0.0.2 h1:27QD6zPd9xYyvh9V1qqWq+EAt5+N+qvyGWKfnjMrhP8=
github.com/1f349/cache v0.0.2/go.mod h1:LibAMy13dF0KO1fQA9aEjZPBCB6Y4b5kKYEQJUqc2rQ= github.com/1f349/cache v0.0.2/go.mod h1:LibAMy13dF0KO1fQA9aEjZPBCB6Y4b5kKYEQJUqc2rQ=
github.com/1f349/overlapfs v0.0.1 h1:LAxBolrXFAgU0yqZtXg/C/aaPq3eoQSPpBc49BHuTp0=
github.com/1f349/overlapfs v0.0.1/go.mod h1:I6aItQycr7nrzplmfNXp/QF9tTmKRSgY3fXmu/7Ky2o=
github.com/1f349/twofactor v1.0.4 h1:kN4EEGFlKRa7fGrxS+FpgwJI+tllES6YzXqCqurk4Uk= github.com/1f349/twofactor v1.0.4 h1:kN4EEGFlKRa7fGrxS+FpgwJI+tllES6YzXqCqurk4Uk=
github.com/1f349/twofactor v1.0.4/go.mod h1:gnG80vElwqLWNMnLT57yu4o4L1GdXGPP6pcIPlapXZs= github.com/1f349/twofactor v1.0.4/go.mod h1:gnG80vElwqLWNMnLT57yu4o4L1GdXGPP6pcIPlapXZs=
github.com/1f349/violet v0.0.9 h1:eQfc5fDMKJXVFUjS2UiAGTkOVVBamppD5dguhmU4GeU= github.com/1f349/violet v0.0.9 h1:eQfc5fDMKJXVFUjS2UiAGTkOVVBamppD5dguhmU4GeU=

View File

@ -0,0 +1,12 @@
<!-- TODO: format this as HTML -->
Hello, {{.Name}}
Please open this link to verify your email address: {{.Data.VerifyUrl}}
This link is valid for 10 minutes.
If you did not create an account with {{.ServiceName}} then please ignore this email and the account will be deleted within a 48-hour period.
Regards,
{{.ServiceName}}

View File

@ -2,26 +2,54 @@ package templates
import ( import (
"embed" "embed"
"errors"
"github.com/1f349/overlapfs"
htmlTemplate "html/template"
"io" "io"
"io/fs"
"log" "log"
"text/template" "os"
"path/filepath"
"sync"
textTemplate "text/template"
) )
var ( var (
//go:embed * //go:embed *.go.html *.go.txt
embeddedTemplates embed.FS embeddedTemplates embed.FS
mailHtmlTemplates *htmlTemplate.Template
mailTemplate *template.Template mailTextTemplates *textTemplate.Template
loadOnce sync.Once
) )
func LoadMailTemplates() (err error) { func LoadMailTemplates(wd string) (err error) {
mailTemplate, err = template.New("mail").ParseFS(embeddedTemplates, "*.go.txt") loadOnce.Do(func() {
var o fs.FS = embeddedTemplates
if wd != "" {
mailDir := filepath.Join(wd, "mail-templates")
err = os.Mkdir(mailDir, os.ModePerm)
if err != nil && !errors.Is(err, os.ErrExist) {
return
}
wdFs := os.DirFS(mailDir)
o = overlapfs.OverlapFS{A: embeddedTemplates, B: wdFs}
}
mailHtmlTemplates, err = htmlTemplate.New("mail").ParseFS(o, "*.go.html")
if err != nil {
return
}
mailTextTemplates, err = textTemplate.New("mail").ParseFS(o, "*.go.txt")
})
return return
} }
func RenderMailTemplate(wr io.Writer, name string, data any) { func RenderMailTemplate(wrHtml, wrTxt io.Writer, name string, data any) {
err := mailTemplate.ExecuteTemplate(wr, name+".go.txt", data) err := mailHtmlTemplates.ExecuteTemplate(wrHtml, name+".go.html", data)
if err != nil { if err != nil {
log.Printf("Failed to render mail: %s: %s\n", name, err) log.Printf("Failed to render mail html: %s: %s\n", name, err)
}
err = mailTextTemplates.ExecuteTemplate(wrTxt, name+".go.txt", data)
if err != nil {
log.Printf("Failed to render mail text: %s: %s\n", name, err)
} }
} }

View File

@ -3,27 +3,45 @@ package pages
import ( import (
"embed" "embed"
_ "embed" _ "embed"
"errors"
"github.com/1f349/overlapfs"
"html/template" "html/template"
"io" "io"
"io/fs"
"log" "log"
"os"
"path/filepath"
"sync"
) )
var ( var (
//go:embed * //go:embed *.go.html
embeddedTemplates embed.FS wwwPages embed.FS
wwwTemplates *template.Template
pageTemplate *template.Template loadOnce sync.Once
) )
func LoadPageTemplates() (err error) { func LoadPages(wd string) (err error) {
pageTemplate, err = template.New("pages").Funcs(template.FuncMap{ loadOnce.Do(func() {
"emailHide": EmailHide, var o fs.FS = wwwPages
}).ParseFS(embeddedTemplates, "*.go.html") if wd != "" {
wwwDir := filepath.Join(wd, "www")
err = os.Mkdir(wwwDir, os.ModePerm)
if err != nil && !errors.Is(err, os.ErrExist) {
return return
}
wdFs := os.DirFS(wwwDir)
o = overlapfs.OverlapFS{A: wwwPages, B: wdFs}
}
wwwTemplates, err = template.New("pages").Funcs(template.FuncMap{
"emailHide": EmailHide,
}).ParseFS(o, "*.go.html")
})
return err
} }
func RenderPageTemplate(wr io.Writer, name string, data any) { func RenderPageTemplate(wr io.Writer, name string, data any) {
err := pageTemplate.ExecuteTemplate(wr, name+".go.html", data) err := wwwTemplates.ExecuteTemplate(wr, name+".go.html", data)
if err != nil { if err != nil {
log.Printf("Failed to render page: %s: %s\n", name, err) log.Printf("Failed to render page: %s: %s\n", name, err)
} }

View File

@ -9,9 +9,7 @@ import (
clientStore "github.com/1f349/tulip/client-store" clientStore "github.com/1f349/tulip/client-store"
"github.com/1f349/tulip/database" "github.com/1f349/tulip/database"
"github.com/1f349/tulip/mail" "github.com/1f349/tulip/mail"
"github.com/1f349/tulip/mail/templates"
"github.com/1f349/tulip/openid" "github.com/1f349/tulip/openid"
"github.com/1f349/tulip/pages"
scope2 "github.com/1f349/tulip/scope" scope2 "github.com/1f349/tulip/scope"
"github.com/go-oauth2/oauth2/v4/errors" "github.com/go-oauth2/oauth2/v4/errors"
"github.com/go-oauth2/oauth2/v4/generates" "github.com/go-oauth2/oauth2/v4/generates"
@ -82,13 +80,6 @@ func NewHttpServer(listen, domain, otpIssuer, serviceName string, mailer mail.Ma
log.Fatalln("Failed to generate OpenID configuration:", err) log.Fatalln("Failed to generate OpenID configuration:", err)
} }
if err := pages.LoadPageTemplates(); err != nil {
log.Fatalln("Failed to load page templates:", err)
}
if err := templates.LoadMailTemplates(); err != nil {
log.Fatalln("Failed to load mail templates:", err)
}
oauthManager := manage.NewDefaultManager() oauthManager := manage.NewDefaultManager()
oauthSrv := server.NewServer(server.NewConfig(), oauthManager) oauthSrv := server.NewServer(server.NewConfig(), oauthManager)
hs := &HttpServer{ hs := &HttpServer{