chore: replace duplicate template code with templ

This commit is contained in:
Johan Siebens
2024-01-26 09:19:58 +01:00
parent 8f2c198bfe
commit cbde00c9f5
24 changed files with 702 additions and 872 deletions
+2
View File
@@ -1,10 +1,12 @@
init: init:
go install github.com/a-h/templ/cmd/templ@latest
go install github.com/bufbuild/buf/cmd/buf@latest go install github.com/bufbuild/buf/cmd/buf@latest
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install github.com/bufbuild/connect-go/cmd/protoc-gen-connect-go@latest go install github.com/bufbuild/connect-go/cmd/protoc-gen-connect-go@latest
generate: generate:
templ generate
buf generate proto buf generate proto
format: format:
+1
View File
@@ -3,6 +3,7 @@ module github.com/jsiebens/ionscale
go 1.21 go 1.21
require ( require (
github.com/a-h/templ v0.2.543
github.com/apparentlymart/go-cidr v1.1.0 github.com/apparentlymart/go-cidr v1.1.0
github.com/bufbuild/connect-go v1.10.0 github.com/bufbuild/connect-go v1.10.0
github.com/caarlos0/env/v6 v6.10.1 github.com/caarlos0/env/v6 v6.10.1
+2
View File
@@ -203,6 +203,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/a-h/templ v0.2.543 h1:8YyLvyUtf0/IE2nIwZ62Z/m2o2NqwhnMynzOL78Lzbk=
github.com/a-h/templ v0.2.543/go.mod h1:jP908DQCwI08IrnTalhzSEH9WJqG/Q94+EODQcJGFUA=
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+12 -32
View File
@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/jsiebens/ionscale/internal/addr" "github.com/jsiebens/ionscale/internal/addr"
"github.com/jsiebens/ionscale/internal/auth" "github.com/jsiebens/ionscale/internal/auth"
tpl "github.com/jsiebens/ionscale/internal/templates"
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
"github.com/mr-tron/base58" "github.com/mr-tron/base58"
"net/http" "net/http"
@@ -40,11 +41,6 @@ type AuthenticationHandlers struct {
systemIAMPolicy *domain.IAMPolicy systemIAMPolicy *domain.IAMPolicy
} }
type AuthFormData struct {
ProviderAvailable bool
Csrf string
}
type AuthInput struct { type AuthInput struct {
Key string `param:"key"` Key string `param:"key"`
Flow AuthFlow `param:"flow"` Flow AuthFlow `param:"flow"`
@@ -60,13 +56,6 @@ type EndAuthForm struct {
State string `form:"state"` State string `form:"state"`
} }
type TailnetSelectionData struct {
AccountID uint64
Tailnets []domain.Tailnet
SystemAdmin bool
Csrf string
}
type oauthState struct { type oauthState struct {
Key string Key string
Flow AuthFlow Flow AuthFlow
@@ -104,7 +93,7 @@ func (h *AuthenticationHandlers) StartAuth(c echo.Context) error {
} }
csrf := c.Get(middleware.DefaultCSRFConfig.ContextKey).(string) csrf := c.Get(middleware.DefaultCSRFConfig.ContextKey).(string)
return c.Render(http.StatusOK, "auth.html", &AuthFormData{ProviderAvailable: h.authProvider != nil, Csrf: csrf}) return c.Render(http.StatusOK, "", tpl.Auth(h.authProvider != nil, csrf))
} }
// cli auth flow // cli auth flow
@@ -245,12 +234,7 @@ func (h *AuthenticationHandlers) Callback(c echo.Context) error {
return h.endMachineRegistrationFlow(c, EndAuthForm{AccountID: account.ID, TailnetID: tailnets[0].ID}, req) return h.endMachineRegistrationFlow(c, EndAuthForm{AccountID: account.ID, TailnetID: tailnets[0].ID}, req)
} }
return c.Render(http.StatusOK, "tailnets.html", &TailnetSelectionData{ return c.Render(http.StatusOK, "", tpl.Tailnets(account.ID, false, tailnets, csrf))
Csrf: csrf,
Tailnets: tailnets,
SystemAdmin: false,
AccountID: account.ID,
})
} }
if state.Flow == AuthFlowClient { if state.Flow == AuthFlowClient {
@@ -267,12 +251,8 @@ func (h *AuthenticationHandlers) Callback(c echo.Context) error {
} }
return c.Redirect(http.StatusFound, "/a/error?e=ua") return c.Redirect(http.StatusFound, "/a/error?e=ua")
} }
return c.Render(http.StatusOK, "tailnets.html", &TailnetSelectionData{
Csrf: csrf, return c.Render(http.StatusOK, "", tpl.Tailnets(account.ID, isSystemAdmin, tailnets, csrf))
Tailnets: tailnets,
SystemAdmin: isSystemAdmin,
AccountID: account.ID,
})
} }
return echo.NewHTTPError(http.StatusNotFound) return echo.NewHTTPError(http.StatusNotFound)
@@ -316,24 +296,24 @@ func (h *AuthenticationHandlers) Success(c echo.Context) error {
s := c.QueryParam("s") s := c.QueryParam("s")
switch s { switch s {
case "nma": case "nma":
return c.Render(http.StatusOK, "newmachine.html", nil) return c.Render(http.StatusOK, "", tpl.NewMachine())
} }
return c.Render(http.StatusOK, "success.html", nil) return c.Render(http.StatusOK, "", tpl.Success())
} }
func (h *AuthenticationHandlers) Error(c echo.Context) error { func (h *AuthenticationHandlers) Error(c echo.Context) error {
e := c.QueryParam("e") e := c.QueryParam("e")
switch e { switch e {
case "iak": case "iak":
return c.Render(http.StatusForbidden, "invalidauthkey.html", nil) return c.Render(http.StatusForbidden, "", tpl.InvalidAuthKey())
case "ua": case "ua":
return c.Render(http.StatusForbidden, "unauthorized.html", nil) return c.Render(http.StatusForbidden, "", tpl.Unauthorized())
case "nto": case "nto":
return c.Render(http.StatusForbidden, "notagowner.html", nil) return c.Render(http.StatusForbidden, "", tpl.NotTagOwner())
case "nmo": case "nmo":
return c.Render(http.StatusForbidden, "notmachineowner.html", nil) return c.Render(http.StatusForbidden, "", tpl.NotMachineOwner())
} }
return c.Render(http.StatusOK, "error.html", nil) return c.Render(http.StatusOK, "", tpl.Error())
} }
func (h *AuthenticationHandlers) endCliAuthenticationFlow(c echo.Context, form EndAuthForm, req *domain.AuthenticationRequest) error { func (h *AuthenticationHandlers) endCliAuthenticationFlow(c echo.Context, form EndAuthForm, req *domain.AuthenticationRequest) error {
+2 -6
View File
@@ -1,17 +1,13 @@
package handlers package handlers
import ( import (
tpl "github.com/jsiebens/ionscale/internal/templates"
"github.com/jsiebens/ionscale/internal/version" "github.com/jsiebens/ionscale/internal/version"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
func IndexHandler(code int) echo.HandlerFunc { func IndexHandler(code int) echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
info, s := version.GetReleaseInfo() return c.Render(code, "", tpl.Index(version.GetReleaseInfo()))
data := map[string]interface{}{
"Version": info,
"Revision": s,
}
return c.Render(code, "index.html", data)
} }
} }
+1 -1
View File
@@ -147,7 +147,7 @@ func Start(c *config.Config) error {
nonTlsAppHandler.Any("/*", handlers.HttpRedirectHandler(c.Tls)) nonTlsAppHandler.Any("/*", handlers.HttpRedirectHandler(c.Tls))
tlsAppHandler := echo.New() tlsAppHandler := echo.New()
tlsAppHandler.Renderer = templates.NewTemplates() tlsAppHandler.Renderer = &templates.Renderer{}
tlsAppHandler.Pre(handlers.HttpsRedirect(c.Tls)) tlsAppHandler.Pre(handlers.HttpsRedirect(c.Tls))
tlsAppHandler.Use(EchoMetrics(p), EchoLogger(logger), EchoErrorHandler(), EchoRecover()) tlsAppHandler.Use(EchoMetrics(p), EchoLogger(logger), EchoErrorHandler(), EchoRecover())
-107
View File
@@ -1,107 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList {
padding-top: 5px
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
input {
display: block;
width: 100%;
height: 100%;
padding: 10px;
}
button {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
height: 45px;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
{{if .ProviderAvailable}}
<div style="text-align: left; padding-bottom: 10px">
<p><b>Authentication required</b></p>
<small>Login with:</small>
</div>
<form method="post">
<input type="hidden" name="_csrf" value="{{.Csrf}}">
<ul class="selectionList">
<li><button type="submit" name="oidc" value="true">OpenID</button></li>
</ul>
</form>
<div style="text-align: left; padding-bottom: 10px; padding-top: 20px">
<small>Or enter an <label for="ak">auth key</label> here:</small>
</div>
{{end}}
{{if not .ProviderAvailable}}
<div style="text-align: left; padding-bottom: 10px">
<p><b>Authentication required</b></p>
<small>Enter an <label for="ak">auth key</label> here:</small>
</div>
{{end}}
<form method="post" style="text-align: right">
<input type="hidden" name="_csrf" value="{{.Csrf}}">
<p><input id="ak" name="ak" type="text"/></p>
<div style="padding-top: 10px">
<button type="submit">submit</button>
</div>
</form>
</div>
</body>
</html>
+32
View File
@@ -0,0 +1,32 @@
package templates
templ Auth(oidc bool, csrf string) {
if oidc {
<div style="text-align: left; padding-bottom: 10px">
<p><b>Authentication required</b></p>
<small>Login with:</small>
</div>
<form method="post">
<input type="hidden" name="_csrf" value={ csrf } />
<ul class="selectionList">
<li><button type="submit" name="oidc" value="true">OpenID</button></li>
</ul>
</form>
<div style="text-align: left; padding-bottom: 10px; padding-top: 20px">
<small>Or enter an <label for="ak">auth key</label> here:</small>
</div>
} else {
<div style="text-align: left; padding-bottom: 10px">
<p><b>Authentication required</b></p>
<small>Enter an <label for="ak">auth key</label> here:</small>
</div>
}
<form method="post" style="text-align: right">
<input type="hidden" name="_csrf" value={ csrf } />
<p><input id="ak" name="ak" type="text"/></p>
<div style="padding-top: 10px">
<button type="submit">submit</button>
</div>
</form>
}
+62
View File
@@ -0,0 +1,62 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.543
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
func Auth(oidc bool, csrf string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if oidc {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: left; padding-bottom: 10px\"><p><b>Authentication required</b></p><small>Login with:</small></div><form method=\"post\"><input type=\"hidden\" name=\"_csrf\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(csrf))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><ul class=\"selectionList\"><li><button type=\"submit\" name=\"oidc\" value=\"true\">OpenID</button></li></ul></form><div style=\"text-align: left; padding-bottom: 10px; padding-top: 20px\"><small>Or enter an <label for=\"ak\">auth key</label> here:</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: left; padding-bottom: 10px\"><p><b>Authentication required</b></p><small>Enter an <label for=\"ak\">auth key</label> here:</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form method=\"post\" style=\"text-align: right\"><input type=\"hidden\" name=\"_csrf\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(csrf))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><p><input id=\"ak\" name=\"ak\" type=\"text\"></p><div style=\"padding-top: 10px\"><button type=\"submit\">submit</button></div></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
-96
View File
@@ -1,96 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList {
padding-top: 5px
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
input {
display: block;
width: 100%;
height: 100%;
padding: 10px;
}
button {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
height: 45px;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
{{if .ProviderAvailable}}
<div style="text-align: left; padding-bottom: 10px">
<p><b>Authentication required</b></p>
<small>Login with:</small>
</div>
<form method="post">
<ul class="selectionList">
<li><button type="submit" name="s" value="true">OpenID</button></li>
</ul>
</form>
{{end}}
{{if not .ProviderAvailable}}
<div style="text-align: center">
<p><b>No authentication method available.</b></p>
<small>contact your ionscale administrator for more information</small>
</div>
{{end}}
</div>
</body>
</html>
-62
View File
@@ -1,62 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>An error occurred</b></p>
</div>
</div>
</body>
</html>
-64
View File
@@ -1,64 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>ionscale</b></p>
<p><small>{{.Version}}</small></p>
<p><small>{{.Revision}}</small></p>
</div>
</div>
</body>
</html>
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authorization failed</b></p>
<small>the provided auth key is <b style="color: red">invalid</b></small>
</div>
</div>
</body>
</html>
+124
View File
@@ -0,0 +1,124 @@
package templates
templ Index(version string, revision string) {
<div style="text-align: center">
<p><b>ionscale</b></p>
<p><small>{ version }</small></p>
<p><small>{ revision }</small></p>
</div>
}
templ Success() {
<div style="text-align: center">
<p><b>Authorization successful</b></p>
<small>You can now close this window</small>
</div>
}
templ NewMachine() {
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but this is a <b style="color: blue">new machine</b> and needs to be authorized by your Tailnet admin.</small>
</div>
}
templ Error() {
<div style="text-align: center">
<p><b>An error occurred</b></p>
</div>
}
templ Unauthorized() {
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> authorized to use any network</small>
</div>
}
templ InvalidAuthKey() {
<div style="text-align: center">
<p><b>Authorization failed</b></p>
<small>the provided auth key is <b style="color: red">invalid</b></small>
</div>
}
templ NotTagOwner() {
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> a valid tag owner for the requested tags</small>
</div>
}
templ NotMachineOwner() {
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> a valid owner of the machine</small>
</div>
}
templ layout(contents templ.Component) {
<!DOCTYPE html>
<html lang="en">
<head>
@heading()
</head>
<body>
<div class="wrapper">
@contents
</div>
</body>
</html>
}
templ heading() {
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
}
+293
View File
@@ -0,0 +1,293 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.543
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
func Index(version string, revision string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>ionscale</b></p><p><small>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/layout.templ`, Line: 5, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</small></p><p><small>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(revision)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/layout.templ`, Line: 6, Col: 28}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</small></p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func Success() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
if templ_7745c5c3_Var4 == nil {
templ_7745c5c3_Var4 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>Authorization successful</b></p><small>You can now close this window</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func NewMachine() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
if templ_7745c5c3_Var5 == nil {
templ_7745c5c3_Var5 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>Authentication successful</b></p><small>but this is a <b style=\"color: blue\">new machine</b> and needs to be authorized by your Tailnet admin.</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func Error() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
if templ_7745c5c3_Var6 == nil {
templ_7745c5c3_Var6 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>An error occurred</b></p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func Unauthorized() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
if templ_7745c5c3_Var7 == nil {
templ_7745c5c3_Var7 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>Authentication successful</b></p><small>but you're <b style=\"color: red\">not</b> authorized to use any network</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func InvalidAuthKey() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
if templ_7745c5c3_Var8 == nil {
templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>Authorization failed</b></p><small>the provided auth key is <b style=\"color: red\">invalid</b></small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func NotTagOwner() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
if templ_7745c5c3_Var9 == nil {
templ_7745c5c3_Var9 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>Authentication successful</b></p><small>but you're <b style=\"color: red\">not</b> a valid tag owner for the requested tags</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func NotMachineOwner() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
if templ_7745c5c3_Var10 == nil {
templ_7745c5c3_Var10 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: center\"><p><b>Authentication successful</b></p><small>but you're <b style=\"color: red\">not</b> a valid owner of the machine</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func layout(contents templ.Component) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
if templ_7745c5c3_Var11 == nil {
templ_7745c5c3_Var11 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html lang=\"en\"><head>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = heading().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</head><body><div class=\"wrapper\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = contents.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
func heading() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var12 := templ.GetChildren(ctx)
if templ_7745c5c3_Var12 == nil {
templ_7745c5c3_Var12 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>\n @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');\n\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n font-family: 'Poppins', sans-serif;\n }\n\n body {\n width: 100%;\n height: 100vh;\n padding: 10px;\n background: #379683;\n }\n\n .wrapper {\n background: #fff;\n max-width: 400px;\n width: 100%;\n margin: 120px auto;\n padding: 25px;\n border-radius: 5px;\n box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);\n }\n\n .selectionList li {\n position: relative;\n list-style: none;\n height: 45px;\n line-height: 45px;\n margin-bottom: 8px;\n background: #f2f2f2;\n border-radius: 3px;\n overflow: hidden;\n box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);\n }\n\n .selectionList li button {\n margin: 0;\n display: block;\n width: 100%;\n height: 100%;\n border: none;\n }\n </style><title>ionscale</title>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but this is a <b style="color: blue">new machine</b> and needs to be authorized by your Tailnet admin.</small>
</div>
</div>
</body>
</html>
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> a valid tag owner for the requested tags</small>
</div>
</div>
</body>
</html>
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> a valid owner of the machine</small>
</div>
</div>
</body>
</html>
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authorization successful</b></p>
<small>You can now close this window</small>
</div>
</div>
</body>
</html>
-114
View File
@@ -1,114 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList {
padding-top: 5px
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
input {
display: block;
width: 100%;
height: 100%;
padding: 10px;
}
button {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
height: 45px;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
{{if .SystemAdmin}}
<div style="text-align: left; padding-bottom: 10px">
<p><b>System Admin</b></p>
<small>You are a member of the System Admin group:</small>
</div>
<form method="post">
<input type="hidden" name="aid" value="{{.AccountID}}">
<input type="hidden" name="_csrf" value="{{.Csrf}}">
<ul class="selectionList">
<li><button type="submit" name="sad" value="true">OK, continue as System Admin</button></li>
</ul>
</form>
{{end}}
{{if .Tailnets}}
{{if .SystemAdmin}}
<div style="text-align: left; padding-bottom: 10px; padding-top: 20px">
<small>Or select your <b>tailnet</b>:</small>
</div>
{{end}}
{{if not .SystemAdmin}}
<div style="text-align: left; padding-bottom: 10px;">
<p><b>Tailnets</b></p>
<small>Select your tailnet:</small>
</div>
{{end}}
<form method="post">
<input type="hidden" name="aid" value="{{.AccountID}}">
<input type="hidden" name="_csrf" value="{{.Csrf}}">
<ul class="selectionList">
{{range .Tailnets}}
<li><button type="submit" name="tid" value="{{.ID}}">{{.Name}}</button></li>
{{end}}
</ul>
</form>
{{end}}
</div>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
package templates
import "strconv"
import "github.com/jsiebens/ionscale/internal/domain"
templ Tailnets(accountID uint64, isSystemAdmin bool, tailnets []domain.Tailnet, csrf string) {
if isSystemAdmin {
<div style="text-align: left; padding-bottom: 10px">
<p><b>System Admin</b></p>
<small>You are a member of the System Admin group:</small>
</div>
<form method="post">
<input type="hidden" name="aid" value={ strconv.FormatUint(accountID, 10) } />
<input type="hidden" name="_csrf" value={ csrf } />
<ul class="selectionList">
<li><button type="submit" name="sad" value="true">OK, continue as System Admin</button></li>
</ul>
</form>
}
if len(tailnets) != 0 {
if isSystemAdmin {
<div style="text-align: left; padding-bottom: 10px; padding-top: 20px">
<small>Or select your <b>tailnet</b>:</small>
</div>
} else {
<div style="text-align: left; padding-bottom: 10px;">
<p><b>Tailnets</b></p>
<small>Select your tailnet:</small>
</div>
}
<form method="post">
<input type="hidden" name="aid" value={ strconv.FormatUint(accountID, 10) }/>
<input type="hidden" name="_csrf" value={ csrf }/>
<ul class="selectionList">
for _, t := range tailnets {
<li><button type="submit" name="tid" value={ strconv.FormatUint(t.ID, 10) }>{ t.Name }</button></li>
}
</ul>
</form>
}
}
+120
View File
@@ -0,0 +1,120 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.543
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
import "strconv"
import "github.com/jsiebens/ionscale/internal/domain"
func Tailnets(accountID uint64, isSystemAdmin bool, tailnets []domain.Tailnet, csrf string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if isSystemAdmin {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: left; padding-bottom: 10px\"><p><b>System Admin</b></p><small>You are a member of the System Admin group:</small></div><form method=\"post\"><input type=\"hidden\" name=\"aid\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(strconv.FormatUint(accountID, 10)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"_csrf\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(csrf))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><ul class=\"selectionList\"><li><button type=\"submit\" name=\"sad\" value=\"true\">OK, continue as System Admin</button></li></ul></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if len(tailnets) != 0 {
if isSystemAdmin {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: left; padding-bottom: 10px; padding-top: 20px\"><small>Or select your <b>tailnet</b>:</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div style=\"text-align: left; padding-bottom: 10px;\"><p><b>Tailnets</b></p><small>Select your tailnet:</small></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <form method=\"post\"><input type=\"hidden\" name=\"aid\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(strconv.FormatUint(accountID, 10)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"_csrf\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(csrf))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><ul class=\"selectionList\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, t := range tailnets {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><button type=\"submit\" name=\"tid\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(strconv.FormatUint(t.ID, 10)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(t.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/tailnets.templ`, Line: 37, Col: 100}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button></li>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}
+8 -12
View File
@@ -1,23 +1,19 @@
package templates package templates
import ( import (
"embed" "fmt"
"github.com/a-h/templ"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"html/template"
"io" "io"
) )
//go:embed *.html type Renderer struct {
var fs embed.FS
func NewTemplates() *Template {
return &Template{templates: template.Must(template.ParseFS(fs, "*.html"))}
} }
type Template struct { func (t *Renderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
templates *template.Template if x, ok := data.(templ.Component); ok {
} return layout(x).Render(c.Request().Context(), w)
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { return fmt.Errorf("invalid data")
return t.templates.ExecuteTemplate(w, name, data)
} }
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> authorized to use any network</small>
</div>
</div>
</body>
</html>