diff --git a/Makefile b/Makefile
index 80bc021..dff54f1 100644
--- a/Makefile
+++ b/Makefile
@@ -38,16 +38,19 @@ EXECUTEABLE := whawty-auth
all: build
.PHONY: vet format ui build clean distclean
+format:
+ $(GOCMD) fmt ./...
+
vet:
$(GOCMD) vet ./...
-format:
- $(GOCMD) fmt ./...
+test: vet
+ $(GOCMD) test ./...
ui:
$(GOCMD) generate ./ui
-build: ui
+build: test ui
$(GOCMD) build -o $(EXECUTEABLE) ./cmd/whawty-auth
dev:
diff --git a/cmd/whawty-auth/main.go b/cmd/whawty-auth/main.go
index 0fd819a..902a08e 100644
--- a/cmd/whawty-auth/main.go
+++ b/cmd/whawty-auth/main.go
@@ -367,14 +367,43 @@ func cmdRun(c *cli.Context) error {
webAddrs := c.StringSlice("web-addr")
saslPaths := c.StringSlice("sock")
+ ssoAuthAddrs := c.StringSlice("sso-auth-addr")
+ ssoLoginAddrs := c.StringSlice("sso-login-addr")
var wg sync.WaitGroup
+ var sessions *webSessionFactory
+ if len(ssoAuthAddrs) > 0 || len(ssoLoginAddrs) > 0 || len(webAddrs) > 0 {
+ var err error
+ if sessions, err = NewWebSessionFactory(600 * time.Second); err != nil { // TODO: hardcoded value
+ return err
+ }
+ }
+ for _, ssoAuth := range ssoAuthAddrs {
+ a := ssoAuth
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ if err := runSSOAuthAddr(a, s.GetInterface(), sessions); err != nil {
+ fmt.Printf("warning running sso login interface(%s) failed: %s\n", a, err)
+ }
+ }()
+ }
+ for _, ssoLogin := range ssoLoginAddrs {
+ a := ssoLogin
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ if err := runSSOLoginAddr(a, s.GetInterface(), sessions); err != nil {
+ fmt.Printf("warning running sso auth interface(%s) failed: %s\n", a, err)
+ }
+ }()
+ }
for _, webAddr := range webAddrs {
a := webAddr
wg.Add(1)
go func() {
defer wg.Done()
- if err := runWebAddr(a, s.GetInterface()); err != nil {
+ if err := runWebAddr(a, s.GetInterface(), sessions); err != nil {
fmt.Printf("warning running web interface(%s) failed: %s\n", a, err)
}
}()
@@ -411,6 +440,7 @@ func cmdRunSa(c *cli.Context) error {
}
var wg sync.WaitGroup
+ var sessions *webSessionFactory
for idx, listener := range listeners {
switch listener.(type) {
case *net.UnixListener:
@@ -425,11 +455,18 @@ func cmdRunSa(c *cli.Context) error {
}()
case *net.TCPListener:
fmt.Printf("listener[%d]: is a TCP socket (-> HTTP)\n", idx)
+ if sessions == nil {
+ sessions, err = NewWebSessionFactory(10 * time.Minute) // TODO
+ if err != nil {
+ fmt.Printf("warning: running web-api failed: web session factory failed: %v\n", err)
+ continue
+ }
+ }
wg.Add(1)
ln := listener.(*net.TCPListener)
go func() {
defer wg.Done()
- if err := runWebListener(ln, s.GetInterface()); err != nil {
+ if err := runWebListener(ln, s.GetInterface(), sessions); err != nil {
fmt.Printf("error running web-api: %s", err)
}
}()
@@ -552,6 +589,16 @@ func main() {
Usage: "address to listen on for web API",
EnvVar: "WHAWTY_AUTH_WEB_ADDR",
},
+ cli.StringSliceFlag{
+ Name: "sso-auth-addr",
+ Usage: "address to listen on for nginx auth_request queries",
+ EnvVar: "WHAWTY_SSO_AUTH_ADDR",
+ },
+ cli.StringSliceFlag{
+ Name: "sso-login-addr",
+ Usage: "address to listen on for form-based login to auth-request",
+ EnvVar: "WHAWTY_SSO_LOGIN_ADDR",
+ },
},
Action: cmdRun,
},
diff --git a/cmd/whawty-auth/sso_api.go b/cmd/whawty-auth/sso_api.go
new file mode 100644
index 0000000..fbb331c
--- /dev/null
+++ b/cmd/whawty-auth/sso_api.go
@@ -0,0 +1,189 @@
+//
+// Copyright (c) 2016 whawty contributors (see AUTHORS file)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * Neither the name of whawty.auth nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+package main
+
+import (
+ "fmt"
+ "html"
+ "net"
+ "net/http"
+ _ "net/http/pprof"
+ "strings"
+ "time"
+)
+
+func handleSSOReturnLoginForm(w http.ResponseWriter, r *http.Request) {
+ baseURI := r.Header.Get("X-BaseURI")
+ if baseURI == "" {
+ baseURI = "/"
+ }
+
+ rip := r.Header.Get("X-Real-IP")
+ redir := r.URL.Query().Get("redir")
+ wdl.Printf("sso: got request for FORM LOGIN for SSO to %q from %q via %s", redir, rip, r.RemoteAddr)
+
+ w.Header().Set("Content-Type", "text/html")
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(fmt.Sprintf(`
+
+
Login to Realm %q at %q
+`, baseURI, "Our Realm", r.Host, html.EscapeString(redir), html.EscapeString(redir))))
+}
+
+func handleSSOPostLogin(store *Store, sessions *webSessionFactory, w http.ResponseWriter, r *http.Request) {
+ rip := r.Header.Get("X-Real-IP")
+ wdl.Printf("sso: got LOGIN for SSO request from %q via %s", rip, r.RemoteAddr)
+
+ user := r.PostFormValue("username")
+ password := r.PostFormValue("password")
+
+ if user == "" || password == "" {
+ http.Error(w, "Bad Request\nMissing at least one of: username, password", http.StatusBadRequest)
+ return
+ }
+
+ ok, isAdmin, _, err := store.Authenticate(user, password)
+ if err != nil || !ok {
+ http.Error(w, "Authentication failed", http.StatusUnauthorized)
+ return
+ }
+
+ status, _, session := sessions.Generate(user, isAdmin)
+ if status != http.StatusOK {
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ return
+ }
+
+ splitter := strings.Index(r.Host, ":")
+ if splitter == -1 {
+ splitter = len(r.Host)
+ }
+ domain := r.Host[:splitter]
+ cookie := http.Cookie{
+ Name: "sso", // TODO
+ Value: session,
+ Expires: time.Now().Add(10 * time.Minute), // TODO
+ Secure: true, // TODO
+ Domain: domain,
+ Path: "/",
+ }
+ http.SetCookie(w, &cookie)
+
+ redirect := r.URL.Query().Get("redir")
+ if redirect == "" {
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("login successful"))
+ return
+ }
+ http.Redirect(w, r, redirect, http.StatusTemporaryRedirect)
+}
+
+func handleSSOLogin(store *Store, sessions *webSessionFactory, w http.ResponseWriter, r *http.Request) {
+ switch r.Method {
+ case http.MethodGet:
+ handleSSOReturnLoginForm(w, r)
+ return
+ case http.MethodPost:
+ handleSSOPostLogin(store, sessions, w, r)
+ return
+ default:
+ http.Error(w, "Bad Request", http.StatusBadRequest)
+ }
+}
+
+func handleSSOAuth(store *Store, sessions *webSessionFactory, w http.ResponseWriter, r *http.Request) {
+ host := r.Header.Get("Host")
+ uri := r.Header.Get("X-Original-URI")
+ rip := r.Header.Get("X-Real-IP")
+ wdl.Printf("sso: got SSO AUTHENTICATE request for %s%s from %q via %s", host, uri, rip, r.RemoteAddr)
+
+ session, err := r.Cookie("sso")
+ if err != nil || session.Value == "" {
+ http.Error(w, "No authentication", http.StatusUnauthorized)
+ return
+ }
+
+ status, _, user, _ := sessions.Check(session.Value)
+ if status != http.StatusOK {
+ // nginx config must redirect to login for 401 for this to work as intended
+ http.Error(w, "Authentication failed", http.StatusUnauthorized)
+ return
+ }
+
+ w.Header().Set("User", user)
+ w.WriteHeader(http.StatusOK)
+}
+
+func runSSOLoginListener(listener *net.TCPListener, store *Store, sessions *webSessionFactory) (err error) {
+ mux := http.NewServeMux()
+ mux.Handle("/", webHandler{store, sessions, handleSSOLogin})
+
+ server := &http.Server{Handler: mux, ReadTimeout: 60 * time.Second, WriteTimeout: 60 * time.Second}
+ wl.Printf("sso-login: listening on '%s'", listener.Addr())
+ return server.Serve(tcpKeepAliveListener{listener})
+}
+
+func runSSOLoginAddr(addr string, store *Store, sessions *webSessionFactory) (err error) {
+ if addr == "" {
+ addr = ":http"
+ }
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return err
+ }
+ return runSSOLoginListener(ln.(*net.TCPListener), store, sessions)
+}
+
+func runSSOAuthListener(listener *net.TCPListener, store *Store, sessions *webSessionFactory) (err error) {
+ mux := http.NewServeMux()
+ mux.Handle("/", webHandler{store, sessions, handleSSOAuth})
+
+ server := &http.Server{Handler: mux, ReadTimeout: 60 * time.Second, WriteTimeout: 60 * time.Second}
+ wl.Printf("sso-auth: listening on '%s'", listener.Addr())
+ return server.Serve(tcpKeepAliveListener{listener})
+}
+
+func runSSOAuthAddr(addr string, store *Store, sessions *webSessionFactory) (err error) {
+ if addr == "" {
+ addr = ":http"
+ }
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return err
+ }
+ return runSSOAuthListener(ln.(*net.TCPListener), store, sessions)
+}
diff --git a/cmd/whawty-auth/web_api.go b/cmd/whawty-auth/web_api.go
index 4161142..d095053 100644
--- a/cmd/whawty-auth/web_api.go
+++ b/cmd/whawty-auth/web_api.go
@@ -33,9 +33,11 @@ package main
import (
"encoding/json"
"fmt"
+ "io/ioutil"
"net"
"net/http"
_ "net/http/pprof"
+ "strings"
"time"
storeLib "github.com/whawty/auth/store"
@@ -477,12 +479,7 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
return tc, nil
}
-func runWebApi(listener *net.TCPListener, store *Store) (err error) {
- var sessions *webSessionFactory
- if sessions, err = NewWebSessionFactory(600 * time.Second); err != nil { // TODO: hardcoded value
- return err
- }
-
+func runWebListener(listener *net.TCPListener, store *Store, sessions *webSessionFactory) (err error) {
mux := http.NewServeMux()
mux.Handle("/api/authenticate", webHandler{store, sessions, handleWebAuthenticate})
mux.Handle("/api/add", webHandler{store, sessions, handleWebAdd})
@@ -492,6 +489,25 @@ func runWebApi(listener *net.TCPListener, store *Store) (err error) {
mux.Handle("/api/list", webHandler{store, sessions, handleWebList})
mux.Handle("/api/list-full", webHandler{store, sessions, handleWebListFull})
+ mux.Handle("/admin/js/admin.js", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ baseURI := r.Header.Get("X-BaseURI")
+ if baseURI == "" {
+ baseURI = "/"
+ }
+ f, err := ui.Assets.Open("js/admin.js")
+ if err != nil {
+ panic("invalid path to compile-time asset specified")
+ }
+ content, _ := ioutil.ReadAll(f)
+ content = []byte(strings.Replace(
+ string(content),
+ `var auth_basepath = "/api/";`,
+ fmt.Sprintf(`var auth_basepath = "%sapi/";`, baseURI),
+ 1))
+ w.Header().Add("Content-Type", "applicatin/javascript")
+ w.WriteHeader(http.StatusOK)
+ w.Write(content)
+ }))
mux.Handle("/admin/", http.StripPrefix("/admin/", http.FileServer(ui.Assets)))
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
@@ -499,7 +515,11 @@ func runWebApi(listener *net.TCPListener, store *Store) (err error) {
http.NotFound(w, r)
return
}
- http.Redirect(w, r, "/admin/", http.StatusTemporaryRedirect)
+ baseURI := r.Header.Get("X-BaseURI")
+ if baseURI == "" {
+ baseURI = "/"
+ }
+ http.Redirect(w, r, fmt.Sprintf("%sadmin/", baseURI), http.StatusTemporaryRedirect)
})
wl.Printf("web-api: listening on '%s'", listener.Addr())
@@ -507,7 +527,7 @@ func runWebApi(listener *net.TCPListener, store *Store) (err error) {
return server.Serve(tcpKeepAliveListener{listener})
}
-func runWebAddr(addr string, store *Store) (err error) {
+func runWebAddr(addr string, store *Store, sessions *webSessionFactory) (err error) {
if addr == "" {
addr = ":http"
}
@@ -515,9 +535,5 @@ func runWebAddr(addr string, store *Store) (err error) {
if err != nil {
return err
}
- return runWebApi(ln.(*net.TCPListener), store)
-}
-
-func runWebListener(listener *net.TCPListener, store *Store) (err error) {
- return runWebApi(listener, store)
+ return runWebListener(ln.(*net.TCPListener), store, sessions)
}
diff --git a/contrib/nginx-sso-snippet.conf b/contrib/nginx-sso-snippet.conf
new file mode 100644
index 0000000..6c5f140
--- /dev/null
+++ b/contrib/nginx-sso-snippet.conf
@@ -0,0 +1,43 @@
+# redirect to a localhost-only admin page of whawty-auth
+location ^~ /whawty-auth/ {
+ proxy_pass http://127.0.0.1:9000/;
+ proxy_set_header X-BaseURI /whawty-auth/ # set to the matched prefix, necessary for redirects to generate correct URLs
+}
+
+# to be used as auth_request endpoint for other locations
+location = /auth {
+ internal;
+
+ proxy_pass http://127.0.0.1:8082;
+
+ # yes, we explicitly need to do both...
+ proxy_pass_request_body off;
+ proxy_set_header Content-Length "";
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header X-Real-IP $remote_addr;
+}
+
+# login response must set a cookie such that /auth will be able to access it
+# on success, must redirect (e.g. w/query param ?redir=target_url), obviously
+# with target_url restriction
+location = /login {
+ proxy_pass http://127.0.0.1:9001/?redir=$arg_redir;
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header X-Real-IP $remote_addr;
+}
+
+# how to use auth_request response
+location ^~ /app {
+ error_page 401 =200 /login/?redir=$http_host$request_uri;
+ auth_request /auth;
+ auth_request_set $user $upstream_http_remote_user;
+
+ proxy_set_header X-Remote-User $user;
+
+ # if all is good (auth_request returned 200), continue w/application
+ proxy_pass http://127.0.0.1:8080;
+}
diff --git a/go.mod b/go.mod
index 7614fd9..b117ab7 100644
--- a/go.mod
+++ b/go.mod
@@ -3,16 +3,19 @@ module github.com/whawty/auth
go 1.12
require (
+ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
github.com/fatih/color v1.7.0 // indirect
github.com/gosuri/uitable v0.0.3
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c
+ github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd // indirect
+ github.com/stretchr/testify v1.4.0 // indirect
github.com/urfave/cli v1.21.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
gopkg.in/spreadspace/scryptauth.v2 v2.0.0-20160119001838-d2c0fcba7783
diff --git a/go.sum b/go.sum
index 0512255..16d36ef 100644
--- a/go.sum
+++ b/go.sum
@@ -1,12 +1,21 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/gosuri/uitable v0.0.3 h1:9ZY4qCODg6JL1Ui4dL9LqCF4ghWnAOSV2h7xG98SkHE=
github.com/gosuri/uitable v0.0.3/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -16,10 +25,15 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE=
github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -33,6 +47,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/spreadspace/scryptauth.v2 v2.0.0-20160119001838-d2c0fcba7783 h1:jFQjb0EX7KZbncFa2MA3nTmtvijJLa76dp0gZKCpti4=
gopkg.in/spreadspace/scryptauth.v2 v2.0.0-20160119001838-d2c0fcba7783/go.mod h1:QqRNRCGuO4kuPa4MzrCXhA0+bvGze0vXYS6tM1MKeEE=
diff --git a/ui/assets/js/admin.js b/ui/assets/js/admin.js
index b5366ef..eb27647 100644
--- a/ui/assets/js/admin.js
+++ b/ui/assets/js/admin.js
@@ -29,6 +29,7 @@ var auth_username = null;
var auth_admin = false;
var auth_lastchanged = new Date();
var auth_session = null;
+var auth_basepath = "/api/";
function auth_loginSuccess(data) {
if (data.session) {
@@ -107,7 +108,7 @@ function auth_init() {
}
$("#login-btn").click(function(event) {
var data = JSON.stringify({ username: $("#login-username").val(), password: $("#login-password").val() })
- $.post("/api/authenticate", data, auth_loginSuccess, 'json').fail(auth_loginError);
+ $.post(auth_basepath + "authenticate", data, auth_loginSuccess, 'json').fail(auth_loginError);
});
$("#login-username").keypress(function(event) { overrideEnter(event, $("#login-btn")); });
$("#login-password").keypress(function(event) { overrideEnter(event, $("#login-btn")); });
@@ -153,7 +154,7 @@ function main_getUpdateButton(user) {
$("#changepw-btn").click(function(event) {
var newpassword = $("#changepw-password").val();
var data = JSON.stringify({ session: auth_session, username: user, newpassword: newpassword });
- $.post("/api/update", data, main_updateSuccess, 'json').fail(main_reqError);
+ $.post(auth_basepath + "update", data, main_updateSuccess, 'json').fail(main_reqError);
$("#changepw-modal").modal('hide');
});
$("#changepw-btn").text("Change");
@@ -173,7 +174,7 @@ function main_getRemoveButton(user) {
btn.html(' Remove')
return btn.click(function() {
var data = JSON.stringify({ session: auth_session, username: user });
- $.post("/api/remove", data, main_removeSuccess, 'json').fail(main_reqError);
+ $.post(auth_basepath + "remove", data, main_removeSuccess, 'json').fail(main_reqError);
});
}
@@ -187,7 +188,7 @@ function main_getSetAdminButton(user, oldstate) {
var newstate = !oldstate;
return btn.click(function() {
var data = JSON.stringify({ session: auth_session, username: user, admin: newstate });
- $.post("/api/set-admin", data, main_setadminSuccess, 'json').fail(main_reqError);
+ $.post(auth_basepath + "set-admin", data, main_setadminSuccess, 'json').fail(main_reqError);
});
}
@@ -258,7 +259,7 @@ function main_setupAddButton() {
$("#changepw-password").val(''); // we don't want the browser to add this user to it's password store...
$("#changepw-password-retype").val('');
var data = JSON.stringify({ session: auth_session, username: user, password: newpassword, admin: admin });
- $.post("/api/add", data, main_addSuccess, 'json').fail(main_reqError);
+ $.post(auth_basepath + "add", data, main_addSuccess, 'json').fail(main_reqError);
$("#changepw-modal").modal('hide');
});
$("#changepw-btn").text("Add");
@@ -270,7 +271,7 @@ function main_setupAddButton() {
function main_updateUserlist() {
var data = JSON.stringify({ session: auth_session });
- $.post("/api/list-full", data, main_userlistSuccess, 'json').fail(main_reqError);
+ $.post(auth_basepath + "list-full", data, main_userlistSuccess, 'json').fail(main_reqError);
}
function main_adminViewInit() {
@@ -300,7 +301,7 @@ function main_userViewInit() {
$("#changepw-btn").click(function(event) {
var newpassword = $("#changepw-password").val();
var data = JSON.stringify({ session: auth_session, username: auth_username, newpassword: newpassword });
- $.post("/api/update", data, main_userUpdateSuccess, 'json').fail(main_reqError);
+ $.post(auth_basepath + "update", data, main_userUpdateSuccess, 'json').fail(main_reqError);
$("#changepw-modal").modal('hide');
});
$("#changepw-btn").text("Change");
diff --git a/ui/assets_vfsdata.go b/ui/assets_vfsdata.go
index dde3060..75a3ad9 100644
--- a/ui/assets_vfsdata.go
+++ b/ui/assets_vfsdata.go
@@ -142,10 +142,10 @@ var Assets = func() http.FileSystem {
},
"/js/admin.js": &vfsgen۰CompressedFileInfo{
name: "admin.js",
- modTime: time.Date(2019, 8, 18, 2, 26, 0, 116152056, time.UTC),
- uncompressedSize: 16057,
+ modTime: time.Date(2019, 11, 22, 21, 9, 53, 893396417, time.UTC),
+ uncompressedSize: 16163,
- compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\xfb\x6f\xdc\xb8\x73\xff\xdd\x7f\xc5\x44\x09\x22\xa9\xde\x95\x93\x3b\x07\x68\xbd\x5e\x17\x79\x15\x4d\x91\xcb\x05\x75\xd2\x43\x11\x04\x06\x57\x9c\xdd\x65\xac\x25\x75\x24\xe5\xcd\xde\xc5\xff\x7b\x41\x52\x0f\xea\xb1\x8f\x24\xbe\xf4\x5a\x7c\x0f\x87\x78\x25\x0e\x87\xe4\xcc\xf0\x33\x0f\x52\x61\xa1\x10\x94\x96\x2c\xd5\xe1\xe4\xe8\x68\x5e\xf0\x54\x33\xc1\x81\xd0\x15\xe3\x57\x8c\x33\x1d\xc5\xf0\xe7\x11\x00\x29\xf4\xb2\x7c\x9e\x1c\x01\xac\x08\xe3\x57\xc8\xc9\x2c\xc3\xb7\xbf\x3d\x5f\x62\x7a\xad\x4c\xc3\xed\xd1\xd1\x0d\x91\x40\x32\x94\x7a\x26\x3e\xc3\x14\x2a\x8e\x86\xcd\xed\xe4\xa8\x6a\x49\xd6\x44\x72\xc6\x17\x1e\x05\x44\x14\x95\x1e\xc1\x12\x09\x65\x7c\x31\x82\x15\x2a\x45\x16\xe8\xc6\x7f\x10\x85\xf7\x43\x38\x06\x43\x03\xc7\x10\x42\x52\xb1\x0a\xe3\x64\xa9\x57\x59\x14\x9e\x53\x76\x03\x69\x46\x94\x9a\x06\xb6\xd1\xcd\x63\x5c\x0e\x15\x5c\x9c\x93\xaa\x39\xcd\x84\xc2\x00\x28\xd1\x64\x4c\x99\x5a\xb1\xba\x4f\x00\x4b\x89\xf3\x69\x70\x3f\xb8\x78\xa8\xd9\x0a\xd5\xe4\xfc\x84\x5c\x9c\x2f\x4f\x5b\x9c\xc7\xe5\x24\x83\x0b\x33\xa7\xf2\xc1\x4c\xeb\xfc\x64\x79\x6a\xdf\x95\x93\x77\xef\x28\xbb\xb9\x08\x8d\x78\x3c\x01\xa0\x94\x42\xfe\x88\xe5\x53\xc2\x17\x28\xff\x66\xab\x67\x7c\x2e\x7e\xc4\xe2\xcd\x38\x7f\xb3\xa5\xab\x22\x4d\x51\xa9\x1f\xb1\xfa\x72\xa8\xbf\x87\x00\x8e\x8e\x4e\xfe\xe9\x08\xcc\xff\xf0\x5a\x2c\x18\x77\xbf\x4f\x1c\x60\x18\x74\x29\x14\x4a\x4e\x56\x08\x53\xe0\x45\x96\x4d\x9a\x16\x8b\x46\x46\x60\x24\x53\xe8\xbd\xcf\x88\xd2\xe9\xd2\xd8\x37\x35\x9d\x70\x0d\x2f\x88\x46\x03\x44\x35\x89\x42\xa5\x8c\x88\x2b\x9e\x1e\xc4\x59\x0e\x66\x26\x97\x4e\x4c\x91\x11\x8a\x93\x39\x9b\x83\x7d\x4a\xca\xee\xee\xad\xd1\x45\x70\xdf\x76\x19\xab\x62\xb6\x62\x3a\x88\x93\x34\x63\xe9\x75\x14\x4f\xe0\xe4\x04\x34\x66\x19\xcc\xa4\x58\x2b\x94\xa0\x05\x28\x2d\x24\x82\x5e\x22\xe4\x44\xa9\xb5\x90\xf4\xc8\xb2\xe9\x2e\xd7\x0e\x55\x3d\x4f\x1a\x92\x6a\xdd\xb6\xdd\x3e\x78\x8d\x5b\x16\x6f\x69\xbd\xb6\xd8\xeb\xd2\x08\xc3\x5f\xdc\xc4\x4d\xaa\x7c\xba\xd4\x42\x92\x05\x26\x0a\xf5\x2b\x8d\xab\x28\x68\x4d\x36\x18\xb5\x27\x5f\x72\xdf\xd9\xd7\x4e\x3c\x18\x41\xd4\x3c\xc5\xf0\xaf\x10\x68\x59\x60\x00\x67\x10\x58\xb5\x06\x87\xb0\xf2\xd6\x55\xcd\xc4\x7b\x95\x68\xf1\xea\xf2\xd7\x4b\x2d\x19\x5f\x44\xf1\x21\xfc\xca\xc6\x8a\x57\xa5\xed\x52\x22\x66\xe7\x39\x6d\xbb\xcd\xa6\x32\x46\xf1\x7d\x1e\xf9\xed\x95\x20\xc6\x73\x86\x19\x0d\xe3\x44\xe3\x67\x1d\x0d\xc9\xc8\xd8\x94\xaf\xd5\x29\x18\x01\x54\x96\xe5\xb8\x49\x91\x75\x38\x05\x4f\xad\xf4\x4a\x1e\xb7\x80\x99\xc2\x7d\x5d\xde\x2b\x94\x75\x8f\x7a\xa6\xc6\x65\xaf\x19\xa7\x62\x1d\xc6\xc9\x9c\x50\x7c\xc5\xa3\x92\xc8\x7a\xf3\xc6\xb9\xb7\x46\x69\x3b\xac\x28\x6c\x04\x32\x82\xe0\xa5\x75\x62\x99\x58\x2c\x0c\x0a\x58\x2d\x5b\xcb\xb2\xb4\xca\x2a\xc2\xb7\xbf\x34\x43\xc2\x8b\xbc\x1c\xc5\x44\x0b\x03\xbb\xd1\xf2\x8c\x24\xfe\x3e\x02\xa5\x89\x2e\xd4\x08\x2c\x3b\x27\x29\xb3\xb1\x2b\x84\x99\x96\x04\x06\x6a\xce\xc0\x60\x8f\x25\x9c\xd8\x0d\x6c\x38\x24\x65\xfb\x74\x0a\xa7\x8f\x1e\x57\xa2\x6e\xba\x07\xf5\x1e\x24\x9c\x9e\x08\x59\x6f\x53\x20\x12\x61\x2d\x05\x5f\xdc\x0b\xdc\x5c\xbf\x5e\x10\x15\x88\x4f\x8e\x7c\xdc\xa8\x46\x08\xe2\xe4\x86\x64\x51\x18\xba\xa8\xa9\x27\x07\x51\xb4\x22\x2f\x4f\x72\x8e\x9d\x73\x02\x41\xec\xfe\x46\xa1\xc5\xf5\xb0\x33\x58\xbd\x6b\xbd\xc1\xf6\x4d\xc6\xb5\x37\xc6\x12\x38\x63\xf9\xb5\x28\x8d\x63\xbb\xd1\xd7\xdd\x87\x8c\xd2\x6b\xec\x6d\xa9\x17\x62\xcd\x23\x3f\x50\xec\x60\xad\xb7\x8c\xb9\x48\x0b\x55\xda\x8f\x93\x85\x9b\x65\x92\x89\x94\x98\xee\x89\xc4\x3c\x23\x29\x46\xc1\x49\xe0\x40\x79\x45\xae\x11\xd2\xa5\x14\x2b\x04\x13\xed\x72\x5c\x67\x1b\xa8\x90\xb3\x12\x81\x4a\x92\xbe\x1e\xba\xf1\xaf\x07\xd9\x1d\x58\x59\x0c\xa3\xa5\x9d\x68\x0b\xca\xa3\x9d\x1d\x1d\x54\xc6\xc6\x60\x1d\x3c\x1a\xa0\x34\x3f\xe0\xac\x72\x7e\xbb\xd1\x7f\x27\x77\x1f\x3d\xe3\x66\x6a\x8d\x57\xd8\xd9\xbb\xc2\x4a\x27\x76\x36\x8f\x5a\x9d\x1f\x3e\xec\x38\x86\x9e\x16\x67\xe2\x73\x10\x27\x4b\x46\xb1\x82\x9d\xff\x4b\xf8\x39\xb0\x25\x0e\xc3\xcf\xae\x00\xda\x3d\x7b\x8c\x1b\xf9\xdc\xb6\xb6\xea\x4c\xf3\x3a\xd8\xa8\xb7\x0a\xde\x20\xd7\x95\x04\x0c\x32\x1a\xf0\x85\x29\xfc\xc7\xe5\xaf\x6f\x12\x07\xbf\x6c\xbe\x89\xfe\x84\x4a\x94\x67\xdb\xc1\x21\x1e\xd5\x7b\xe1\x6c\x3b\x44\xc4\x70\x1b\xbb\x89\x27\xb9\x50\x3a\x0a\x4e\x48\xce\x4e\x8c\x5a\x90\x6b\x96\x12\x8d\xa5\x0b\x18\xf5\xe3\xab\x11\x84\x9f\x94\xe0\xd6\xfb\xb0\x2c\xea\x20\x7e\xbd\xa7\xb7\xec\xfc\x6b\xdc\xe4\xd2\x44\x69\xbd\xd5\x83\xb8\x41\x29\x19\xc5\x97\x5c\xa3\x74\xaf\x47\x5d\xd1\xc5\x93\x1e\x73\x6f\x69\x77\xc3\xbc\x87\x1f\x35\x6a\x5b\x15\x75\x76\x97\xc4\x95\xb8\xc1\xad\xa8\xb1\x8f\x9a\x34\x76\xbd\x8f\xb4\xb5\xef\x0f\xe9\xd0\xde\xea\xc3\xc1\x39\x0c\x86\xe6\xc3\xe8\xe4\x77\xe8\x05\xe4\xdf\xeb\xb0\x6e\xfd\xcc\xe2\x17\xc2\xf8\x99\xab\x5e\xc0\x0d\xc3\x75\x95\x64\xd4\x7a\xb1\x5b\xb5\xc8\x29\xd1\x38\x14\xf6\x47\xad\x50\xdc\x80\xcc\x56\x54\x73\xeb\xcb\xd7\x87\xa5\x02\x6e\x48\x60\x3a\x54\x4d\x94\x61\xf3\x83\x11\xcc\x0a\x0d\x82\x67\x1b\x03\x71\x4c\x03\x53\x20\x0a\xa9\x92\x24\xe9\x46\x1e\x65\x3e\x17\x85\x5e\x2c\x37\x82\xe0\x6d\xc5\xef\xbd\x1d\x24\x18\x41\x50\x52\xce\x8b\x2c\xdb\x94\x63\x37\xbe\x0e\xe6\x42\x42\x60\x52\x4a\x7f\xb1\x4d\x5d\xc7\xd1\x1b\x14\xcc\x98\xd2\x51\xc7\xb2\x2d\xc9\x02\xb5\x1b\xec\x59\xa1\xb5\xe0\x91\x61\xd2\x04\x68\x33\x6d\xf4\xfb\x20\x0a\xcf\x67\xb6\xf9\x22\x8c\x13\x42\xe9\x73\x93\x47\x46\x81\x83\xb2\xd6\xf3\x38\x97\x6c\x45\xe4\xa6\xf7\x5e\xad\x9c\xc5\xce\x34\xaf\x72\x5d\x95\x13\x5e\xa5\xa4\x8b\x6c\x93\x2f\x59\x2a\x38\xd4\xbf\xc6\x39\xf2\x94\x65\x01\x10\xc9\xc8\x78\xc9\x28\x45\x3e\x75\xce\xf4\xe2\xfc\xc4\x74\xbe\x78\xc8\x67\x2a\x9f\xb8\x7f\x2b\xd9\x39\x4b\x93\xa8\x0b\xc9\xed\x68\x1d\xa8\xad\x83\x47\xb3\xfa\x72\x5f\x57\x7d\x7f\x11\xd4\x40\xa3\x97\x15\xd4\xb6\x61\xe4\xd2\x72\x2e\x56\x50\x93\x61\x42\xa3\x85\xd0\x59\xb6\x23\xab\x0d\xc9\xa4\x90\x07\x19\x53\xdf\x3a\xf7\x3b\x0e\xa7\x33\x8e\xeb\x9a\xd5\xb4\xcd\xa2\xeb\x03\x26\x5e\xb7\x6d\x1e\xa7\xdc\xe6\x67\xad\x4d\x3f\xf2\x1c\x91\xf9\x35\xf2\x47\x3d\x6b\x4d\xe1\xb6\x1e\xa5\xe5\x69\x8a\xca\xc2\x9d\x8f\xe9\xef\xe6\x8e\x93\xb1\x04\x12\x7f\x6f\x5c\x4c\x4f\x40\x2b\xa3\xbd\x20\x4e\xec\xdf\x28\x34\x0e\x38\xac\x9c\xbf\xe7\xa5\x3b\x02\x75\x91\xc2\x73\xfb\x32\x18\x22\xfb\x4e\xef\xd2\x1e\xae\xf6\x5e\x5b\x06\x19\x4b\xd4\x9b\xfc\x5b\xdd\xe4\x61\x63\x75\xe4\xa4\x96\x26\x91\xac\x9c\x76\x0f\x20\x9c\x4f\xe9\x43\xec\x3e\x2c\xfb\x4f\xdb\x0f\x6c\x08\xd6\xc5\x31\xc7\x93\x5a\xd3\xf9\x7e\xfc\x72\x23\xdd\x11\x7e\x95\x45\xd6\x3b\x80\x2f\x2d\x89\x5a\x1e\x8a\x5e\x6e\x0d\x61\x7c\x10\x74\x7d\xf7\x76\x6d\xec\xc2\xdf\x92\x4e\x2b\xed\x2d\xd9\xd2\xfe\xde\x2d\x39\x68\x40\x0a\xb5\x75\xe3\x7d\x13\xfa\x0a\x1d\x5f\xa2\xb6\xf1\xbf\xa7\xe5\x11\x88\x8c\x2a\x4d\x34\x7e\x8f\xbe\xab\x33\x85\x3b\x50\xb8\x24\x9c\x8a\xd5\xc1\x1a\x17\x99\xd3\x77\x89\xd9\x76\x25\x30\x85\x7b\xd5\xaa\x0e\x73\x63\x77\x00\xdd\x56\x3b\x67\xcd\x1c\x06\x8d\x43\xa1\x1e\x57\xf5\x3f\xcf\x3e\x3a\xca\xfd\x36\x0b\x31\x7b\x58\x64\xf8\x9a\xcc\x30\x8b\xca\xb2\x62\x55\xbc\x1d\xcc\x11\x4b\xb1\x3c\x28\x95\xd2\xd6\x72\x66\xd8\x04\xbd\x37\x5e\x64\xd2\xca\x27\xbb\x69\xde\x37\xf1\xa6\x38\x27\x45\xa6\x83\x76\xe2\xd9\xab\x8d\x55\xab\x7d\x26\x44\xf6\x2a\x15\x3c\x9a\x67\x64\xd1\xac\xd5\x3c\x7d\xd5\x52\x6b\xdb\x0b\x06\xdf\x8e\xc5\xf5\x58\xb1\x85\x0d\x1b\x4c\x43\x2a\x32\x61\xc1\xf8\xfe\x93\x74\xf6\xcf\x4f\xd2\xea\xfd\x5c\x70\x3d\x56\xec\x0f\x1b\x70\x3e\x4e\x4e\xb1\xb4\xfd\xc3\xe5\xb2\x6f\x22\x0e\x46\xb6\x4c\x86\xfe\xcb\x93\x9f\x4f\xe7\x7b\x27\x63\x24\xf9\xa6\x58\xcd\x50\x26\xb9\x14\x5a\x18\x3f\x99\xe4\x84\xfa\x67\x93\xa6\x5f\x83\x06\x0a\xa6\x50\x16\x91\xf5\x92\x29\xcb\x66\xbd\x64\x19\x42\xa4\x92\x0c\xf9\x42\x2f\xe1\x1c\x6c\x27\xf8\xf2\x05\x7e\x8a\x63\xf8\xd3\xf4\x09\x1e\x19\x9f\xa4\x26\xb7\xcd\x0e\x54\x6d\xb3\x5d\xa0\x7e\x4d\x94\x76\x51\x43\xd4\x24\x49\x6e\x6c\x5f\x54\x76\xf8\xae\x11\x29\x3d\x4e\xcb\x80\xc3\x19\xcc\x02\xf5\x0b\xa2\xf1\x1d\x5b\x61\x39\x61\x8f\x67\xdc\xb7\xa1\xa2\x84\xcb\x3e\xa6\x56\xa5\x98\xb1\x69\x06\x3d\x13\x74\x63\x76\x23\xe3\x34\x0a\xb5\x0c\xe3\x32\x47\x74\xb1\x9f\x49\x1f\x22\x23\x29\xeb\x14\x18\x77\x7e\xd8\xf4\xf4\xe1\x45\x8a\x75\x09\xaa\x5a\xda\x95\xe4\x39\x72\x1a\xd9\x17\xf4\xa2\x15\x0f\xc7\x65\x5c\x06\xd0\xa7\x6a\x04\x60\xe8\xc7\x29\x9a\xe8\x25\xa8\xd9\xf5\x91\xa0\x9e\xcc\x07\xc3\xfb\xa3\x3b\x37\x89\x77\x8f\xe1\x5e\xb4\xd5\xd3\x39\x51\x69\x18\xfa\x87\x2b\x7b\xf8\x1e\x36\xf7\x7a\x5f\x77\x47\xba\x21\x19\xa3\x7f\xed\x10\xaa\xc8\x73\x21\x35\xee\x19\xc6\xea\xaa\xdb\x77\x2e\xe4\x8a\x68\x46\xed\xa9\x64\x14\x56\x01\x59\x8f\x22\x27\x92\xac\x6c\x95\x3e\x0e\xef\x62\x31\x83\x5e\x7d\x8b\xda\xeb\xd1\x0e\xfe\xaf\x3b\x5a\x3f\xcf\xbd\x03\xa6\xfd\xe0\x33\xee\x14\x45\xdd\x4e\xbc\x70\x7b\xf1\xcc\xd8\x5c\x63\xa8\x52\xac\x07\x8e\x50\x2c\x6f\x42\x69\x7f\x77\x9f\x9c\xc0\x1a\x81\x0a\x1e\x6a\x58\x13\xae\x0f\xcf\x27\x61\x7c\x51\xf6\x73\x55\x0e\xdb\xd3\x68\xf5\xde\x01\xb1\xfc\x53\x4a\x87\x03\x79\x42\xe9\xdd\x84\xf1\x0a\x75\x91\x3f\xa5\xb4\x14\x64\x85\x65\xc1\x7d\x42\xa9\x15\xa2\x99\x6a\x10\x27\x6e\xf2\x5b\xf2\x5f\xfb\x90\xe4\xd2\xfe\x7d\xe1\x5c\x72\x95\xe4\xd6\x28\x37\x6d\xb1\xf5\xeb\xa6\x0d\x61\xaf\x16\xe6\xfc\xb3\x51\x29\xe3\x79\xa1\x3f\x98\x6e\xd3\x80\x50\x2a\x45\x86\xc1\xc7\xb3\x74\x89\xe9\x35\xd2\xb0\xaa\xad\xda\xba\x7f\x75\x06\x50\x25\xe7\x15\x57\xe3\xde\xfd\x9a\xf4\x0f\xaa\x44\x84\xa1\xab\x43\xec\x34\x20\x42\x29\x18\x5f\xe9\x64\xa5\xc5\x90\x29\xb9\x7a\xd6\x8f\xab\x4e\x6c\xd1\x57\x18\x7a\x14\xbb\xe4\xd3\x22\xdc\x3e\xde\x9d\xcb\x67\x6f\x8a\xdf\x59\xc5\x1d\x84\xf2\x83\x25\x98\x3a\xc2\x77\x06\xb8\xa5\x20\x43\x28\x6d\x87\xf6\x0d\x00\xfd\xd8\x52\xcc\x53\x4a\xef\xb6\x0e\xf3\x57\xd5\x5c\xee\xa6\xbe\xd2\x05\xc7\x3a\x7a\xfd\x2a\x53\xa8\xce\x44\x7c\x8d\x1a\x7e\x63\x83\xd3\x9d\x2a\x5b\x3b\x76\xdc\xa3\xdc\x01\xbf\xb4\x62\xfc\xbf\x18\xae\x5f\x35\x67\xaa\x83\x10\xbe\x1b\xfe\xbb\x95\x7e\xbb\x9f\x76\x14\xfa\x15\xca\xf7\x5b\x8a\xfd\x77\x59\xc3\xff\x91\x45\xfa\xc1\xa8\xbe\x23\x59\xb3\x36\x0b\x7c\x46\x34\x90\x78\xc7\x2a\x5b\x8e\x57\x3b\x1d\x9a\x10\x77\x7b\xaa\xd1\x3d\xe8\x89\x5b\xd7\x03\x4a\x46\x33\x6d\x4c\xe4\x2f\xaa\xa5\x0f\x9d\x12\xef\x72\x65\x1d\xfa\xff\xcf\xd5\xf5\xd6\x52\xef\xa8\xcc\xde\xdd\x4b\xff\x28\xb5\xff\x6f\x95\xda\xbb\x28\xb8\xc8\xc4\x8c\x64\x3d\x08\x24\x6a\xc3\xd3\xab\x4c\x10\x1a\x29\x99\x36\x2e\x62\xce\xa4\xd2\x23\x50\xf6\x28\x18\xa6\x40\x45\x5a\xac\x4c\x0c\x9c\x4a\x24\x1a\x5f\x66\x68\x9e\xa2\x50\xa5\x92\xe5\xda\x8d\xac\x12\x25\x53\x98\x82\x92\xa9\x7b\x34\x42\x80\x29\x84\x46\x3b\x27\x9f\xc8\x0d\x29\xa9\x5d\xab\x1d\xda\x0b\x5a\xed\x90\xfe\x50\x0b\xd4\xe5\x38\xea\xd9\xe6\x1d\x59\xbc\x21\x2b\x6c\x46\xfc\xf0\xe8\xa3\x57\xc7\xb4\x9d\x93\x9c\x48\xe4\xfa\x8d\xa0\x98\x30\xae\x50\xea\x67\x38\x17\x12\x23\x35\x72\x04\x71\xaf\xd6\xd2\x01\x2c\xda\x72\x92\x68\xef\xb8\x6a\x13\xd9\xbb\xf2\x50\x44\x93\xb2\x4f\x14\xc7\x49\x4e\x68\xf4\x93\x5d\xb9\x4f\x7b\x3c\x85\x30\x31\x89\xae\xdf\xe5\x17\xc1\xf5\x32\x8a\xe1\x18\x1e\xef\xed\x67\x3b\xfc\x5b\x91\x65\xff\x8d\x44\x46\x83\x74\xd0\xe5\xff\xef\xa2\x90\x6a\xf7\x9c\xce\x7a\x73\x62\xbc\xd0\xf8\xb5\xbd\x2e\x31\x15\x9c\x76\x7a\x95\x4a\xf0\x3a\xb7\x05\x3d\x68\xeb\x33\x5d\x17\x63\xdd\xab\x64\xbd\x64\xe9\xd2\x24\x38\x8f\x7f\x86\x2f\x5f\xca\xa4\xeb\x1a\x37\xcf\x05\x45\xf7\xfa\x90\x7c\x8c\xcd\x23\x63\x78\x62\x6e\x6b\xf6\xf7\xa6\x53\x08\x0b\x4e\x71\xce\x38\xd2\x10\x1e\x3e\xb4\x35\xef\x5c\x8a\x3c\x0a\x29\x53\x64\x96\x99\xec\xca\xb0\xb7\x39\x59\x83\xc9\x4d\x69\xdc\xbb\xe7\x33\x90\x4e\x57\x78\xb6\xf3\x3e\xa2\x8f\xd2\x39\x91\x0a\xed\xdd\x43\x89\x2a\x17\x5c\xe1\x3b\xfc\xac\xed\x20\x3b\xae\x2e\x4e\xfc\x3b\xc7\xee\xcb\x80\x7b\x53\x08\x82\xee\x95\xc5\xe3\xa9\x77\xbf\xb2\x57\x6b\xf5\xa8\x1a\x82\xa3\x3d\xb7\x21\xbd\x0c\xb7\xe5\x34\xfc\x9b\xc6\xe5\x75\xc4\xc9\xf6\x7b\x79\xcd\x99\x75\x87\xc6\xc3\x66\xef\xee\xde\x9e\xdb\x94\x4f\x9b\xfb\x44\x46\x13\xc6\xbd\x14\x12\x3b\x77\x2a\x77\xde\x52\xed\x14\x22\xde\xbe\x02\xab\xc6\x2e\x8b\xbe\xc2\x87\xc3\x91\xba\x46\xda\x73\x07\x61\x5c\x02\x53\x14\x27\x44\x6b\x19\x85\xf6\xa8\x27\x1c\x41\x38\x17\x72\x35\x5e\x48\x51\xe4\xcd\x35\x96\x5d\x59\xe4\x0e\x12\x2d\xd9\x62\x81\xb2\xac\x23\xec\xa6\xf5\xc4\xbc\xc7\x81\x7d\xd7\xc4\x07\xf3\xd1\xbe\x17\x6b\xbe\x56\x08\xba\x37\x41\x7b\x8e\x5e\xcc\xe7\x66\x16\x2c\xbd\xde\x4a\xd2\xd9\xda\x23\x77\xe8\x31\x10\x14\xa7\x62\x65\x96\x57\xe9\x51\x45\x35\x1c\xed\x0c\xbe\x6c\x05\x26\x30\x00\xb5\x9b\xec\xde\x96\x20\xae\x2d\x95\xb8\xb9\x2f\x34\x60\x3a\x25\xed\x41\x16\x04\x4b\xa2\xc6\xd6\xb6\xc3\xed\x81\xd2\x36\xe1\xf4\x6e\x24\xde\xc5\x64\xca\xe4\xe5\x6b\xa6\xe3\x30\xb8\xde\x78\x16\x0f\x8d\xae\xde\xfe\x76\xa9\xa5\x3b\x57\x71\x57\x59\x9f\x4a\x49\x36\xd1\x93\x78\x72\xd4\x69\xff\xf0\xe8\xa3\x89\x39\x6e\x50\x6e\x60\x8d\xe4\x3a\xec\x53\x3c\xb6\x14\x5b\x1a\x7f\xb2\x8d\x4a\x8c\x95\x18\x68\xfd\xd9\xb5\x6a\x29\xf8\x62\xa0\xf9\xb4\x19\xbb\xa6\x19\x5a\xc4\x6b\xbc\xc1\x6c\xdf\x4a\x2c\x51\xb9\x1c\x77\x79\xa0\x3f\xa2\xa3\x79\x7c\x00\x8d\x5b\x57\x79\x28\xbd\x8d\xa8\x5c\x5e\xa9\xb7\x2d\x44\xa7\x1d\xa2\xce\xb6\xea\x7e\xf2\xb7\x13\x18\x05\xaf\x00\x6b\x04\x5b\x92\xbf\xde\x2e\x2d\x13\x3f\x7b\x80\x84\x26\x38\xfd\xe3\x73\x7a\x33\xe3\xd1\x03\x77\x16\x57\x5d\x55\xfd\xb0\x27\x35\x8c\x47\x10\xae\x97\x64\xad\x37\x21\x7c\x6c\xb2\xc9\xe0\x7e\xbe\x46\xa5\xd9\xca\xa4\xda\xa9\x24\xe9\xb5\x09\x69\x82\xea\x3b\xaa\xba\x09\x6c\xdb\xd8\x34\x9e\xc1\xb9\xd3\xb6\xfd\xb8\x49\xa2\x4a\x6c\xdb\x95\x8d\x85\xae\x28\x53\x79\x46\x36\x06\xba\x32\xc6\xf1\x4a\x65\x62\x7d\xb5\x24\x6a\xc9\xf8\xe2\xea\x31\x9e\x5e\xe5\x28\xaf\x94\x0d\xab\xdc\x07\x51\x15\x2f\x7f\xa1\x8c\xbb\xa4\x30\xbc\x9f\xaf\x55\xa9\x0d\xc6\xa9\x71\x7f\x66\xbf\x27\xb8\xca\xf5\xa6\x72\x9c\x73\x21\xed\xd9\x1b\x9b\x3e\x9a\x00\x3b\x3f\x9d\xc0\xf1\x31\x6b\x02\x1b\x36\x8f\x18\x9c\xdb\x79\xaa\x54\x48\x2f\xe4\x01\x33\x4e\x75\x82\xb0\xff\x5a\x82\xd2\x44\x42\x33\x1f\xcb\xac\x92\x80\x7d\x30\xeb\xd9\x75\x6b\xa1\xa9\x50\x76\x6e\x5d\x7f\xc3\x44\xc6\x56\x04\xdd\xe9\x3c\x3a\x70\xf8\x32\xc0\xab\xe5\xad\x59\x6e\x2c\x2b\x0c\xeb\x98\xb2\x65\x5d\xce\x07\x34\x82\xab\xc8\x77\x7e\x63\x08\x52\x64\x58\x7d\x49\x77\xf1\x36\x43\xa2\x10\x6c\x8e\xc4\x38\x90\xba\x8e\x50\x7e\x11\xd7\xba\x8d\x6e\xa3\x33\x95\xcc\x11\xe9\x8c\xa4\xd7\xd5\xa7\xb1\x87\x4f\xa0\xbc\x7c\xd4\x9e\x42\xa5\xab\x2e\x5b\xef\xbb\xbc\xc1\x3b\xf1\xfb\x06\xb3\x9f\xf8\x0d\x21\x47\x6d\x18\x1f\x9d\x65\xb4\x66\xf3\x6e\xc9\x14\x30\x05\x04\x06\xfa\x77\xba\x6e\x11\x56\x79\x9d\xc0\x5b\x91\x2a\x16\x0b\xb3\x65\x05\x57\xc9\x5c\xc8\x97\x24\x5d\x36\xb9\xb8\x66\x79\x4f\x82\xf6\xcf\xf1\x57\x69\xd2\x4c\x57\xb3\xbc\x2f\xb5\x36\xa8\x54\x76\x69\x46\xa8\xe0\xc4\xfc\xf6\xbf\x54\xd9\xe3\x77\x7d\xb4\x1c\x04\xc7\xa1\x30\xc7\xfb\x42\x65\xf7\xf7\x11\xee\x34\x64\xc5\xb8\x2d\xcc\x05\x71\xa2\x96\x62\xed\x87\xf4\x75\xd1\xae\xf3\x91\xc6\x50\xf5\x76\xf0\x23\x87\x16\xf7\xf6\x67\x1e\x6d\xee\xfe\xc8\x03\x05\xcc\xea\xdb\x07\xaf\x7a\x11\x7e\x52\x27\xce\x0f\x24\x9f\x94\xbb\xf3\xfd\x3f\x01\x00\x00\xff\xff\xdc\xce\xdb\x23\xb9\x3e\x00\x00"),
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\xfb\x6f\xdc\xb8\x73\xff\xdd\x7f\xc5\x44\x09\x22\xa9\xde\x95\x93\x3b\x07\x68\xbd\x5e\x17\x79\x15\x4d\x91\xcb\x05\x75\xd2\x43\x11\x04\x06\x57\x9c\xdd\x65\xac\x25\x75\x24\xe5\xcd\xde\xc5\xff\x7b\x41\x52\x0f\xea\xb1\x8f\x24\xbe\xf4\x5a\x7c\x0f\x87\x78\x25\x0e\x87\xe4\xcc\xf0\x33\x0f\x52\x61\xa1\x10\x94\x96\x2c\xd5\xe1\xe4\xe8\x68\x5e\xf0\x54\x33\xc1\x81\xd0\x15\xe3\x57\x8c\x33\x1d\xc5\xf0\xe7\x11\x00\x29\xf4\xb2\x7c\x9e\x1c\x01\xac\x08\xe3\x57\xc8\xc9\x2c\xc3\xb7\xbf\x3d\x5f\x62\x7a\xad\x4c\xc3\xed\xd1\xd1\x0d\x91\x40\x32\x94\x7a\x26\x3e\xc3\x14\x2a\x8e\x86\xcd\xed\xe4\xa8\x6a\x49\xd6\x44\x72\xc6\x17\x1e\x05\x44\x14\x95\x1e\xc1\x12\x09\x65\x7c\x31\x82\x15\x2a\x45\x16\xe8\xc6\x7f\x10\x85\xf7\x43\x38\x06\x43\x03\xc7\x10\x42\x52\xb1\x0a\xe3\x64\xa9\x57\x59\x14\x9e\x53\x76\x03\x69\x46\x94\x9a\x06\xb6\xd1\xcd\x63\x5c\x0e\x15\x5c\x9c\x93\xaa\x39\xcd\x84\xc2\x00\x28\xd1\x64\x4c\x99\x5a\xb1\xba\x4f\x00\x4b\x89\xf3\x69\x70\x3f\xb8\x78\xa8\xd9\x0a\xd5\xe4\xfc\x84\x5c\x9c\x2f\x4f\x5b\x9c\xc7\xe5\x24\x83\x0b\x33\xa7\xf2\xc1\x4c\xeb\xfc\x64\x79\x6a\xdf\x95\x93\x77\xef\x28\xbb\xb9\x08\x8d\x78\x3c\x01\xa0\x94\x42\xfe\x88\xe5\x53\xc2\x17\x28\xff\x66\xab\x67\x7c\x2e\x7e\xc4\xe2\xcd\x38\x7f\xb3\xa5\xab\x22\x4d\x51\xa9\x1f\xb1\xfa\x72\xa8\xbf\x87\x00\x8e\x8e\x4e\xfe\xe9\x08\xcc\xff\xf0\x5a\x2c\x18\x77\xbf\x4f\x1c\x60\x18\x74\x29\x14\x4a\x4e\x56\x08\x53\xe0\x45\x96\x4d\x9a\x16\x8b\x46\x46\x60\x24\x53\xe8\xbd\xcf\x88\xd2\xe9\xd2\xd8\x37\x35\x9d\x70\x0d\x2f\x88\x46\x03\x44\x35\x89\x42\xa5\x8c\x88\x7b\x3c\x67\x44\x61\x4e\xf4\x12\xa6\x10\x9c\x90\x9c\x9d\x04\x2d\xfc\xb3\xec\xcd\x34\x2f\x9d\x0c\x23\x23\x31\xa7\x10\x36\x07\xfb\x94\x94\xbc\xdd\x5b\xa3\xa8\xe0\xbe\xed\x32\x56\xc5\x6c\xc5\x74\x10\x27\x69\xc6\xd2\xeb\x28\x9e\xc0\xc9\x09\x68\xcc\x32\x98\x49\xb1\x56\x28\x41\x0b\x50\x5a\x48\x04\xbd\x44\xc8\x89\x52\x6b\x21\xe9\x91\x65\xd3\x95\x85\x1d\xaa\x7a\x9e\x34\x24\x95\x50\x6c\xbb\x7d\xf0\x1a\xb7\x48\xc6\xd2\x7a\x6d\xb1\xd7\xa5\x91\x94\xbf\xb8\x89\x9b\x54\xf9\x74\xa9\x85\x24\x0b\x4c\x14\xea\x57\x1a\x57\x51\xd0\x9a\x6c\x30\x6a\x4f\xbe\xe4\xbe\xb3\xaf\x9d\x78\x30\x82\xa8\x79\x8a\xe1\x5f\x21\xd0\xb2\xc0\x00\xce\x20\xb0\x3a\x0f\x0e\x61\xe5\xad\xab\x9a\x89\xf7\x2a\xd1\xe2\xd5\xe5\xaf\x97\x5a\x32\xbe\x88\xe2\x43\xf8\x95\x8d\x15\xaf\x4a\xdb\xa5\x44\xcc\xb6\x74\xda\x76\x3b\x51\x65\x8c\xe2\xfb\x3c\xf2\xdb\x2b\x41\x8c\xe7\x0c\x33\x1a\xc6\x89\xc6\xcf\x3a\x1a\x92\x91\xb1\x29\x5f\xab\x53\x30\x02\xa8\x2c\xcb\x71\x93\x22\xeb\x70\x0a\x9e\x5a\xe9\x95\x3c\x6e\x01\x33\x85\xfb\xba\xbc\x57\x28\xeb\x1e\xf5\x4c\x8d\x3f\x5f\x33\x4e\xc5\x3a\x8c\x93\x39\xa1\xf8\x8a\x47\x25\x91\x75\xf5\x8d\xe7\x6f\x8d\xd2\xf6\x66\x51\xd8\x08\x64\x04\xc1\x4b\xeb\xe1\x32\xb1\x58\x18\x88\xb0\x5a\xb6\x96\x65\x69\x95\x55\x84\x6f\x7f\x69\x86\x84\x17\x79\x39\x8a\x09\x25\x06\x76\xa3\xe5\x19\x49\xfc\x7d\x04\x4a\x13\x5d\xa8\x11\x58\x76\x4e\x52\x66\x73\x57\xf0\x33\x2d\x09\x0c\x0e\x9d\x81\x01\x26\x4b\x38\xb1\x1b\xd8\x70\x48\xca\xf6\xe9\x14\x4e\x1f\x3d\xae\x44\xdd\x74\x0f\xea\x3d\x48\x38\x3d\x11\xb2\xde\xa6\x40\x24\xc2\x5a\x0a\xbe\xb8\x17\xb8\xb9\x7e\xbd\x20\x2a\x84\x9f\x1c\xf9\xb8\x51\x8d\x10\xc4\xc9\x0d\xc9\xa2\x30\x74\x21\x55\x4f\x0e\xa2\x68\x85\x65\x9e\xe4\x1c\x3b\xe7\x21\x82\xd8\xfd\x8d\x42\x0b\xfa\x61\x67\xb0\x7a\xd7\x7a\x83\xed\x9b\x8c\x6b\x6f\x8c\x25\x70\xc6\xf2\x6b\x51\x1a\xc7\x76\xa3\xaf\xbb\x0f\x19\xa5\xd7\xd8\xdb\x52\x2f\xc4\x9a\x47\x7e\x14\xd9\xc1\x5a\x6f\x19\x73\x91\x16\xaa\xb4\x1f\x27\x0b\x37\xcb\x24\x13\x29\x31\xdd\x13\x89\x79\x46\x52\x8c\x82\x93\xc0\x81\xf2\x8a\x5c\x23\xa4\x4b\x29\x56\x08\x26\x14\xe6\xb8\xce\x36\x50\x21\x67\x25\x02\x95\x24\x7d\x3d\x74\x83\x63\x0f\xb2\x3b\xb0\xb2\x18\x46\x4b\x3b\xd1\x16\x94\x47\x3b\x3b\x3a\xa8\x8c\x8d\xc1\x3a\x78\x34\x40\x69\x7e\xc0\x59\xe5\x19\x77\xa3\xff\x4e\xee\x3e\x7a\xc6\xcd\xd4\x1a\xaf\xb0\xb3\x77\x85\x95\x4e\xec\x6c\x1e\xb5\x3a\x3f\x7c\xd8\x71\x0c\x3d\x2d\xce\xc4\xe7\x20\x4e\x96\x8c\x62\x05\x3b\xff\x97\xf0\x73\x60\x4b\x1c\x86\x9f\x5d\x01\xb4\x7b\xf6\x18\x37\xf2\xb9\x6d\x6d\xd5\x99\xe6\x75\xb0\x51\x6f\x15\xbc\x41\xae\x2b\x09\x18\x64\x34\xe0\x0b\x53\xf8\x8f\xcb\x5f\xdf\x24\x0e\x7e\xd9\x7c\x13\xfd\x09\x95\x28\xcf\xb6\x83\x43\x3c\xaa\xf7\xc2\xd9\x76\x88\x88\xe1\x36\x76\x13\x4f\x72\xa1\x4a\x45\xd5\x71\xd6\x31\x58\x53\x41\xae\x59\x4a\x34\x96\xde\x60\xd4\x0f\xb5\x46\x10\x7e\x52\x82\x5b\x47\xc4\xb2\xa8\x03\xfe\xf5\xf6\xde\x02\x02\xd7\xb8\xc9\xa5\x09\xd8\x7a\x82\x00\x71\x83\x52\x32\x8a\x2f\xb9\x46\xe9\x5e\x8f\xba\x52\x8c\x27\x3d\xe6\xde\x2a\xef\x86\x79\x0f\x4a\x6a\x00\xb7\xda\xea\x6c\x34\x89\x2b\x71\x83\x5b\x01\x64\x1f\x35\x69\x4c\x7c\x1f\x69\x0b\x02\x0e\xe9\xd0\xde\xf5\xc3\x41\x3c\x0c\x86\xf0\xc3\x40\xe5\x77\xe8\x06\xee\xdf\xed\xbb\x6e\xfd\x0c\xe4\x17\xc2\xf8\x99\xab\x72\xc0\x0d\xc3\x75\x95\x8c\xd4\x7a\xb1\xbb\xb6\xc8\x29\xd1\x38\x94\x01\x44\xad\xa8\xdc\xe0\xcd\x56\x80\x73\xeb\xcb\xd7\x87\x65\x05\x6e\x48\x60\x3a\x54\x4d\xc0\x61\x53\x85\x11\xcc\x0a\x0d\x82\x67\x1b\x83\x76\x4c\x03\x53\x20\x0a\xa9\x92\x24\xe9\x06\x21\x65\xde\x17\x85\x5e\x58\x37\x82\xe0\x6d\xc5\xef\xbd\x1d\x24\x18\x41\x50\x52\xce\x8b\x2c\xdb\x94\x63\x37\x6e\x0f\xe6\x42\x42\x60\x52\x4f\x7f\xb1\x4d\xfd\xc7\xd1\x1b\x40\xcc\x98\xd2\x51\xc7\xb2\x2d\xc9\x02\xb5\x1b\xec\x59\xa1\xb5\xe0\x91\x61\xd2\xc4\x6a\x33\x6d\xf4\xfb\x20\x0a\xcf\x67\xb6\xf9\x22\x8c\x13\x42\xe9\x73\x93\x6f\x46\x81\x43\xb5\xd6\xf3\x38\x97\x6c\x45\xe4\xa6\xf7\x5e\xad\x9c\xc5\xce\x34\xaf\x72\x62\x95\x13\x5e\xa5\xae\x8b\x6c\x93\x2f\x59\x2a\x38\xd4\xbf\xc6\x39\xf2\x94\x65\x01\x10\xc9\xc8\x78\xc9\x28\x45\x3e\x75\x7e\xf5\xe2\xfc\xc4\x74\xbe\x78\xc8\x67\x2a\x9f\xb8\x7f\x2b\xd9\x39\x4b\x93\xa8\x0b\xc9\xed\x68\x1d\xd4\xad\xe3\x48\xb3\xfa\x72\x5f\x57\x7d\x7f\x11\xd4\xa0\xa4\x97\x20\xd4\xb6\x61\xe4\xd2\xf2\x33\x56\x50\x93\x61\x42\xa3\x85\xd0\x59\xb6\x23\xab\x0d\xc9\x64\x93\x07\x19\x53\xdf\x3a\xf7\xfb\x10\xa7\x33\x8e\xeb\x9a\xd5\xb4\xcd\xa2\xeb\x0e\x26\x5e\xb7\x6d\xce\xa7\xdc\xe6\x67\xad\x4d\x3f\xf2\x7c\x92\xf9\x35\xf2\x47\x3d\x6b\x4d\xe1\xb6\x1e\x65\x9b\xd3\x29\x2a\x63\x77\xee\xa6\xbf\xb1\x3b\xfe\xc6\x12\x48\xfc\xbd\xf1\x36\x3d\x59\xad\x8c\x22\x83\x38\xb1\x7f\xa3\xd0\xb8\xe5\xb0\x0a\x09\x3c\xdf\xdd\x91\xad\x8b\x1f\x9e\xdb\x97\xc1\x10\xd9\x77\x3a\x9a\xf6\x70\xb5\x23\xdb\x32\xc8\x58\xa2\xde\xe4\xdf\xea\x31\x0f\x1b\xab\x23\x27\xb5\x34\xe9\x65\xe5\xbf\x7b\x58\xe1\xdc\x4b\x1f\x6d\xf7\xc1\xda\x7f\xda\x7e\x60\x03\xb3\x2e\xa4\x39\x9e\xd4\x5a\xd1\xf7\x43\x99\x1b\xe9\x8e\xa0\xac\xac\xcb\xde\x01\x92\x69\x49\xd4\xf2\x50\x20\x73\x6b\x08\xe3\x83\x50\xec\xbb\x77\x6e\x63\x17\x5b\x76\xa7\x53\x50\x7b\x77\xb6\x0c\x61\xef\xee\x1c\xb4\x25\x85\xda\x3a\xf7\xbe\x35\x7d\x85\xba\x2f\x51\xdb\x04\xc1\x53\xf8\x08\x44\x46\x95\x26\x1a\xbf\x47\xf5\xd5\x89\xc4\x1d\xe8\x5e\x12\x4e\xc5\xea\x60\xe5\x8b\xcc\xa9\xbe\x44\x72\xbb\x12\x98\xc2\xbd\x6a\x55\x87\x39\xb7\x3b\x00\x74\xab\x9d\xb3\x66\x0e\xfb\xec\x44\xa1\x1e\x57\xb5\x42\xcf\x54\x3a\x7a\xfe\x36\x63\x31\x3b\x5b\x64\xf8\x9a\xcc\x30\x8b\xca\x12\x64\x55\xe8\x1d\xcc\x27\x4b\x09\x3d\x28\xf5\xd3\x56\x78\x66\xd8\x04\xbd\x37\x5e\xe8\xd2\xca\x3d\xbb\x29\xe1\x37\xf1\xa6\x38\x27\x45\xa6\x83\x76\x92\xda\xab\xa3\x55\xab\x7d\x26\x44\xf6\x2a\x15\x3c\x9a\x67\x64\xd1\xac\xd5\x3c\x7d\xd5\x52\x6b\x33\x0c\x06\xdf\x8e\xc5\xf5\x58\xb1\x85\x8d\x2b\x4c\x43\x2a\x32\x61\x21\xfa\xfe\x93\x74\xf6\xcf\x4f\xd2\xea\xfd\x5c\x70\x3d\x56\xec\x0f\x1b\x91\x3e\x4e\x4e\xb1\xdc\x06\x87\xcb\x65\xdf\x44\x1c\xa2\x6c\x99\x0c\xfd\x97\x27\x3f\x9f\xce\xf7\x4e\xc6\x48\xf2\x4d\xb1\x9a\xa1\x4c\x72\x29\xb4\x30\xde\x33\xc9\x09\xf5\x0f\x39\x4d\xbf\x06\x18\x14\x4c\xa1\x2c\x38\xeb\x25\x53\x96\xcd\x7a\xc9\x32\x84\x48\x25\x19\xf2\x85\x5e\xc2\x39\xd8\x4e\xf0\xe5\x0b\xfc\x14\xc7\xf0\xa7\xe9\x13\x3c\x32\x9e\x4a\x4d\x6e\x9b\xcd\xa8\xda\x66\xbb\x40\xfd\x9a\x28\xed\x62\x89\xa8\xc9\xa2\xdc\xd8\xbe\xa8\xec\xf0\x5d\x23\x52\x7a\x9c\x96\x61\x88\x33\x98\x05\xea\x17\x44\xe3\x3b\xb6\xc2\x72\xc2\x1e\xcf\xb8\x6f\x43\x45\x89\x9c\x7d\x78\xad\xca\x36\x63\xd3\x0c\x7a\x26\xe8\xc6\xec\x46\xc6\x69\x14\x6a\x19\xc6\x65\x12\xe9\x82\x43\x93\x5f\x44\x46\x52\xd6\x55\x30\xee\xbc\xb3\xe9\xe9\x23\x8d\x14\xeb\x12\x5f\xb5\xb4\x2b\xc9\x73\xe4\x34\xb2\x2f\xe8\x45\x2b\x60\x8e\xcb\x68\x0d\xa0\x4f\xd5\x08\xc0\xd0\x8f\x53\x34\x31\x4d\x50\xb3\xeb\x23\x41\x3d\x99\x0f\x86\xf7\x47\x77\xc6\x12\xef\x1e\xc3\xbd\x68\xab\xa7\x73\xfa\xd2\x30\xf4\x0f\x62\xf6\xf0\x3d\x6c\xee\xf5\xbe\xee\x8e\x74\x43\x32\x46\xff\xda\x21\x54\x91\xe7\x42\x6a\xdc\x33\x8c\xd5\x55\xb7\xef\x5c\xc8\x15\xd1\x8c\xda\xe3\xcd\x28\xac\xc2\xb4\x1e\x45\x4e\x24\x59\xd9\x8a\x7e\x1c\xde\xc5\x62\x06\x1d\xfc\x16\xb5\xd7\xa3\x1d\xfc\x5f\x77\xb4\x7e\x22\x7c\x07\x4c\xfb\x21\x69\xdc\x29\xa0\xba\x9d\x78\xe1\xf6\xe2\x99\xb1\xb9\xc6\x50\xa5\x58\x0f\x1c\xb7\x58\xde\x84\xd2\xfe\xee\x3e\x39\x81\x35\x02\x15\x3c\xd4\xb0\x26\x5c\x1f\x9e\x70\xc2\xf8\xa2\xec\xe7\xca\x20\xb6\xa7\xd1\xea\xbd\x03\x22\xfc\xa7\x94\x0e\x87\xf7\x84\xd2\xbb\x09\xee\x15\xea\x22\x7f\x4a\x69\x29\xc8\x0a\xcb\x82\xfb\x84\x52\x2b\x44\x33\xd5\x20\x4e\xdc\xe4\xb7\x24\xc8\xf6\x21\xc9\xa5\xfd\xfb\xc2\xb9\xe4\x2a\x0b\xae\x51\x6e\xda\x62\xeb\xd7\x58\x1b\xc2\x5e\xb1\xcc\xf9\x67\xa3\x52\xc6\xf3\x42\x7f\x30\xdd\xa6\x01\xa1\x54\x8a\x0c\x83\x8f\x67\xe9\x12\xd3\x6b\xa4\x61\x55\x87\xb5\x67\x04\xd5\x79\x41\x95\xbd\x57\x5c\x8d\x7b\xf7\xeb\xd7\x3f\xa8\x54\x11\x86\xae\x50\xb1\xd3\x80\x08\xa5\x60\x7c\xa5\x93\x95\x16\x43\xa6\xe4\x0a\x5e\x3f\xae\x7c\xb1\x45\x5f\x61\xe8\x51\xec\x92\x4f\x8b\x70\xfb\x78\x77\x2e\x9f\xbd\x89\x7f\x67\x15\x77\x10\xd5\x0f\xd6\x68\xea\x60\xdf\x19\xe0\xfe\x8a\x0d\xa1\xb4\x1d\xe5\x37\x58\xf4\x63\x6b\x35\x4f\x29\xbd\xdb\x42\xcd\x5f\x55\x94\xb9\x9b\x02\x4c\x17\x27\xeb\x40\xf6\xab\xac\xa2\x3a\x3f\xd9\xa2\x5c\xc3\x7a\x6c\xd0\xbb\x53\x91\x6b\x47\x94\x7b\xf4\x3c\xe0\xad\x56\x8c\xff\x17\xc3\xf5\xab\xe6\x54\x76\x10\xd8\x77\x3b\x85\xee\x01\x81\xdd\x65\x3b\xce\x07\x14\xca\xf7\x5b\xce\x08\xee\xb2\xf4\xff\x23\x6b\xfb\x83\xb1\x7e\x47\xb2\x66\x6d\x16\x0e\x8d\x68\x20\xf1\x4e\x63\xb6\x1c\xd0\x76\x3a\x34\x81\xef\xf6\x04\xa4\x7b\x3e\x14\xb7\x2e\x18\x94\x8c\x66\xda\x98\xc8\x5f\x54\x82\x1f\x3a\x67\xde\xe5\xe0\x3a\xf4\xff\x9f\x8b\xf2\xad\xa5\xde\x7d\x75\xbe\xbb\xad\xfe\x51\xa1\xff\xdf\xaa\xd0\x77\x01\x71\x91\x89\x19\xc9\x7a\x68\x48\xd4\x86\xa7\x57\x99\x20\x34\x52\x32\x6d\x1c\xc7\x9c\x49\xa5\x47\xa0\xec\x61\x32\x4c\x81\x8a\xb4\x58\x99\x20\x39\x95\x48\x34\xbe\xcc\xd0\x3c\x45\xa1\x4a\x25\xcb\xb5\x1b\x59\x25\x4a\xa6\x30\x05\x25\x53\xf7\x68\x84\x00\x53\x08\x8d\x76\x4e\x3e\x91\x1b\x52\x52\xbb\x56\x3b\xb4\x17\xd5\xda\x21\xfd\xa1\x16\xa8\xcb\x71\xd4\xb3\xcd\x3b\xb2\x78\x43\x56\xd8\x8c\xf8\xe1\xd1\x47\xaf\xe6\x69\x3b\x27\x39\x91\xc8\xf5\x1b\x41\x31\x61\x5c\xa1\xd4\xcf\x70\x2e\x24\x46\x6a\xe4\x08\xe2\x5e\x31\xa6\x83\x5d\xb4\xe5\x3a\xd1\xde\xa6\xd5\x26\xf4\x77\xf5\xa3\x88\x26\x65\x9f\x28\x8e\x93\x9c\xd0\xe8\x27\xbb\x72\x9f\xf6\x78\x0a\x61\x62\x32\x61\xbf\xcb\x2f\x82\xeb\x65\x14\xc3\x31\x3c\xde\xdb\xcf\x76\xf8\xb7\x22\xcb\xfe\x1b\x89\x8c\x06\xe9\xa0\xcb\xff\xdf\x45\x21\xd5\xee\x39\x9d\xf5\xe6\xc4\x78\xa1\xf1\x6b\x7b\x5d\x62\x2a\x38\xed\xf4\x2a\x95\xe0\x75\x6e\x0b\x7a\xd0\xd6\x67\xba\xae\xd6\xba\x57\xc9\x7a\xc9\xd2\xa5\xc9\x80\x1e\xff\x0c\x5f\xbe\x94\x59\xd9\x35\x6e\x9e\x0b\x8a\xee\xf5\x21\x09\x1b\x9b\x47\xc6\xf0\xc4\xdc\xd6\xf7\xef\x4d\xa7\x10\x16\x9c\xe2\x9c\x71\xa4\x21\x3c\x7c\x68\xeb\xe3\xb9\x14\x79\x14\x52\xa6\xc8\x2c\x33\xe9\x97\x61\x6f\x93\xb6\x06\x9e\x9b\x32\xba\x77\x69\x68\x20\xdf\xae\xf0\x6c\xe7\xe5\x46\x1f\xb0\x73\x22\x15\xda\x8b\x8c\x12\x55\x2e\xb8\xc2\x77\xf8\x59\xdb\x41\x76\xdc\x83\x9c\xf8\x17\x98\xdd\x37\x08\xf7\xa6\x10\x04\xdd\xfb\x8f\xc7\x53\xef\xb2\x66\xaf\x18\xeb\x51\x35\x04\x47\x7b\xae\x56\x7a\x29\x70\xcb\x7f\xf8\xd7\x96\xcb\xbb\x8d\x93\xed\x97\xfc\x9a\x53\xef\x0e\x8d\x87\xcd\xde\x45\xc0\x3d\x57\x33\x9f\x36\x37\x92\x8c\x26\x8c\x7b\x29\x24\x76\x2e\x68\xee\xbc\xf2\xda\xa9\x54\xbc\x7d\x05\x56\x8d\x5d\x16\x7d\x85\x0f\x47\x26\x75\x11\xb5\xe7\x0e\xc2\xb8\x04\xa6\x28\x4e\x88\xd6\x32\x0a\xed\xb1\x50\x38\x82\x70\x2e\xe4\x6a\xbc\x90\xa2\xc8\x9b\x8b\x30\xbb\xd2\xcc\x1d\x24\x5a\xb2\xc5\x02\x65\x59\x68\xd8\x4d\xeb\x89\x79\x8f\x03\xfb\xae\x89\x0f\x26\xac\x7d\x2f\xd6\x7c\x17\x11\x74\xaf\x95\xf6\x1c\xbd\x98\xcf\xcd\x2c\x58\x7a\xbd\x95\xa4\xb3\xb5\x47\xee\x54\x64\x20\x3e\x4e\xc5\xca\x2c\xaf\xd2\xa3\x8a\x6a\x38\xda\x19\x87\xd9\x12\x4d\x60\x00\x6a\x37\xd9\xbd\x2d\xf1\x5c\x5b\x2a\x71\x73\xe3\x68\xc0\x74\x4a\xda\x83\x2c\x08\x96\x44\x8d\xad\x6d\x87\xdb\x03\xa5\x6d\xc2\xe9\x5d\x6f\xbc\x8b\xc9\x94\x79\xcc\xd7\x4c\xc7\x61\x70\xbd\xf1\x2c\x1e\x1a\x5d\xbd\xfd\xed\x52\x4b\x77\xf0\xe2\xee\xc5\x3e\x95\x92\x6c\xa2\x27\xf1\xe4\xa8\xd3\xfe\xe1\xd1\x47\x13\x73\xdc\xa0\xdc\xc0\x1a\xc9\x75\xd8\xa7\x78\x6c\x29\xb6\x34\xfe\x64\x1b\x95\x18\x2b\x31\xd0\xfa\xb3\x6b\xd5\x52\xf0\xc5\x40\xf3\x69\x33\x76\x4d\x33\xb4\x88\xd7\x78\x83\xd9\xbe\x95\x58\xa2\x72\x39\xee\xce\x41\x7f\x44\x47\xf3\xf8\x00\x1a\xb7\xae\xf2\x00\x7b\x1b\x51\xb9\xbc\x52\x6f\x5b\x88\x4e\x3b\x44\x9d\x6d\xd5\xfd\xb8\x70\x27\x30\x0a\x5e\x01\xd6\x08\xb6\xe4\x81\xbd\x5d\x5a\xe6\x80\xf6\x84\x09\x4d\x70\xfa\xc7\xe7\xf4\x66\xc6\xa3\x07\xee\xb0\xae\xba\xf7\xfa\x61\x4f\x96\x18\x8f\x20\x5c\x2f\xc9\x5a\x6f\x42\xf8\xd8\x24\x96\xc1\xfd\x7c\x8d\x4a\xb3\x95\xc9\xba\x53\x49\xd2\x6b\x13\xd2\x04\xd5\x17\x5b\x75\x13\xd8\xb6\xb1\x69\x3c\x83\x73\xa7\x6d\xfb\x19\x95\x44\x95\xd8\xb6\x2b\x1b\x0b\x5d\x51\xa6\xf2\x8c\x6c\x0c\x74\x65\x8c\xe3\x95\xca\xc4\xfa\x6a\x49\xd4\x92\xf1\xc5\xd5\x63\x3c\xbd\xca\x51\x5e\x29\x1b\x56\xb9\x4f\xaf\x2a\x5e\xfe\x42\x19\x77\xf9\x61\x78\x3f\x5f\xab\x52\x1b\x8c\x53\xe3\xfe\xcc\x7e\x4f\x70\x95\xeb\x4d\xe5\x38\xe7\x42\xda\xc3\x39\x36\x7d\x34\x01\x76\x7e\x3a\x81\xe3\x63\xd6\x04\x36\x6c\x1e\x31\x38\xb7\xf3\x54\xa9\x90\x5e\xc8\x03\x66\x9c\xea\x88\x61\xff\x15\x06\xa5\x89\x84\x66\x3e\x96\x59\x25\x01\xfb\x60\xd6\xb3\xeb\x86\x43\x53\xc2\xec\x5c\xe1\xfe\x86\x89\x8c\xad\x08\xba\xd3\x79\x74\xe0\xf0\x65\x80\x57\xcb\x5b\xb3\xdc\x58\x56\x18\xd6\x31\x65\xcb\xba\x9c\x0f\x68\x04\x57\x91\xef\xfc\x9a\x11\xa4\xc8\xb0\xfa\x66\xef\xe2\x6d\x86\x44\x21\xd8\x1c\x89\x71\x20\x75\x49\xa1\xfc\xf6\xae\x75\xb5\xdd\x46\x67\x2a\x99\x23\xd2\x19\x49\xaf\xab\x8f\x70\x0f\x9f\x40\x79\x67\xa9\x3d\x85\x4a\x57\x5d\xb6\xde\x17\x80\x83\x17\xec\xf7\x0d\x66\x3f\x26\x1c\x42\x8e\xda\x30\x3e\x3a\xcb\x68\xcd\xe6\xdd\x92\x29\x60\x0a\x08\x0c\xf4\xef\x74\xdd\x22\xac\xf2\xbe\x81\xb7\x22\x55\x2c\x16\x66\xcb\x0a\xae\x92\xb9\x90\x2f\x49\xba\x6c\x72\x71\xcd\xf2\x9e\x04\xed\x9f\xe3\xaf\xd2\xa4\x99\xae\x66\x79\x5f\x6a\x6d\x50\xa9\xec\xd2\x8c\x50\xc1\x89\xf9\xed\x7f\xf6\xb2\xc7\xef\xfa\x68\x39\x08\x8e\x43\x61\x8e\xf7\xb9\xcb\xee\x8f\x2d\xdc\x71\xc9\x8a\x71\x5b\xa3\x0b\xe2\x44\x2d\xc5\xda\x0f\xe9\xeb\xfa\x5d\xe7\x8b\x8f\xa1\x42\xee\xe0\x17\x13\x2d\xee\xed\x6f\x46\xda\xdc\xfd\x91\x07\x6a\x99\xd5\x87\x14\x5e\xf5\x22\xfc\xa4\x4e\x9c\x1f\x48\x3e\x29\x77\x6b\xfc\x7f\x02\x00\x00\xff\xff\x37\x32\x80\xe8\x23\x3f\x00\x00"),
},
"/js/zxcvbn.js": &vfsgen۰CompressedFileInfo{
name: "zxcvbn.js",