Switched auth assets from statik to go:embed
This commit is contained in:
@@ -145,10 +145,6 @@ provision:
|
||||
docs: $(STATIK)
|
||||
$(STATIK) -p docs -m -Z -f -src=./docs
|
||||
|
||||
auth: $(STATIK)
|
||||
$(STATIK) -dest auth -p handlers -a embedded_assets -m -Z -f -src=./auth/assets
|
||||
|
||||
|
||||
#######################################################################################################################
|
||||
# Quality Assurance
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ login:
|
||||
- { Label: Facebook, Handle: facebook, Icon: facebook }
|
||||
- { Label: Corteza, Handle: corteza, Icon: oidc }
|
||||
|
||||
Without signup & pass reset:
|
||||
Without signup and pass reset:
|
||||
settings:
|
||||
LocalEnabled: true
|
||||
SignupEnabled: false
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<script type="application/javascript">
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById("preview").src=location.hash.substring(1)
|
||||
document.getElementsByID('preview').src=location.hash.substring(1)
|
||||
})
|
||||
</script>
|
||||
</head>
|
||||
@@ -39,7 +39,6 @@
|
||||
<div class="col-9 m-0 p-0">
|
||||
<iframe
|
||||
name="preview"
|
||||
id="preview"
|
||||
class="w-100 border-0"
|
||||
style="height: 100vh;"
|
||||
src="about:blank"
|
||||
|
||||
+23
-2
@@ -2,7 +2,9 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/Masterminds/sprig"
|
||||
"github.com/cortezaproject/corteza-server/auth/external"
|
||||
"github.com/cortezaproject/corteza-server/auth/handlers"
|
||||
"github.com/cortezaproject/corteza-server/auth/oauth2"
|
||||
@@ -11,6 +13,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza-server/pkg/auth"
|
||||
"github.com/cortezaproject/corteza-server/pkg/options"
|
||||
"github.com/cortezaproject/corteza-server/pkg/version"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
systemService "github.com/cortezaproject/corteza-server/system/service"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
@@ -18,6 +21,7 @@ import (
|
||||
oauth2def "github.com/go-oauth2/oauth2/v4"
|
||||
"go.uber.org/zap"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -33,6 +37,9 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
//go:embed assets/public
|
||||
var publicAssets embed.FS
|
||||
|
||||
// New initializes Auth service that orchestrates session manager, oauth2 manager and http request handlers
|
||||
func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthOpt) (svc *service, err error) {
|
||||
var (
|
||||
@@ -150,7 +157,13 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO
|
||||
}
|
||||
|
||||
var (
|
||||
tplBase = handlers.TemplateBase()
|
||||
tplBase = template.New("").
|
||||
Funcs(sprig.FuncMap()).
|
||||
Funcs(template.FuncMap{
|
||||
"version": func() string { return version.Version },
|
||||
"buildtime": func() string { return version.BuildTime },
|
||||
"links": handlers.GetLinks,
|
||||
})
|
||||
tplLoader templateLoader
|
||||
)
|
||||
|
||||
@@ -164,7 +177,7 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO
|
||||
}
|
||||
log.Info("loading assets from filesystem", zap.String("path", opt.AssetsPath))
|
||||
} else {
|
||||
tplLoader = handlers.EmbeddedTemplates
|
||||
tplLoader = EmbeddedTemplates
|
||||
log.Info("using embedded assets")
|
||||
}
|
||||
|
||||
@@ -275,6 +288,14 @@ func (svc service) gcOAuth2Tokens(ctx context.Context) {
|
||||
|
||||
func (svc service) MountHttpRoutes(r chi.Router) {
|
||||
svc.handlers.MountHttpRoutes(r)
|
||||
|
||||
const uriRoot = "/auth/assets/public"
|
||||
if len(svc.opt.AssetsPath) == 0 {
|
||||
r.Handle(uriRoot+"/*", http.StripPrefix("/auth/assets", http.FileServer(http.FS(publicAssets))))
|
||||
} else {
|
||||
var root = strings.TrimRight(svc.opt.AssetsPath, "/") + "/public"
|
||||
r.Handle(uriRoot+"/*", http.StripPrefix(uriRoot, http.FileServer(http.Dir(root))))
|
||||
}
|
||||
}
|
||||
|
||||
//func (svc service) WellKnownOpenIDConfiguration() http.HandlerFunc {
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Masterminds/sprig"
|
||||
"github.com/cortezaproject/corteza-server/pkg/version"
|
||||
"github.com/goware/statik/fs"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type (
|
||||
TemplateExecutor interface {
|
||||
ExecuteTemplate(io.Writer, string, interface{}) error
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
tmplRoot = "/templates"
|
||||
TmplAuthorizedClients = "authorized-clients.html.tpl"
|
||||
TmplChangePassword = "change-password.html.tpl"
|
||||
TmplLogin = "login.html.tpl"
|
||||
TmplLogout = "logout.html.tpl"
|
||||
TmplOAuth2AuthorizeClient = "oauth2-authorize-client.html.tpl"
|
||||
TmplRequestPasswordReset = "request-password-reset.html.tpl"
|
||||
TmplPasswordResetRequested = "password-reset-requested.html.tpl"
|
||||
TmplResetPassword = "reset-password.html.tpl"
|
||||
TmplProfile = "profile.html.tpl"
|
||||
TmplSessions = "sessions.html.tpl"
|
||||
TmplSignup = "signup.html.tpl"
|
||||
TmplPendingEmailConfirmation = "pending-email-confirmation.html.tpl"
|
||||
TmplInternalError = "error-internal.html.tpl"
|
||||
)
|
||||
|
||||
//var (
|
||||
// Templates = []string{
|
||||
// TmplAuthorizedClients,
|
||||
// TmplChangePassword,
|
||||
// TmplLogin,
|
||||
// TmplLogout,
|
||||
// TmplOAuth2AuthorizeClient,
|
||||
// TmplRequestPasswordReset,
|
||||
// TmplPasswordResetRequested,
|
||||
// TmplResetPassword,
|
||||
// TmplProfile,
|
||||
// TmplSessions,
|
||||
// TmplSignup,
|
||||
// TmplPendingEmailConfirmation,
|
||||
// TmplInternalError,
|
||||
// }
|
||||
//)
|
||||
|
||||
func TemplateBase() *template.Template {
|
||||
return template.New("").
|
||||
Funcs(sprig.FuncMap()).
|
||||
Funcs(template.FuncMap{
|
||||
"version": func() string { return version.Version },
|
||||
"buildtime": func() string { return version.BuildTime },
|
||||
"links": GetLinks,
|
||||
})
|
||||
}
|
||||
|
||||
// EmbeddedTemplates returns embedded templates.
|
||||
//
|
||||
// @todo migrate to go:embed as soon as we can
|
||||
func EmbeddedTemplates(t *template.Template) (tpl *template.Template, err error) {
|
||||
var (
|
||||
f http.File
|
||||
tplBody []byte
|
||||
sfs http.FileSystem
|
||||
)
|
||||
|
||||
if sfs, err = fs.New(embedded_assets); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if t, err = t.Clone(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return t, fs.Walk(sfs, tmplRoot, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// templates are always referenced with path, relative to template root
|
||||
var tplName = path[len(tmplRoot)+1:]
|
||||
|
||||
if f, err = sfs.Open(path); err != nil {
|
||||
return fmt.Errorf("could not open %s: %w", path, err)
|
||||
} else if tplBody, err = ioutil.ReadAll(f); err != nil {
|
||||
return fmt.Errorf("could not read %s: %w", path, err)
|
||||
} else if t, err = t.New(tplName).Parse(string(tplBody)); err != nil {
|
||||
return fmt.Errorf("could not parse %s: %w", path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func EmbeddedPublicAssets() http.HandlerFunc {
|
||||
sfs, err := fs.New(embedded_assets)
|
||||
if err != nil {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, fmt.Sprintf("could not read embeded filesystem: %v", err.Error()), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
http.StripPrefix("/auth/assets", http.FileServer(sfs)).ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func DirectPublicAssets(prefix, root string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
http.StripPrefix(prefix, http.FileServer(http.Dir(root))).ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
@@ -36,14 +36,14 @@ func (h *AuthHandlers) devView(req *request.AuthReq) (err error) {
|
||||
func (h *AuthHandlers) devSceneView(w http.ResponseWriter, r *http.Request) {
|
||||
s, err := findScenario(r.URL.Query().Get("template"), r.URL.Query().Get("scene"))
|
||||
|
||||
if err == nil {
|
||||
if err == nil && s != nil {
|
||||
err = h.Templates.ExecuteTemplate(w, s.Template+".html.tpl", s.Data)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func findScenario(template, scene string) (*devScene, error) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/markbates/goth"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
@@ -52,10 +53,14 @@ type (
|
||||
DeleteByUserID(ctx context.Context, userID uint64) error
|
||||
}
|
||||
|
||||
templateExecutor interface {
|
||||
ExecuteTemplate(io.Writer, string, interface{}) error
|
||||
}
|
||||
|
||||
AuthHandlers struct {
|
||||
Log *zap.Logger
|
||||
|
||||
Templates TemplateExecutor
|
||||
Templates templateExecutor
|
||||
OAuth2 *oauth2server.Server
|
||||
SessionManager *session.Manager
|
||||
AuthService authService
|
||||
@@ -70,6 +75,22 @@ type (
|
||||
handlerFn func(req *request.AuthReq) error
|
||||
)
|
||||
|
||||
const (
|
||||
TmplAuthorizedClients = "authorized-clients.html.tpl"
|
||||
TmplChangePassword = "change-password.html.tpl"
|
||||
TmplLogin = "login.html.tpl"
|
||||
TmplLogout = "logout.html.tpl"
|
||||
TmplOAuth2AuthorizeClient = "oauth2-authorize-client.html.tpl"
|
||||
TmplRequestPasswordReset = "request-password-reset.html.tpl"
|
||||
TmplPasswordResetRequested = "password-reset-requested.html.tpl"
|
||||
TmplResetPassword = "reset-password.html.tpl"
|
||||
TmplProfile = "profile.html.tpl"
|
||||
TmplSessions = "sessions.html.tpl"
|
||||
TmplSignup = "signup.html.tpl"
|
||||
TmplPendingEmailConfirmation = "pending-email-confirmation.html.tpl"
|
||||
TmplInternalError = "error-internal.html.tpl"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(&types.User{})
|
||||
gob.Register(&types.AuthClient{})
|
||||
|
||||
+1
-10
@@ -4,11 +4,9 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/auth/request"
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/httprate"
|
||||
"github.com/gorilla/csrf"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (h *AuthHandlers) MountHttpRoutes(r chi.Router) {
|
||||
@@ -16,8 +14,6 @@ func (h *AuthHandlers) MountHttpRoutes(r chi.Router) {
|
||||
l = GetLinks()
|
||||
)
|
||||
|
||||
r.Use(middleware.StripSlashes)
|
||||
|
||||
r.Use(func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := actionlog.RequestOriginToContext(r.Context(), actionlog.RequestOrigin_Auth)
|
||||
@@ -30,6 +26,7 @@ func (h *AuthHandlers) MountHttpRoutes(r chi.Router) {
|
||||
r.Get("/auth/dev/scenarios", h.devSceneView)
|
||||
}
|
||||
|
||||
r.Handle("/auth/", http.RedirectHandler("/auth", http.StatusSeeOther))
|
||||
r.Group(func(r chi.Router) {
|
||||
if h.Opt.RequestRateLimit > 0 {
|
||||
r.Use(httprate.LimitByIP(h.Opt.RequestRateLimit, h.Opt.RequestRateWindowLength)) // @todo make configurable
|
||||
@@ -95,10 +92,4 @@ func (h *AuthHandlers) MountHttpRoutes(r chi.Router) {
|
||||
r.HandleFunc("/auth/oauth2/info", h.oauth2Info)
|
||||
})
|
||||
|
||||
const uriRoot = "/auth/assets/public"
|
||||
if len(h.Opt.AssetsPath) == 0 {
|
||||
r.Handle(uriRoot+"/*", EmbeddedPublicAssets())
|
||||
} else {
|
||||
r.Handle(uriRoot+"/*", DirectPublicAssets(uriRoot, strings.TrimRight(h.Opt.AssetsPath, "/")+"/public"))
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
+10
-1
@@ -1,10 +1,14 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"html/template"
|
||||
"io"
|
||||
)
|
||||
|
||||
//go:embed assets/templates/*.tpl
|
||||
var embeddedTemplates embed.FS
|
||||
|
||||
type (
|
||||
templateLoader func(tpls *template.Template) (tpl *template.Template, err error)
|
||||
|
||||
@@ -51,7 +55,12 @@ func NewStaticTemplates(base *template.Template, loader templateLoader) (s *temp
|
||||
return
|
||||
}
|
||||
|
||||
// Executes preloaded templates
|
||||
// ExecuteTemplate executes preloaded templates
|
||||
func (t templateStatic) ExecuteTemplate(w io.Writer, name string, data interface{}) error {
|
||||
return t.base.ExecuteTemplate(w, name, data)
|
||||
}
|
||||
|
||||
// EmbeddedTemplates returns embedded templates.
|
||||
func EmbeddedTemplates(t *template.Template) (tpl *template.Template, err error) {
|
||||
return t.ParseFS(embeddedTemplates, "templates/*.html.tpl")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user