mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Fix mail send, complete jade support, fix iriscontrol index , replace iriscontrol session to basicauth
This commit is contained in:
parent
91b45ebfdb
commit
48aaca5bc0
10
HISTORY.md
10
HISTORY.md
|
@ -1,5 +1,15 @@
|
||||||
# History
|
# History
|
||||||
|
|
||||||
|
## 3.0.0-beta.2 -> 3.0.0-beta.3
|
||||||
|
|
||||||
|
- Complete the Jade Template Engine support, {{ render }} and {{ url }} done also.
|
||||||
|
|
||||||
|
- Fix Mail().Send
|
||||||
|
|
||||||
|
- Iriscontrol plugin: Replace login using session to basic authentication
|
||||||
|
|
||||||
|
And other not-too-important fixes
|
||||||
|
|
||||||
## 3.0.0-beta -> 3.0.0-beta.2
|
## 3.0.0-beta -> 3.0.0-beta.2
|
||||||
|
|
||||||
- NEW: Wildcard(dynamic) subdomains, read [here](https://kataras.gitbooks.io/iris/content/subdomains.html)
|
- NEW: Wildcard(dynamic) subdomains, read [here](https://kataras.gitbooks.io/iris/content/subdomains.html)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
[Travis]: http://travis-ci.org/kataras/iris
|
[Travis]: http://travis-ci.org/kataras/iris
|
||||||
[License Widget]: https://img.shields.io/badge/license-Apache%20License%202.0-E91E63.svg?style=flat-square
|
[License Widget]: https://img.shields.io/badge/license-Apache%20License%202.0-E91E63.svg?style=flat-square
|
||||||
[License]: https://github.com/kataras/iris/blob/master/LICENSE
|
[License]: https://github.com/kataras/iris/blob/master/LICENSE
|
||||||
[Release Widget]: https://img.shields.io/badge/release-v3.0.0--beta.2-blue.svg?style=flat-square
|
[Release Widget]: https://img.shields.io/badge/release-v3.0.0--beta.3-blue.svg?style=flat-square
|
||||||
[Release]: https://github.com/kataras/iris/releases
|
[Release]: https://github.com/kataras/iris/releases
|
||||||
[Gitter Widget]: https://img.shields.io/badge/chat-on%20gitter-00BCD4.svg?style=flat-square
|
[Gitter Widget]: https://img.shields.io/badge/chat-on%20gitter-00BCD4.svg?style=flat-square
|
||||||
[Gitter]: https://gitter.im/kataras/iris
|
[Gitter]: https://gitter.im/kataras/iris
|
||||||
|
@ -116,7 +116,7 @@ Iris suggests you to use [this](https://github.com/gavv/httpexpect) new suite t
|
||||||
Versioning
|
Versioning
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Current: **v3.0.0-beta.2**
|
Current: **v3.0.0-beta.3**
|
||||||
> Iris is an active project
|
> Iris is an active project
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,13 +104,13 @@ type (
|
||||||
|
|
||||||
// HTMLTemplate contains specific configs for HTMLTemplate standard html/template
|
// HTMLTemplate contains specific configs for HTMLTemplate standard html/template
|
||||||
HTMLTemplate HTMLTemplate
|
HTMLTemplate HTMLTemplate
|
||||||
// Pongo contains specific configs for for pongo2
|
// Jade contains specific configs for Jade
|
||||||
|
Jade Jade
|
||||||
|
// Pongo contains specific configs for pongo2
|
||||||
Pongo Pongo
|
Pongo Pongo
|
||||||
// Markdown contains specific configs for for markdown
|
// Markdown contains specific configs for markdown
|
||||||
// this doesn't supports Layout & binding context
|
// this doesn't supports Layout & binding context
|
||||||
Markdown Markdown
|
Markdown Markdown
|
||||||
// Jade contains specific configs for jade
|
|
||||||
Jade Jade
|
|
||||||
// Amber contains specific configs for amber
|
// Amber contains specific configs for amber
|
||||||
Amber Amber
|
Amber Amber
|
||||||
}
|
}
|
||||||
|
@ -132,6 +132,8 @@ type (
|
||||||
// these can override the Funcs inside no-layout templates also, use it when you know what you're doing
|
// these can override the Funcs inside no-layout templates also, use it when you know what you're doing
|
||||||
LayoutFuncs map[string]interface{}
|
LayoutFuncs map[string]interface{}
|
||||||
}
|
}
|
||||||
|
// Jade the configs for JadeEngine
|
||||||
|
Jade HTMLTemplate
|
||||||
// Pongo the configs for PongoEngine
|
// Pongo the configs for PongoEngine
|
||||||
Pongo struct {
|
Pongo struct {
|
||||||
// Filters for pongo2, map[name of the filter] the filter function . The filters are auto register
|
// Filters for pongo2, map[name of the filter] the filter function . The filters are auto register
|
||||||
|
@ -145,17 +147,6 @@ type (
|
||||||
Sanitize bool // if true then returns safe html, default is false
|
Sanitize bool // if true then returns safe html, default is false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jade the configs for JadeEngine
|
|
||||||
Jade struct {
|
|
||||||
// Funcs like html/template
|
|
||||||
Funcs map[string]interface{}
|
|
||||||
// LayoutFuncs like html/template
|
|
||||||
// the difference from Funcs is that these funcs
|
|
||||||
// can be used inside a layout and can override the predefined (yield,partial...) or add more custom funcs
|
|
||||||
// these can override the Funcs inside no-layout templates also, use it when you know what you're doing
|
|
||||||
LayoutFuncs map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Amber the configs for AmberEngine
|
// Amber the configs for AmberEngine
|
||||||
Amber struct {
|
Amber struct {
|
||||||
// Funcs for the html/template result, amber default funcs are not overrided so use it without worries
|
// Funcs for the html/template result, amber default funcs are not overrided so use it without worries
|
||||||
|
@ -213,10 +204,10 @@ func DefaultTemplate() Template {
|
||||||
Charset: "UTF-8",
|
Charset: "UTF-8",
|
||||||
Layout: "", // currently this is the only config which not working for pongo2 yet but I will find a way
|
Layout: "", // currently this is the only config which not working for pongo2 yet but I will find a way
|
||||||
HTMLTemplate: HTMLTemplate{Left: "{{", Right: "}}", Funcs: make(map[string]interface{}, 0), LayoutFuncs: make(map[string]interface{}, 0)},
|
HTMLTemplate: HTMLTemplate{Left: "{{", Right: "}}", Funcs: make(map[string]interface{}, 0), LayoutFuncs: make(map[string]interface{}, 0)},
|
||||||
|
Jade: Jade{Left: "{{", Right: "}}", Funcs: make(map[string]interface{}, 0), LayoutFuncs: make(map[string]interface{}, 0)},
|
||||||
Pongo: Pongo{Filters: make(map[string]pongo2.FilterFunction, 0), Globals: make(map[string]interface{}, 0)},
|
Pongo: Pongo{Filters: make(map[string]pongo2.FilterFunction, 0), Globals: make(map[string]interface{}, 0)},
|
||||||
Markdown: Markdown{Sanitize: false},
|
Markdown: Markdown{Sanitize: false},
|
||||||
Amber: Amber{Funcs: template.FuncMap{}},
|
Amber: Amber{Funcs: template.FuncMap{}},
|
||||||
Jade: Jade{Funcs: template.FuncMap{}, LayoutFuncs: template.FuncMap{}},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
87
iris.go
87
iris.go
|
@ -1,4 +1,4 @@
|
||||||
// Package iris v3.0.0-beta.2
|
// Package iris the fastest golang web framework, so far.
|
||||||
//
|
//
|
||||||
// Note: When 'Station', we mean the Iris type.
|
// Note: When 'Station', we mean the Iris type.
|
||||||
package iris
|
package iris
|
||||||
|
@ -11,7 +11,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/flosch/pongo2"
|
|
||||||
"github.com/kataras/iris/config"
|
"github.com/kataras/iris/config"
|
||||||
"github.com/kataras/iris/logger"
|
"github.com/kataras/iris/logger"
|
||||||
"github.com/kataras/iris/mail"
|
"github.com/kataras/iris/mail"
|
||||||
|
@ -30,7 +29,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of the iris
|
// Version of the iris
|
||||||
Version = "v3.0.0-beta.2"
|
Version = "v3.0.0-beta.3"
|
||||||
banner = ` _____ _
|
banner = ` _____ _
|
||||||
|_ _| (_)
|
|_ _| (_)
|
||||||
| | ____ _ ___
|
| | ____ _ ___
|
||||||
|
@ -113,85 +112,17 @@ func (s *Iris) newContextPool() sync.Pool {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///TODO HERE MOVE THEM SOMEWHERE ELSE OR MAKE IT MORE BUETY->
|
||||||
func (s *Iris) initTemplates() {
|
func (s *Iris) initTemplates() {
|
||||||
if s.templates == nil { // because if .Templates() called before server's listen, s.templates != nil when PreListen
|
if s.templates == nil { // because if .Templates() called before server's listen, s.templates != nil when PreListen
|
||||||
// init the templates
|
// init the templates
|
||||||
|
template.RegisterSharedFunc("url", func(routeName string, args ...interface{}) string {
|
||||||
// set the custom iris-direct-integration functions, layout and no-layout if HTMLEngine is used
|
if url, err := s.UriOf(routeName, args...); err == nil {
|
||||||
templateConfig := &s.config.Render.Template
|
return url
|
||||||
///TODO gia AMber episis
|
} else {
|
||||||
if templateConfig.Engine == config.HTMLEngine || templateConfig.Engine == config.AmberEngine {
|
return err.Error()
|
||||||
funcs := map[string]interface{}{
|
|
||||||
|
|
||||||
"url": func(routeName string, args ...interface{}) (string, error) {
|
|
||||||
r := s.RouteByName(routeName)
|
|
||||||
// check if not found
|
|
||||||
if r.GetMethod() == "" {
|
|
||||||
return "", ErrRenderRouteNotFound.Format(routeName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.ParseURI(args...), nil
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
// these should be already a non-nil map but if .New(cfg) it's not, is mergo's bug, temporary:
|
|
||||||
if templateConfig.Engine == config.HTMLEngine {
|
|
||||||
if templateConfig.HTMLTemplate.LayoutFuncs == nil {
|
|
||||||
templateConfig.HTMLTemplate.LayoutFuncs = make(map[string]interface{}, len(funcs))
|
|
||||||
}
|
|
||||||
|
|
||||||
if templateConfig.HTMLTemplate.Funcs == nil {
|
|
||||||
templateConfig.HTMLTemplate.Funcs = make(map[string]interface{}, len(funcs))
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range funcs {
|
|
||||||
// we don't want to override the user's LayoutFuncs, user should be able to override anything.
|
|
||||||
if templateConfig.HTMLTemplate.LayoutFuncs[k] == nil {
|
|
||||||
templateConfig.HTMLTemplate.LayoutFuncs[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
if templateConfig.HTMLTemplate.Funcs[k] == nil {
|
|
||||||
templateConfig.HTMLTemplate.Funcs[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if templateConfig.Engine == config.AmberEngine {
|
|
||||||
if templateConfig.Amber.Funcs == nil {
|
|
||||||
templateConfig.Amber.Funcs = make(map[string]interface{}, len(funcs))
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range funcs {
|
|
||||||
if templateConfig.Amber.Funcs[k] == nil {
|
|
||||||
templateConfig.Amber.Funcs[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
} else if templateConfig.Engine == config.PongoEngine {
|
|
||||||
if templateConfig.Pongo.Globals == nil {
|
|
||||||
templateConfig.Pongo.Globals = make(map[string]interface{}, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
urlFunc := func(routeName string, args ...interface{}) (out *pongo2.Value) {
|
|
||||||
|
|
||||||
r := s.RouteByName(routeName)
|
|
||||||
// check if not found
|
|
||||||
if r.GetMethod() == "" {
|
|
||||||
return pongo2.AsValue(ErrRenderRouteNotFound.Format(routeName).Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return pongo2.AsValue(r.ParseURI(args...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// register it to the global context, no as Filter.
|
|
||||||
templateConfig.Pongo.Globals["url"] = urlFunc
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
s.templates = template.New(s.config.Render.Template)
|
s.templates = template.New(s.config.Render.Template)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package mail
|
package mail
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/mail"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/config"
|
"github.com/kataras/iris/config"
|
||||||
"github.com/kataras/iris/utils"
|
"github.com/kataras/iris/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const tmpl = `From: {{.From}}<br /> To: {{.To}}<br /> Subject: {{.Subject}}<br /> MIME-version: 1.0<br /> Content-Type: text/html; charset="UTF-8"<br /> <br /> {{.Body}}`
|
|
||||||
|
|
||||||
var buf = utils.NewBufferPool(64)
|
var buf = utils.NewBufferPool(64)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -24,6 +23,7 @@ type (
|
||||||
|
|
||||||
mailer struct {
|
mailer struct {
|
||||||
config config.Mail
|
config config.Mail
|
||||||
|
fromAddr mail.Address
|
||||||
auth smtp.Auth
|
auth smtp.Auth
|
||||||
authenticated bool
|
authenticated bool
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,14 @@ type (
|
||||||
|
|
||||||
// New creates and returns a new Service
|
// New creates and returns a new Service
|
||||||
func New(cfg config.Mail) Service {
|
func New(cfg config.Mail) Service {
|
||||||
return &mailer{config: cfg}
|
m := &mailer{config: cfg}
|
||||||
|
|
||||||
|
// not necessary
|
||||||
|
if !cfg.UseCommand && cfg.Username != "" && strings.Contains(cfg.Username, "@") {
|
||||||
|
m.fromAddr = mail.Address{cfg.Username[0:strings.IndexByte(cfg.Username, '@')], cfg.Username}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send sends a mail to recipients
|
// Send sends a mail to recipients
|
||||||
|
@ -56,19 +63,31 @@ func (m *mailer) sendSMTP(to []string, subject, body string) error {
|
||||||
m.authenticated = true
|
m.authenticated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
mailArgs := map[string]string{"To": strings.Join(to, ","), "Subject": subject, "Body": body}
|
fullhost := fmt.Sprintf("%s:%d", m.config.Host, m.config.Port)
|
||||||
template := template.Must(template.New("mailTmpl").Parse(tmpl))
|
|
||||||
|
|
||||||
if err := template.Execute(buffer, mailArgs); err != nil {
|
/* START: This one helped me https://gist.github.com/andelf/5004821 */
|
||||||
return err
|
header := make(map[string]string)
|
||||||
|
header["From"] = m.fromAddr.String()
|
||||||
|
header["To"] = strings.Join(to, ",")
|
||||||
|
header["Subject"] = subject
|
||||||
|
header["MIME-Version"] = "1.0"
|
||||||
|
header["Content-Type"] = "text/html; charset=\"utf-8\""
|
||||||
|
header["Content-Transfer-Encoding"] = "base64"
|
||||||
|
|
||||||
|
message := ""
|
||||||
|
for k, v := range header {
|
||||||
|
message += fmt.Sprintf("%s: %s\r\n", k, v)
|
||||||
}
|
}
|
||||||
|
message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
|
||||||
|
|
||||||
|
/* END */
|
||||||
|
|
||||||
return smtp.SendMail(
|
return smtp.SendMail(
|
||||||
fmt.Sprintf("%s:%d", m.config.Host, m.config.Port),
|
fmt.Sprintf(fullhost),
|
||||||
m.auth,
|
m.auth,
|
||||||
m.config.Username,
|
m.config.Username,
|
||||||
to,
|
to,
|
||||||
buffer.Bytes(),
|
[]byte(message),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,15 @@ func (i *irisControlPlugin) startControlPanel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
i.server = iris.New()
|
i.server = iris.New()
|
||||||
|
i.server.Config().DisableBanner = true
|
||||||
i.server.Config().Render.Template.Directory = installationPath + "templates"
|
i.server.Config().Render.Template.Directory = installationPath + "templates"
|
||||||
//i.server.SetRenderConfig(i.server.Config.Render)
|
//i.server.SetRenderConfig(i.server.Config.Render)
|
||||||
i.setPluginsInfo()
|
i.setPluginsInfo()
|
||||||
i.setPanelRoutes()
|
i.setPanelRoutes()
|
||||||
|
|
||||||
go i.server.Listen(strconv.Itoa(i.options.Port))
|
go i.server.Listen(strconv.Itoa(i.options.Port))
|
||||||
i.pluginContainer.Printf("[%s] %s is running at port %d with %d authenticated users", time.Now().UTC().String(), Name, i.options.Port, len(i.auth.authenticatedUsers))
|
|
||||||
|
i.pluginContainer.Printf("[%s] %s is running at port %d", time.Now().UTC().String(), Name, i.options.Port)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,21 +69,10 @@ func (i *irisControlPlugin) installAssets() (err error) {
|
||||||
func (i *irisControlPlugin) setPanelRoutes() {
|
func (i *irisControlPlugin) setPanelRoutes() {
|
||||||
|
|
||||||
i.server.Static("/public", installationPath+"static", 1)
|
i.server.Static("/public", installationPath+"static", 1)
|
||||||
i.server.Get("/login", func(ctx *iris.Context) {
|
|
||||||
ctx.Render("login", nil)
|
|
||||||
})
|
|
||||||
|
|
||||||
i.server.Post("/login", func(ctx *iris.Context) {
|
i.server.Use(i.authFunc)
|
||||||
i.auth.login(ctx)
|
|
||||||
})
|
|
||||||
|
|
||||||
i.server.Use(i.auth)
|
|
||||||
i.server.Get("/", func(ctx *iris.Context) {
|
i.server.Get("/", func(ctx *iris.Context) {
|
||||||
ctx.Render("index", DashboardPage{ServerIsRunning: i.station.Server().IsListening(), Routes: i.routes.All(), Plugins: i.plugins})
|
ctx.Render("index.html", DashboardPage{ServerIsRunning: i.station.Server().IsListening(), Routes: i.routes.All(), Plugins: i.plugins})
|
||||||
})
|
|
||||||
|
|
||||||
i.server.Post("/logout", func(ctx *iris.Context) {
|
|
||||||
i.auth.logout(ctx)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
//the controls
|
//the controls
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/config"
|
"github.com/kataras/iris/config"
|
||||||
|
"github.com/kataras/iris/middleware/basicauth"
|
||||||
"github.com/kataras/iris/plugin/routesinfo"
|
"github.com/kataras/iris/plugin/routesinfo"
|
||||||
"github.com/kataras/iris/server"
|
"github.com/kataras/iris/server"
|
||||||
)
|
)
|
||||||
|
@ -29,7 +30,7 @@ type irisControlPlugin struct {
|
||||||
plugins []PluginInfo
|
plugins []PluginInfo
|
||||||
//
|
//
|
||||||
|
|
||||||
auth *userAuth
|
authFunc iris.HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns the plugin which is ready-to-use inside iris.Plugin method
|
// New returns the plugin which is ready-to-use inside iris.Plugin method
|
||||||
|
@ -39,12 +40,13 @@ func New(cfg ...config.IrisControl) iris.IPlugin {
|
||||||
if len(cfg) > 0 {
|
if len(cfg) > 0 {
|
||||||
c = cfg[0]
|
c = cfg[0]
|
||||||
}
|
}
|
||||||
auth := newUserAuth(c.Users)
|
if c.Users == nil || len(c.Users) == 0 {
|
||||||
if auth == nil {
|
|
||||||
panic(Name + " Error: you should pass authenticated users map to the options, refer to the docs!")
|
panic(Name + " Error: you should pass authenticated users map to the options, refer to the docs!")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &irisControlPlugin{options: c, auth: auth, routes: routesinfo.RoutesInfo()}
|
auth := basicauth.Default(c.Users)
|
||||||
|
|
||||||
|
return &irisControlPlugin{options: c, authFunc: auth, routes: routesinfo.RoutesInfo()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Web set the options for the plugin and return the plugin which is ready-to-use inside iris.Plugin method
|
// Web set the options for the plugin and return the plugin which is ready-to-use inside iris.Plugin method
|
||||||
|
@ -106,7 +108,6 @@ func (i *irisControlPlugin) Destroy() {
|
||||||
i.station = nil
|
i.station = nil
|
||||||
i.server.Close()
|
i.server.Close()
|
||||||
i.pluginContainer = nil
|
i.pluginContainer = nil
|
||||||
i.auth.Destroy()
|
i.authFunc = nil
|
||||||
i.auth = nil
|
|
||||||
i.pluginContainer.Printf("[%s] %s is turned off", time.Now().UTC().String(), Name)
|
i.pluginContainer.Printf("[%s] %s is turned off", time.Now().UTC().String(), Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
package iriscontrol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
|
||||||
"github.com/kataras/iris/sessions"
|
|
||||||
// _ empty because it auto-registers
|
|
||||||
_ "github.com/kataras/iris/sessions/providers/memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
var panelSessions *sessions.Manager
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
//using the default
|
|
||||||
panelSessions = sessions.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
type user struct {
|
|
||||||
username string
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
type userAuth struct {
|
|
||||||
authenticatedUsers []user
|
|
||||||
}
|
|
||||||
|
|
||||||
// newUserAuth returns a new userAuth object, parameter is the authenticated users as map
|
|
||||||
func newUserAuth(usersMap map[string]string) *userAuth {
|
|
||||||
if usersMap != nil {
|
|
||||||
obj := &userAuth{make([]user, 0)}
|
|
||||||
for key, val := range usersMap {
|
|
||||||
obj.authenticatedUsers = append(obj.authenticatedUsers, user{key, val})
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userAuth) login(ctx *iris.Context) {
|
|
||||||
session := panelSessions.Start(ctx)
|
|
||||||
|
|
||||||
username := ctx.PostFormValue("username")
|
|
||||||
password := ctx.PostFormValue("password")
|
|
||||||
|
|
||||||
for _, authenticatedUser := range u.authenticatedUsers {
|
|
||||||
if authenticatedUser.username == username && authenticatedUser.password == password {
|
|
||||||
session.Set("username", username)
|
|
||||||
session.Set("password", password)
|
|
||||||
ctx.Write("success")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.Write("fail")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userAuth) logout(ctx *iris.Context) {
|
|
||||||
session := panelSessions.Start(ctx)
|
|
||||||
session.Set("user", nil)
|
|
||||||
|
|
||||||
ctx.Redirect("/login")
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if session stored, then check if this user is the correct, each time, then continue, else not
|
|
||||||
func (u *userAuth) Serve(ctx *iris.Context) {
|
|
||||||
if ctx.PathString() == "/login" || strings.HasPrefix(ctx.PathString(), "/public") {
|
|
||||||
ctx.Next()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
session := panelSessions.Start(ctx)
|
|
||||||
|
|
||||||
if sessionVal := session.Get("username"); sessionVal != nil {
|
|
||||||
username := sessionVal.(string)
|
|
||||||
password := session.GetString("password")
|
|
||||||
if username != "" && password != "" {
|
|
||||||
|
|
||||||
for _, authenticatedUser := range u.authenticatedUsers {
|
|
||||||
if authenticatedUser.username == username && authenticatedUser.password == password {
|
|
||||||
ctx.Next()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
//if not logged in the redirect to the /login
|
|
||||||
ctx.Redirect("/login")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy this is called on PreClose by the iriscontrol.go
|
|
||||||
func (u *userAuth) Destroy() {
|
|
||||||
|
|
||||||
}
|
|
|
@ -10,20 +10,15 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Joker/jade"
|
||||||
"github.com/kataras/iris/config"
|
"github.com/kataras/iris/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Engine the html/template engine
|
// Engine the html/template engine & Jade
|
||||||
Engine struct {
|
Engine struct {
|
||||||
Config *config.Template
|
Config *config.Template
|
||||||
Templates *template.Template
|
Templates *template.Template
|
||||||
// Middleware
|
|
||||||
// Note:
|
|
||||||
// I see that many template engines returns html/template as result
|
|
||||||
// so I decided that the HTMLTemplate should accept a middleware for the final string content will be parsed to the main *html/template.Template
|
|
||||||
// for example user of this property is Jade, currently
|
|
||||||
Middleware func(string, string) (string, error)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,7 +31,7 @@ var emptyFuncs = template.FuncMap{
|
||||||
},
|
},
|
||||||
"current": func() (string, error) {
|
"current": func() (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}, "render": func(string) (string, error) {
|
}, "render": func() (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -73,7 +68,6 @@ func (s *Engine) buildFromDir() error {
|
||||||
dir := s.Config.Directory
|
dir := s.Config.Directory
|
||||||
s.Templates = template.New(dir)
|
s.Templates = template.New(dir)
|
||||||
s.Templates.Delims(s.Config.HTMLTemplate.Left, s.Config.HTMLTemplate.Right)
|
s.Templates.Delims(s.Config.HTMLTemplate.Left, s.Config.HTMLTemplate.Right)
|
||||||
hasMiddleware := s.Middleware != nil
|
|
||||||
// Walk the supplied directory and compile any files that match our extension list.
|
// Walk the supplied directory and compile any files that match our extension list.
|
||||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
if info == nil || info.IsDir() {
|
if info == nil || info.IsDir() {
|
||||||
|
@ -107,8 +101,8 @@ func (s *Engine) buildFromDir() error {
|
||||||
name := filepath.ToSlash(rel)
|
name := filepath.ToSlash(rel)
|
||||||
tmpl := s.Templates.New(name)
|
tmpl := s.Templates.New(name)
|
||||||
|
|
||||||
if hasMiddleware {
|
if s.Config.Engine == config.JadeEngine {
|
||||||
contents, err = s.Middleware(name, contents)
|
contents, err = jade.Parse(name, contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -117,11 +111,11 @@ func (s *Engine) buildFromDir() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add our funcmaps.
|
// Add our funcmaps.
|
||||||
//if s.Config.HTMLTemplate.Funcs != nil {
|
if s.Config.HTMLTemplate.Funcs != nil {
|
||||||
// tmpl.Funcs(s.Config.HTMLTemplate.Funcs)
|
tmpl.Funcs(s.Config.HTMLTemplate.Funcs)
|
||||||
//}
|
}
|
||||||
|
|
||||||
tmpl.Funcs(s.Config.HTMLTemplate.Funcs).Parse(contents)
|
tmpl.Funcs(emptyFuncs).Parse(contents)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,16 +153,20 @@ func (s *Engine) buildFromAsset() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
contents := string(buf)
|
||||||
name := filepath.ToSlash(rel)
|
name := filepath.ToSlash(rel)
|
||||||
tmpl := s.Templates.New(name)
|
tmpl := s.Templates.New(name)
|
||||||
|
|
||||||
// Add our funcmaps.
|
if s.Config.Engine == config.JadeEngine {
|
||||||
//for _, funcs := range s.Config.HTMLTemplate.Funcs {
|
contents, err = jade.Parse(name, contents)
|
||||||
/*if s.Config.HTMLTemplate.Funcs != nil {
|
}
|
||||||
tmpl.Funcs(s.Config.HTMLTemplate.Funcs)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
tmpl.Funcs(emptyFuncs).Funcs(s.Config.HTMLTemplate.Funcs).Parse(string(buf))
|
// Add our funcmaps.
|
||||||
|
if s.Config.HTMLTemplate.Funcs != nil {
|
||||||
|
tmpl.Funcs(s.Config.HTMLTemplate.Funcs)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl.Funcs(emptyFuncs).Parse(contents)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,25 +176,11 @@ func (s *Engine) buildFromAsset() error {
|
||||||
|
|
||||||
func (s *Engine) executeTemplateBuf(name string, binding interface{}) (*bytes.Buffer, error) {
|
func (s *Engine) executeTemplateBuf(name string, binding interface{}) (*bytes.Buffer, error) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
/*
|
|
||||||
var err error
|
|
||||||
if s.Middleware != nil {
|
|
||||||
contents, err := s.Middleware(name, buf.String())
|
|
||||||
if err != nil {
|
|
||||||
return buf, err
|
|
||||||
}
|
|
||||||
buf.WriteString(contents)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
err := s.Templates.ExecuteTemplate(buf, name, binding)
|
err := s.Templates.ExecuteTemplate(buf, name, binding)
|
||||||
|
|
||||||
return buf, err
|
return buf, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Engine) ExecuteTemplateBuf(name string, binding interface{}) (*bytes.Buffer, error) {
|
|
||||||
return s.executeTemplateBuf(name, binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Engine) layoutFuncsFor(name string, binding interface{}) {
|
func (s *Engine) layoutFuncsFor(name string, binding interface{}) {
|
||||||
funcs := template.FuncMap{
|
funcs := template.FuncMap{
|
||||||
"yield": func() (template.HTML, error) {
|
"yield": func() (template.HTML, error) {
|
||||||
|
@ -211,15 +195,12 @@ func (s *Engine) layoutFuncsFor(name string, binding interface{}) {
|
||||||
fullPartialName := fmt.Sprintf("%s-%s", partialName, name)
|
fullPartialName := fmt.Sprintf("%s-%s", partialName, name)
|
||||||
if s.Config.HTMLTemplate.RequirePartials || s.Templates.Lookup(fullPartialName) != nil {
|
if s.Config.HTMLTemplate.RequirePartials || s.Templates.Lookup(fullPartialName) != nil {
|
||||||
buf, err := s.executeTemplateBuf(fullPartialName, binding)
|
buf, err := s.executeTemplateBuf(fullPartialName, binding)
|
||||||
// Return safe HTML here since we are rendering our own template.
|
|
||||||
return template.HTML(buf.String()), err
|
return template.HTML(buf.String()), err
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
"render": func(fullPartialName string) (template.HTML, error) {
|
"render": func(fullPartialName string) (template.HTML, error) {
|
||||||
buf, err := s.executeTemplateBuf(fullPartialName, binding)
|
buf, err := s.executeTemplateBuf(fullPartialName, binding)
|
||||||
println("html.go:217-> " + buf.String())
|
|
||||||
// Return safe HTML here since we are rendering our own template.
|
|
||||||
return template.HTML(buf.String()), err
|
return template.HTML(buf.String()), err
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -234,12 +215,28 @@ func (s *Engine) layoutFuncsFor(name string, binding interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Engine) runtimeFuncsFor(name string, binding interface{}) {
|
||||||
|
funcs := template.FuncMap{
|
||||||
|
"render": func(fullPartialName string) (template.HTML, error) {
|
||||||
|
buf, err := s.executeTemplateBuf(fullPartialName, binding)
|
||||||
|
return template.HTML(buf.String()), err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if tpl := s.Templates.Lookup(name); tpl != nil {
|
||||||
|
tpl.Funcs(funcs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ExecuteWriter executes a templates and write its results to the out writer
|
// ExecuteWriter executes a templates and write its results to the out writer
|
||||||
func (s *Engine) ExecuteWriter(out io.Writer, name string, binding interface{}, layout string) error {
|
func (s *Engine) ExecuteWriter(out io.Writer, name string, binding interface{}, layout string) error {
|
||||||
if layout != "" && layout != config.NoLayout {
|
if layout != "" && layout != config.NoLayout {
|
||||||
|
s.layoutFuncsFor(name, binding)
|
||||||
name = layout
|
name = layout
|
||||||
|
|
||||||
|
} else {
|
||||||
|
s.runtimeFuncsFor(name, binding)
|
||||||
}
|
}
|
||||||
s.layoutFuncsFor(name, binding)
|
|
||||||
|
|
||||||
return s.Templates.ExecuteTemplate(out, name, binding)
|
return s.Templates.ExecuteTemplate(out, name, binding)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,15 @@
|
||||||
|
// Package jade the JadeEngine's functionality lives inside ../html now
|
||||||
package jade
|
package jade
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Joker/jade"
|
|
||||||
"github.com/kataras/iris/config"
|
"github.com/kataras/iris/config"
|
||||||
"github.com/kataras/iris/render/template/engine/html"
|
"github.com/kataras/iris/render/template/engine/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Engine the JadeEngine
|
// New creates and returns the HTMLTemplate template engine
|
||||||
type Engine struct {
|
func New(c config.Template) *html.Engine {
|
||||||
*html.Engine
|
// copy the Jade to the HTMLTemplate
|
||||||
}
|
c.HTMLTemplate = config.HTMLTemplate(c.Jade)
|
||||||
|
s := &html.Engine{Config: &c}
|
||||||
// New creates and returns a new JadeEngine with its configs
|
return s
|
||||||
func New(cfg config.Template) *Engine {
|
|
||||||
cfg.HTMLTemplate.Funcs = cfg.Jade.Funcs //copy the jade's funcs to the underline HTMLEngine
|
|
||||||
cfg.HTMLTemplate.LayoutFuncs = cfg.Jade.LayoutFuncs
|
|
||||||
underline := &Engine{Engine: html.New(cfg)}
|
|
||||||
underline.Middleware = func(relativeName string, fileContents string) (string, error) {
|
|
||||||
return jade.Parse(relativeName, fileContents)
|
|
||||||
}
|
|
||||||
|
|
||||||
return underline
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,21 +55,48 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// sharedFuncs the funcs should be exists in all supported view template engines
|
||||||
|
var sharedFuncs map[string]interface{}
|
||||||
|
|
||||||
|
// we do this because we don't want to override the user's funcs
|
||||||
|
func setSharedFuncs(source map[string]interface{}, target map[string]interface{}) {
|
||||||
|
if source == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if target == nil {
|
||||||
|
target = make(map[string]interface{}, len(source))
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range source {
|
||||||
|
if target[k] == nil {
|
||||||
|
target[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// New creates and returns a Template instance which keeps the Template Engine and helps with render
|
// New creates and returns a Template instance which keeps the Template Engine and helps with render
|
||||||
func New(c config.Template) *Template {
|
func New(c config.Template) *Template {
|
||||||
|
defer func() {
|
||||||
|
sharedFuncs = nil
|
||||||
|
}()
|
||||||
|
|
||||||
var e Engine
|
var e Engine
|
||||||
// [ENGINE-2]
|
// [ENGINE-2]
|
||||||
switch c.Engine {
|
switch c.Engine {
|
||||||
case config.HTMLEngine:
|
case config.HTMLEngine:
|
||||||
|
setSharedFuncs(sharedFuncs, c.HTMLTemplate.Funcs)
|
||||||
e = html.New(c) // HTMLTemplate
|
e = html.New(c) // HTMLTemplate
|
||||||
|
case config.JadeEngine:
|
||||||
|
setSharedFuncs(sharedFuncs, c.Jade.Funcs)
|
||||||
|
e = jade.New(c) // Jade
|
||||||
case config.PongoEngine:
|
case config.PongoEngine:
|
||||||
|
setSharedFuncs(sharedFuncs, c.Pongo.Globals)
|
||||||
e = pongo.New(c) // Pongo2
|
e = pongo.New(c) // Pongo2
|
||||||
case config.MarkdownEngine:
|
case config.MarkdownEngine:
|
||||||
e = markdown.New(c) // Markdown
|
e = markdown.New(c) // Markdown
|
||||||
case config.JadeEngine:
|
|
||||||
e = jade.New(c) // Jade
|
|
||||||
case config.AmberEngine:
|
case config.AmberEngine:
|
||||||
|
setSharedFuncs(sharedFuncs, c.Amber.Funcs)
|
||||||
e = amber.New(c) // Amber
|
e = amber.New(c) // Amber
|
||||||
default: // config.NoEngine
|
default: // config.NoEngine
|
||||||
return nil
|
return nil
|
||||||
|
@ -97,6 +124,14 @@ func New(c config.Template) *Template {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterSharedFunc registers a functionality that should be inherited from all supported template engines
|
||||||
|
func RegisterSharedFunc(name string, fn interface{}) {
|
||||||
|
if sharedFuncs == nil {
|
||||||
|
sharedFuncs = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
sharedFuncs[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
// Render renders a template using the context's writer
|
// Render renders a template using the context's writer
|
||||||
func (t *Template) Render(ctx context.IContext, name string, binding interface{}, layout ...string) (err error) {
|
func (t *Template) Render(ctx context.IContext, name string, binding interface{}, layout ...string) (err error) {
|
||||||
|
|
||||||
|
|
21
router.go
21
router.go
|
@ -118,15 +118,32 @@ func (r *router) addRoute(route IRoute) {
|
||||||
|
|
||||||
// RouteByName returns a route by its name,if not found then returns a route with empty path
|
// RouteByName returns a route by its name,if not found then returns a route with empty path
|
||||||
// Note that the searching is case-sensitive
|
// Note that the searching is case-sensitive
|
||||||
func (r *router) RouteByName(lookUpName string) IRoute {
|
func (r *router) RouteByName(routeName string) IRoute {
|
||||||
for _, route := range r.lookups {
|
for _, route := range r.lookups {
|
||||||
if route.GetName() == lookUpName {
|
if route.GetName() == routeName {
|
||||||
return route
|
return route
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Route{}
|
return &Route{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UriOf returns the parsed URI of a route
|
||||||
|
// receives two parameters
|
||||||
|
// the first is the route's name (string)
|
||||||
|
// the second is a variadic, if the route is dynamic (receives named parameters) then pass the value of these parameters here
|
||||||
|
// overview of the result is: scheme(http or https if ListenTLS)/yourhost.com:PORT/profile/theusername/friends/theid
|
||||||
|
//
|
||||||
|
// example /profile/:username/friends/:friendId with name "profile" -> .UriOf("profile","kataras",8) will give http://127.0.0.1:8080/profile/kataras/friends/8
|
||||||
|
func (r *router) UriOf(routeName string, args ...interface{}) (string, error) {
|
||||||
|
route := r.RouteByName(routeName)
|
||||||
|
// check if not found
|
||||||
|
if route.GetMethod() == "" {
|
||||||
|
return "", ErrRenderRouteNotFound.Format(routeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return route.ParseURI(args...), nil
|
||||||
|
}
|
||||||
|
|
||||||
//check if any tree has cors setted to true, means that cors middleware is added
|
//check if any tree has cors setted to true, means that cors middleware is added
|
||||||
func (r *router) cors() (has bool) {
|
func (r *router) cors() (has bool) {
|
||||||
r.garden.visitAll(func(i int, tree *tree) {
|
r.garden.visitAll(func(i int, tree *tree) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user