Initial commit

This commit is contained in:
paul 2018-04-22 16:55:50 +02:00
commit 2422e3108f
37 changed files with 12691 additions and 0 deletions

79
views/funcs.go Normal file
View file

@ -0,0 +1,79 @@
package views
import (
"fmt"
"html/template"
"strings"
"time"
)
var funcs = template.FuncMap{
"asset": assetURLFn,
"url": relURLFn,
"lower": lower,
"upper": upper,
"date": dateFn,
"humanDate": readableDateFn,
"t": translateFn,
}
func lower(input string) string {
return strings.ToLower(input)
}
func upper(input string) string {
return strings.ToUpper(input)
}
func assetURLFn(input string) string {
url := "/static/" //os.Getenv("ASSET_URL")
return fmt.Sprintf("%s%s", url, input)
}
func relURLFn(input string) string {
url := "/" //os.Getenv("ASSET_URL")
return fmt.Sprintf("%s%s", url, input)
}
func dateFn(format string, input interface{}) string {
var t time.Time
switch date := input.(type) {
default:
t = time.Now()
case time.Time:
t = date
}
return t.Format(format)
}
func translateFn(language string, text string) string {
return text
}
func readableDateFn(t time.Time) string {
if time.Now().Before(t) {
return "in the future"
}
diff := time.Now().Sub(t)
day := 24 * time.Hour
month := 30 * day
year := 12 * month
switch {
case diff < time.Second:
return "just now"
case diff < 5*time.Minute:
return "a few minutes ago"
case diff < time.Hour:
return fmt.Sprintf("%d minutes ago", diff/time.Minute)
case diff < day:
return fmt.Sprintf("%d hours ago", diff/time.Hour)
case diff < month:
return fmt.Sprintf("%d days ago", diff/day)
case diff < year:
return fmt.Sprintf("%d months ago", diff/month)
default:
return fmt.Sprintf("%d years ago", diff/year)
}
}

92
views/templates.go Normal file
View file

@ -0,0 +1,92 @@
package views
import (
"bytes"
"fmt"
"html/template"
"log"
"net/http"
"path/filepath"
"git.klink.asia/paul/certman/assets"
)
// map of all parsed templates, by template name
var templates map[string]*template.Template
// LoadTemplates initializes the templates map, parsing all defined templates.
func LoadTemplates() {
templates = map[string]*template.Template{
"401": newTemplate("layouts/application.gohtml", "errors/401.gohtml"),
"403": newTemplate("layouts/application.gohtml", "errors/403.gohtml"),
"404": newTemplate("layouts/application.gohtml", "errors/404.gohtml"),
"500": newTemplate("layouts/application.gohtml", "errors/500.gohtml"),
"login": newTemplate("layouts/auth.gohtml", "views/login.gohtml"),
"client_list": newTemplate("layouts/application.gohtml", "views/client_list.gohtml"),
"config.ovpn": newTemplate("files/config.ovpn"),
}
return
}
// newTemplate returns a new template from the assets
func newTemplate(filenames ...string) *template.Template {
f := []string{}
prefix := "/templates"
for _, filename := range filenames {
f = append(f, filepath.Join(prefix, filename))
}
baseTemplate := template.New("base").Funcs(funcs)
tmpl, err := parseAssets(baseTemplate, assets.Assets, f...)
if err != nil {
log.Fatalf("could not parse template: %s", err.Error())
}
return tmpl
}
// parseAssets is a helper function to generate a template from multiple
// assets. If the argument template is nil, it is created from the first
// parameter that is passed (first file).
func parseAssets(t *template.Template, fs http.FileSystem, assets ...string) (*template.Template, error) {
if len(assets) == 0 {
// Not really a problem, but be consistent.
return nil, fmt.Errorf("no templates supplied in call to parseAssets")
}
for _, filename := range assets {
f, err := fs.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
buf := new(bytes.Buffer)
buf.ReadFrom(f)
s := buf.String()
name := filepath.Base(filename)
// First template becomes return value if not already defined,
// and we use that one for subsequent New calls to associate
// all the templates together.
var tmpl *template.Template
if t == nil {
t = template.New(name)
}
if name == t.Name() {
tmpl = t
} else {
tmpl = t.New(name)
}
_, err = tmpl.Parse(s)
if err != nil {
return nil, err
}
}
return t, nil
}

110
views/views.go Normal file
View file

@ -0,0 +1,110 @@
package views
import (
"errors"
"fmt"
"html/template"
"log"
"net/http"
"git.klink.asia/paul/certman/services"
"github.com/gorilla/csrf"
)
type View struct {
Vars map[string]interface{}
Request *http.Request
SessionStore *services.Sessions
}
func New(req *http.Request) *View {
return &View{
Request: req,
Vars: map[string]interface{}{
"CSRF_TOKEN": csrf.Token(req),
"csrfField": csrf.TemplateField(req),
"Meta": map[string]interface{}{
"Path": req.URL.Path,
"Env": "develop",
},
"flashes": []services.Flash{},
"username": "",
},
}
}
func NewWithSession(req *http.Request, sessionStore *services.Sessions) *View {
return &View{
Request: req,
SessionStore: sessionStore,
Vars: map[string]interface{}{
"CSRF_TOKEN": csrf.Token(req),
"csrfField": csrf.TemplateField(req),
"Meta": map[string]interface{}{
"Path": req.URL.Path,
"Env": "develop",
},
"flashes": []services.Flash{},
"username": sessionStore.GetUsername(req),
},
}
}
func (view View) Render(w http.ResponseWriter, name string) {
var err error
t, err := GetTemplate(name)
if err != nil {
log.Printf("the template '%s' does not exist.", name)
view.RenderError(w, 404)
return
}
if view.SessionStore != nil {
// add flashes to template
view.Vars["flashes"] = view.SessionStore.Flashes(w, view.Request)
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK)
t.Execute(w, view.Vars)
}
func (view View) RenderError(w http.ResponseWriter, status int) {
var name string
switch status {
case http.StatusUnauthorized:
name = "401"
case http.StatusForbidden:
name = "403"
case http.StatusNotFound:
name = "404"
default:
name = "500"
}
t, err := GetTemplate(name)
if err != nil {
log.Printf("the error template '%s' does not exist.", name)
fmt.Fprintf(w, "Error page for status '%d' could not be rendered.", status)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(status)
t.Execute(w, view.Vars)
}
// GetTemplate returns a parsed template. The template ,ap needs to be
// Initialized by calling `LoadTemplates()` first.
func GetTemplate(name string) (*template.Template, error) {
if tmpl, ok := templates[name]; ok {
return tmpl, nil
}
return nil, errors.New("Template not found")
}