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 - - -
-
-

An error occurred

-
-
- - \ 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() { +
+

An error occurred

+
+} + +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("

An error occurred

") + 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