diff --git a/Makefile b/Makefile
index a8beb31..68beb39 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,12 @@
init:
+ go install github.com/a-h/templ/cmd/templ@latest
go install github.com/bufbuild/buf/cmd/buf@latest
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@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
generate:
+ templ generate
buf generate proto
format:
diff --git a/go.mod b/go.mod
index 603da3d..b53f95b 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/jsiebens/ionscale
go 1.21
require (
+ github.com/a-h/templ v0.2.543
github.com/apparentlymart/go-cidr v1.1.0
github.com/bufbuild/connect-go v1.10.0
github.com/caarlos0/env/v6 v6.10.1
diff --git a/go.sum b/go.sum
index 06b037d..9778b79 100644
--- a/go.sum
+++ b/go.sum
@@ -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/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
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.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
diff --git a/internal/handlers/authentication.go b/internal/handlers/authentication.go
index 1fad01a..3f8bf79 100644
--- a/internal/handlers/authentication.go
+++ b/internal/handlers/authentication.go
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/jsiebens/ionscale/internal/addr"
"github.com/jsiebens/ionscale/internal/auth"
+ tpl "github.com/jsiebens/ionscale/internal/templates"
"github.com/labstack/echo/v4/middleware"
"github.com/mr-tron/base58"
"net/http"
@@ -40,11 +41,6 @@ type AuthenticationHandlers struct {
systemIAMPolicy *domain.IAMPolicy
}
-type AuthFormData struct {
- ProviderAvailable bool
- Csrf string
-}
-
type AuthInput struct {
Key string `param:"key"`
Flow AuthFlow `param:"flow"`
@@ -60,13 +56,6 @@ type EndAuthForm struct {
State string `form:"state"`
}
-type TailnetSelectionData struct {
- AccountID uint64
- Tailnets []domain.Tailnet
- SystemAdmin bool
- Csrf string
-}
-
type oauthState struct {
Key string
Flow AuthFlow
@@ -104,7 +93,7 @@ func (h *AuthenticationHandlers) StartAuth(c echo.Context) error {
}
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
@@ -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 c.Render(http.StatusOK, "tailnets.html", &TailnetSelectionData{
- Csrf: csrf,
- Tailnets: tailnets,
- SystemAdmin: false,
- AccountID: account.ID,
- })
+ return c.Render(http.StatusOK, "", tpl.Tailnets(account.ID, false, tailnets, csrf))
}
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.Render(http.StatusOK, "tailnets.html", &TailnetSelectionData{
- Csrf: csrf,
- Tailnets: tailnets,
- SystemAdmin: isSystemAdmin,
- AccountID: account.ID,
- })
+
+ return c.Render(http.StatusOK, "", tpl.Tailnets(account.ID, isSystemAdmin, tailnets, csrf))
}
return echo.NewHTTPError(http.StatusNotFound)
@@ -316,24 +296,24 @@ func (h *AuthenticationHandlers) Success(c echo.Context) error {
s := c.QueryParam("s")
switch s {
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 {
e := c.QueryParam("e")
switch e {
case "iak":
- return c.Render(http.StatusForbidden, "invalidauthkey.html", nil)
+ return c.Render(http.StatusForbidden, "", tpl.InvalidAuthKey())
case "ua":
- return c.Render(http.StatusForbidden, "unauthorized.html", nil)
+ return c.Render(http.StatusForbidden, "", tpl.Unauthorized())
case "nto":
- return c.Render(http.StatusForbidden, "notagowner.html", nil)
+ return c.Render(http.StatusForbidden, "", tpl.NotTagOwner())
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 {
diff --git a/internal/handlers/index.go b/internal/handlers/index.go
index 67298b3..0b0fc97 100644
--- a/internal/handlers/index.go
+++ b/internal/handlers/index.go
@@ -1,17 +1,13 @@
package handlers
import (
+ tpl "github.com/jsiebens/ionscale/internal/templates"
"github.com/jsiebens/ionscale/internal/version"
"github.com/labstack/echo/v4"
)
func IndexHandler(code int) echo.HandlerFunc {
return func(c echo.Context) error {
- info, s := version.GetReleaseInfo()
- data := map[string]interface{}{
- "Version": info,
- "Revision": s,
- }
- return c.Render(code, "index.html", data)
+ return c.Render(code, "", tpl.Index(version.GetReleaseInfo()))
}
}
diff --git a/internal/server/server.go b/internal/server/server.go
index e126fba..7968295 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -147,7 +147,7 @@ func Start(c *config.Config) error {
nonTlsAppHandler.Any("/*", handlers.HttpRedirectHandler(c.Tls))
tlsAppHandler := echo.New()
- tlsAppHandler.Renderer = templates.NewTemplates()
+ tlsAppHandler.Renderer = &templates.Renderer{}
tlsAppHandler.Pre(handlers.HttpsRedirect(c.Tls))
tlsAppHandler.Use(EchoMetrics(p), EchoLogger(logger), EchoErrorHandler(), EchoRecover())
diff --git a/internal/templates/auth.html b/internal/templates/auth.html
deleted file mode 100644
index 40263bf..0000000
--- a/internal/templates/auth.html
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
- {{if .ProviderAvailable}}
-
-
Authentication required
-
Login with:
-
-
-
- Or enter an here:
-
- {{end}}
- {{if not .ProviderAvailable}}
-
-
Authentication required
-
Enter an here:
-
- {{end}}
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/auth.templ b/internal/templates/auth.templ
new file mode 100644
index 0000000..a180ff3
--- /dev/null
+++ b/internal/templates/auth.templ
@@ -0,0 +1,32 @@
+package templates
+
+templ Auth(oidc bool, csrf string) {
+ if oidc {
+
+
Authentication required
+
Login with:
+
+
+
+ Or enter an here:
+
+ } else {
+
+
Authentication required
+
Enter an here:
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/internal/templates/auth_templ.go b/internal/templates/auth_templ.go
new file mode 100644
index 0000000..958c41b
--- /dev/null
+++ b/internal/templates/auth_templ.go
@@ -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("Authentication required
Login with:Or enter an here:
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Authentication required
Enter an here: ")
+ 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
+ }
+ if !templ_7745c5c3_IsBuffer {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
+ }
+ return templ_7745c5c3_Err
+ })
+}
diff --git a/internal/templates/cli_auth.html b/internal/templates/cli_auth.html
deleted file mode 100644
index 0b4631f..0000000
--- a/internal/templates/cli_auth.html
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
- {{if .ProviderAvailable}}
-
-
Authentication required
-
Login with:
-
-
- {{end}}
- {{if not .ProviderAvailable}}
-
-
No authentication method available.
-
contact your ionscale administrator for more information
-
- {{end}}
-
-
-
\ No newline at end of file
diff --git a/internal/templates/error.html b/internal/templates/error.html
deleted file mode 100644
index 503a399..0000000
--- a/internal/templates/error.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/index.html b/internal/templates/index.html
deleted file mode 100644
index 5e4d776..0000000
--- a/internal/templates/index.html
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
ionscale
-
{{.Version}}
-
{{.Revision}}
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/invalidauthkey.html b/internal/templates/invalidauthkey.html
deleted file mode 100644
index 9e7ea81..0000000
--- a/internal/templates/invalidauthkey.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
Authorization failed
-
the provided auth key is invalid
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/layout.templ b/internal/templates/layout.templ
new file mode 100644
index 0000000..7110134
--- /dev/null
+++ b/internal/templates/layout.templ
@@ -0,0 +1,124 @@
+package templates
+
+templ Index(version string, revision string) {
+
+
ionscale
+
{ version }
+
{ revision }
+
+}
+
+templ Success() {
+
+
Authorization successful
+
You can now close this window
+
+}
+
+templ NewMachine() {
+
+
Authentication successful
+
but this is a new machine and needs to be authorized by your Tailnet admin.
+
+}
+
+templ Error() {
+
+}
+
+templ Unauthorized() {
+
+
Authentication successful
+
but you're not authorized to use any network
+
+}
+
+templ InvalidAuthKey() {
+
+
Authorization failed
+
the provided auth key is invalid
+
+}
+
+templ NotTagOwner() {
+
+
Authentication successful
+
but you're not a valid tag owner for the requested tags
+
+}
+
+templ NotMachineOwner() {
+
+
Authentication successful
+
but you're not a valid owner of the machine
+
+}
+
+templ layout(contents templ.Component) {
+
+
+
+ @heading()
+
+
+
+ @contents
+
+
+
+}
+
+templ heading() {
+
+
+
+ ionscale
+}
diff --git a/internal/templates/layout_templ.go b/internal/templates/layout_templ.go
new file mode 100644
index 0000000..49224ea
--- /dev/null
+++ b/internal/templates/layout_templ.go
@@ -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("ionscale
")
+ 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("
")
+ 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("
")
+ 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("Authorization successful
You can now close this window ")
+ 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("Authentication successful
but this is a new machine and needs to be authorized by your Tailnet admin. ")
+ 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("")
+ 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("Authentication successful
but you're not authorized to use any network ")
+ 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("Authorization failed
the provided auth key is invalid ")
+ 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("Authentication successful
but you're not a valid tag owner for the requested tags ")
+ 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("Authentication successful
but you're not a valid owner of the machine ")
+ 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("")
+ 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("")
+ 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("
")
+ 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("ionscale")
+ 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
+ })
+}
diff --git a/internal/templates/newmachine.html b/internal/templates/newmachine.html
deleted file mode 100644
index 7b1d298..0000000
--- a/internal/templates/newmachine.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
Authentication successful
-
but this is a new machine and needs to be authorized by your Tailnet admin.
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/notagowner.html b/internal/templates/notagowner.html
deleted file mode 100644
index f2834ec..0000000
--- a/internal/templates/notagowner.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
Authentication successful
-
but you're not a valid tag owner for the requested tags
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/notmachineowner.html b/internal/templates/notmachineowner.html
deleted file mode 100644
index c91691f..0000000
--- a/internal/templates/notmachineowner.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
Authentication successful
-
but you're not a valid owner of the machine
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/success.html b/internal/templates/success.html
deleted file mode 100644
index da79281..0000000
--- a/internal/templates/success.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
Authorization successful
-
You can now close this window
-
-
-
-
\ No newline at end of file
diff --git a/internal/templates/tailnets.html b/internal/templates/tailnets.html
deleted file mode 100644
index f734e34..0000000
--- a/internal/templates/tailnets.html
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
- {{if .SystemAdmin}}
-
-
System Admin
-
You are a member of the System Admin group:
-
-
- {{end}}
- {{if .Tailnets}}
- {{if .SystemAdmin}}
-
- Or select your tailnet:
-
- {{end}}
- {{if not .SystemAdmin}}
-
-
Tailnets
-
Select your tailnet:
-
- {{end}}
-
- {{end}}
-
-
-
\ No newline at end of file
diff --git a/internal/templates/tailnets.templ b/internal/templates/tailnets.templ
new file mode 100644
index 0000000..f394878
--- /dev/null
+++ b/internal/templates/tailnets.templ
@@ -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 {
+
+
System Admin
+
You are a member of the System Admin group:
+
+
+ }
+
+ if len(tailnets) != 0 {
+ if isSystemAdmin {
+
+ Or select your tailnet:
+
+ } else {
+
+
Tailnets
+
Select your tailnet:
+
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/internal/templates/tailnets_templ.go b/internal/templates/tailnets_templ.go
new file mode 100644
index 0000000..19c260e
--- /dev/null
+++ b/internal/templates/tailnets_templ.go
@@ -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("System Admin
You are a member of the System Admin group: ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ if len(tailnets) != 0 {
+ if isSystemAdmin {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Or select your tailnet:
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Tailnets
Select your tailnet: ")
+ 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
+ }
+ }
+ if !templ_7745c5c3_IsBuffer {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
+ }
+ return templ_7745c5c3_Err
+ })
+}
diff --git a/internal/templates/templates.go b/internal/templates/templates.go
index df1c35c..6455320 100644
--- a/internal/templates/templates.go
+++ b/internal/templates/templates.go
@@ -1,23 +1,19 @@
package templates
import (
- "embed"
+ "fmt"
+ "github.com/a-h/templ"
"github.com/labstack/echo/v4"
- "html/template"
"io"
)
-//go:embed *.html
-var fs embed.FS
-
-func NewTemplates() *Template {
- return &Template{templates: template.Must(template.ParseFS(fs, "*.html"))}
+type Renderer struct {
}
-type Template struct {
- templates *template.Template
-}
+func (t *Renderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
+ 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 t.templates.ExecuteTemplate(w, name, data)
+ return fmt.Errorf("invalid data")
}
diff --git a/internal/templates/unauthorized.html b/internal/templates/unauthorized.html
deleted file mode 100644
index 62d0c2b..0000000
--- a/internal/templates/unauthorized.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
- ionscale
-
-
-
-
-
Authentication successful
-
but you're not authorized to use any network
-
-
-
-
\ No newline at end of file