3
0

Add dev-mode with list of templates & scenarios

This commit is contained in:
Denis Arh
2021-02-23 19:58:29 +01:00
parent ea159ce83a
commit 06eb038ba8
8 changed files with 286 additions and 5 deletions

View File

@@ -1,4 +1,4 @@
# Corteza auth
= Corteza auth
.Main responsibilities:
- Sign-up protocol
@@ -8,3 +8,10 @@
- Session management
- Identity federation (login via external providers)
- Support OAuth2 flows
== Development
=== Templates
All (golang) templates can be found under `assets/templates`.
You can also find `scenarios.yaml` with list of all templates and scenaris with data that renders auth screens in all possible situations.

View File

@@ -0,0 +1,111 @@
# The following list of templates and scenarios describes
# all possible views (hopefully).
#
# Please read auth/README.adoc for details
error-internal:
Default:
error: |-
Lorem ipsum dolor sit...
login:
All disabled: {}
All enabled:
settings:
LocalEnabled: true
SignupEnabled: true
PasswordResetEnabled: true
ExternalEnabled: true
providers:
- { Label: Google, Handle: google, Icon: google }
- { Label: Facebook, Handle: facebook, Icon: facebook }
- { Label: Corteza, Handle: corteza, Icon: oidc }
Only external:
settings:
PasswordResetEnabled: true
ExternalEnabled: true
providers:
- { Label: Google, Handle: google, Icon: google }
- { Label: Facebook, Handle: facebook, Icon: facebook }
- { Label: Corteza, Handle: corteza, Icon: oidc }
Without signup & pass reset:
settings:
LocalEnabled: true
SignupEnabled: false
PasswordResetEnabled: false
With errors after submit:
settings:
LocalEnabled: true
form:
email: some.email@example.tld
error: "There was an error..."
logout:
Default: {}
signup:
Default: {}
reset-password:
Default: {}
request-password-reset:
Default: {}
password-reset-requested:
Default: {}
pending-email-confirmation:
Default: {}
profile:
Default: {}
change-password:
Default: {}
authorized-clients:
Empty: {}
Full:
authorizedClients:
- Name: Corteza Web Applications
- Name: Matrix Chat server
- Name: Company's Wordpress
oauth2-authorize-client:
Default:
client:
Name: name of the client
user:
Name: John Doe
Disabled:
invalidUser: Some good reason why this authorization of client is disabled...
disabled: true
client:
Name: name of the client
user:
Name: John Doe
sessions:
Full:
sessions:
- Current: true
ExpiresIn: 3
RemoteAddr: 4.224.2.3
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
- ExpiresIn: 2
RemoteAddr: 4.224.2.3
SameRemoteAddr: true
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
- ExpiresIn: 1
RemoteAddr: 4.224.2.3
SameUserAgent: true
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
- ExpiresIn: 0
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36

View File

@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap core CSS -->
<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)
})
</script>
</head>
<body class="bg-dark text-light">
<div class="container-fluid">
<div class="row m-0 p-0">
<div class="col-3">
{{ range .templates }}
<div class="pt-2">
<code>{{ .Template }}.html.tpl</code>
<ul class="nav flex-column">
{{ range .Scenes }}
<li class="nav-item border-top">
<a target="preview"
class="nav-link text-light"
href="/auth/dev/scenarios?template={{ .Template }}&scene={{ .Name }}"
onclick="location.hash=this.href"
>
<div>
{{ .Name }}
</div>
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
</div>
<div class="col-9 m-0 p-0">
<iframe
name="preview"
id="preview"
class="w-100 border-0"
style="height: 100vh;"
src="about:blank"
/>
</div>
</div>
</div>
</body>
</html>

View File

@@ -168,7 +168,7 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO
log.Info("using embedded assets")
}
if !opt.ReloadTemplates || len(opt.AssetsPath) == 0 {
if !opt.DevelopmentMode || len(opt.AssetsPath) == 0 {
log.Info("initializing templates without reloading (production mode)")
tpls, err = NewStaticTemplates(tplBase, tplLoader)
if err != nil {

107
auth/handlers/handle_dev.go Normal file
View File

@@ -0,0 +1,107 @@
package handlers
// Handlers dev-view for templates & scenarios
//
// See auth/README.adoc for details on how this works
import (
"github.com/cortezaproject/corteza-server/auth/request"
"github.com/cortezaproject/corteza-server/pkg/y7s"
"gopkg.in/yaml.v3"
"net/http"
"os"
)
type (
devScenariosDoc []*devTemplate
devTemplate struct {
Template string
Scenes devScenes
}
devScenes []*devScene
devScene struct {
Name string
Template string
Data map[string]interface{}
}
)
func (h *AuthHandlers) devView(req *request.AuthReq) (err error) {
req.Template = "template-dev.html.tpl"
req.Data["templates"], err = getScenes()
return
}
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 {
err = h.Templates.ExecuteTemplate(w, s.Template+".html.tpl", s.Data)
}
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func findScenario(template, scene string) (*devScene, error) {
templates, err := getScenes()
if err != nil {
return nil, err
}
for _, t := range templates {
if t.Template != template {
continue
}
for _, s := range t.Scenes {
if s.Name != scene {
continue
}
return s, nil
}
}
return nil, nil
}
func getScenes() (devScenariosDoc, error) {
f, err := os.Open("auth/assets/templates/scenarios.yaml")
if err != nil {
return nil, err
}
aux := devScenariosDoc{}
return aux, yaml.NewDecoder(f).Decode(&aux)
}
func (doc *devScenariosDoc) UnmarshalYAML(n *yaml.Node) error {
return y7s.EachMap(n, func(k *yaml.Node, v *yaml.Node) (err error) {
dt := &devTemplate{Template: k.Value, Scenes: devScenes{}}
err = y7s.EachMap(v, func(k *yaml.Node, v *yaml.Node) (err error) {
s := &devScene{
Name: k.Value,
Template: dt.Template,
Data: make(map[string]interface{}),
}
if err = v.Decode(s.Data); err != nil {
return
}
dt.Scenes = append(dt.Scenes, s)
return nil
})
if err != nil {
return
}
*doc = append(*doc, dt)
return nil
})
}

View File

@@ -25,6 +25,11 @@ func (h *AuthHandlers) MountHttpRoutes(r chi.Router) {
})
})
if h.Opt.DevelopmentMode {
r.Get("/auth/dev", h.handle(h.devView))
r.Get("/auth/dev/scenarios", h.devSceneView)
}
r.Group(func(r chi.Router) {
if h.Opt.RequestRateLimit > 0 {
r.Use(httprate.LimitByIP(h.Opt.RequestRateLimit, h.Opt.RequestRateWindowLength)) // @todo make configurable

View File

@@ -35,7 +35,7 @@ type (
CsrfCookieName string `env:"AUTH_CSRF_COOKIE_NAME"`
DefaultClient string `env:"AUTH_DEFAULT_CLIENT"`
AssetsPath string `env:"AUTH_ASSETS_PATH"`
ReloadTemplates bool `env:"AUTH_RELOAD_TEMPLATES"`
DevelopmentMode bool `env:"AUTH_DEVELOPMENT_MODE"`
}
)

View File

@@ -141,10 +141,10 @@ props:
When corteza starts, if path exists it tries to load template files from it.
If not it uses statically embedded files.
- name: reloadTemplates
- name: developmentMode
type: bool
description: |-
When enabled, corteza reloads template before every execution.
Enable this for debugging or when developing auth templates.
Disable it for environments (production) where templates do not change between server restarts.
Should be disabled in production where templates do not change between server restarts.