-
-
- {{ if .PathDuplicate }}
-
This path already exist
- {{ else if .PathError }}
-
Invalid path
- {{ else }}
-
Valid URL path beginning with a /
+
{{ end }}
diff --git a/pkg/webui/html/version.html b/pkg/webui/html/version.html
new file mode 100644
index 0000000..b849783
--- /dev/null
+++ b/pkg/webui/html/version.html
@@ -0,0 +1,10 @@
+{{ define "main" }}
+
+
+ Created by
+ {{ .Account.Username }}
+ at {{ .Version.Created }}
+
+ {{ .VersionData }}
+
+{{ end }}
diff --git a/pkg/webui/html/versions.html b/pkg/webui/html/versions.html
deleted file mode 100644
index 8adab56..0000000
--- a/pkg/webui/html/versions.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{{ define "main" }}
-
-
- Created by
- {{ .Account.Username }}
- at {{ .Version.Created }}
-
-
-
-{{ end }}
diff --git a/pkg/webui/index.go b/pkg/webui/index.go
index 28a4964..1168098 100644
--- a/pkg/webui/index.go
+++ b/pkg/webui/index.go
@@ -8,7 +8,6 @@ import (
)
type Page struct {
- IsAdmin bool
LightMode bool
Precedent string
Section string
@@ -16,8 +15,6 @@ type Page struct {
}
func makePage(r *http.Request, page *Page) *Page {
- account := r.Context().Value(model.AccountContextKey{}).(*model.Account)
- page.IsAdmin = account.IsAdmin
settings := r.Context().Value(model.SettingsContextKey{}).(*model.Settings)
page.LightMode = settings.LightMode
return page
diff --git a/pkg/webui/routes.go b/pkg/webui/routes.go
index 2037df6..e84f33a 100644
--- a/pkg/webui/routes.go
+++ b/pkg/webui/routes.go
@@ -12,8 +12,6 @@ func addRoutes(
) {
requireSession := sessionsMiddleware(db)
requireLogin := loginMiddleware(db, requireSession)
- requireAdmin := adminMiddleware(db, requireLogin)
- mux.Handle("GET /accounts", requireAdmin(handleAccountsGET(db)))
mux.Handle("GET /healthz", handleHealthz())
mux.Handle("GET /login", requireSession(handleLoginGET()))
mux.Handle("POST /login", requireSession(handleLoginPOST(db)))
@@ -21,9 +19,8 @@ func addRoutes(
mux.Handle("GET /settings", requireLogin(handleSettingsGET(db)))
mux.Handle("POST /settings", requireLogin(handleSettingsPOST(db)))
mux.Handle("GET /states", requireLogin(handleStatesGET(db)))
- mux.Handle("POST /states", requireLogin(handleStatesPOST(db)))
- mux.Handle("GET /states/{id}", requireLogin(handleStatesIdGET(db)))
+ mux.Handle("GET /state/{id}", requireLogin(handleStateGET(db)))
mux.Handle("GET /static/", cache(http.FileServer(http.FS(staticFS))))
- mux.Handle("GET /versions/{id}", requireLogin(handleVersionsGET(db)))
+ mux.Handle("GET /version/{id}", requireLogin(handleVersionGET(db)))
mux.Handle("GET /", requireLogin(handleIndexGET()))
}
diff --git a/pkg/webui/state.go b/pkg/webui/state.go
new file mode 100644
index 0000000..141d2d8
--- /dev/null
+++ b/pkg/webui/state.go
@@ -0,0 +1,54 @@
+package webui
+
+import (
+ "html/template"
+ "net/http"
+ "strconv"
+
+ "git.adyxax.org/adyxax/tfstated/pkg/database"
+ "git.adyxax.org/adyxax/tfstated/pkg/model"
+)
+
+var stateTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/state.html"))
+
+func handleStateGET(db *database.DB) http.Handler {
+ type StatesData struct {
+ Page *Page
+ State *model.State
+ Usernames map[int]string
+ Versions []model.Version
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ stateIdStr := r.PathValue("id")
+ stateId, err := strconv.Atoi(stateIdStr)
+ if err != nil {
+ errorResponse(w, http.StatusBadRequest, err)
+ return
+ }
+ state, err := db.LoadStateById(stateId)
+ if err != nil {
+ errorResponse(w, http.StatusInternalServerError, err)
+ return
+ }
+ versions, err := db.LoadVersionsByState(state)
+ if err != nil {
+ errorResponse(w, http.StatusInternalServerError, err)
+ return
+ }
+ usernames, err := db.LoadAccountUsernames()
+ if err != nil {
+ errorResponse(w, http.StatusInternalServerError, err)
+ return
+ }
+ render(w, stateTemplate, http.StatusOK, StatesData{
+ Page: makePage(r, &Page{
+ Precedent: "/states",
+ Section: "states",
+ Title: state.Path,
+ }),
+ State: state,
+ Usernames: usernames,
+ Versions: versions,
+ })
+ })
+}
diff --git a/pkg/webui/states.go b/pkg/webui/states.go
index 64b7967..a0d16ca 100644
--- a/pkg/webui/states.go
+++ b/pkg/webui/states.go
@@ -1,135 +1,29 @@
package webui
import (
- "fmt"
"html/template"
- "io"
"net/http"
- "net/url"
- "path"
"git.adyxax.org/adyxax/tfstated/pkg/database"
"git.adyxax.org/adyxax/tfstated/pkg/model"
- "go.n16f.net/uuid"
)
-type StatesPage struct {
- ActiveTab int
- Page *Page
- Path string
- PathError bool
- PathDuplicate bool
- States []model.State
-}
-
var statesTemplates = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/states.html"))
-var statesIdTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/statesId.html"))
func handleStatesGET(db *database.DB) http.Handler {
+ type StatesData struct {
+ Page *Page
+ States []model.State
+ }
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
states, err := db.LoadStates()
if err != nil {
errorResponse(w, http.StatusInternalServerError, err)
return
}
- render(w, statesTemplates, http.StatusOK, StatesPage{
+ render(w, statesTemplates, http.StatusOK, StatesData{
Page: makePage(r, &Page{Title: "States", Section: "states"}),
States: states,
})
})
}
-
-func handleStatesPOST(db *database.DB) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // file upload limit of 20MB
- if err := r.ParseMultipartForm(20 << 20); err != nil {
- errorResponse(w, http.StatusBadRequest, err)
- return
- }
- file, _, err := r.FormFile("file")
- if err != nil {
- errorResponse(w, http.StatusBadRequest, err)
- return
- }
- defer file.Close()
- statePath := r.FormValue("path")
- parsedStatePath, err := url.Parse(statePath)
- if err != nil || path.Clean(parsedStatePath.Path) != statePath || statePath[0] != '/' {
- render(w, statesTemplates, http.StatusBadRequest, StatesPage{
- ActiveTab: 1,
- Page: makePage(r, &Page{Title: "New State", Section: "states"}),
- Path: statePath,
- PathError: true,
- })
- return
- }
- data, err := io.ReadAll(file)
- if err != nil {
- errorResponse(w, http.StatusBadRequest, fmt.Errorf("failed to read uploaded file: %w", err))
- return
- }
- fileType := http.DetectContentType(data)
- if fileType != "text/plain; charset=utf-8" {
- errorResponse(w, http.StatusBadRequest, fmt.Errorf("invalid file type: expected \"text/plain; charset=utf-8\" but got \"%s\"", fileType))
- return
- }
- account := r.Context().Value(model.AccountContextKey{}).(*model.Account)
- version, err := db.CreateState(statePath, account.Id, data)
- if err != nil {
- errorResponse(w, http.StatusInternalServerError, err)
- return
- }
- if version == nil {
- render(w, statesTemplates, http.StatusBadRequest, StatesPage{
- ActiveTab: 1,
- Page: makePage(r, &Page{Title: "New State", Section: "states"}),
- Path: statePath,
- PathDuplicate: true,
- })
- return
- }
- destination := path.Join("/versions", version.Id.String())
- http.Redirect(w, r, destination, http.StatusFound)
- })
-}
-
-func handleStatesIdGET(db *database.DB) http.Handler {
- type StatesData struct {
- Page *Page
- State *model.State
- Usernames map[string]string
- Versions []model.Version
- }
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- var stateId uuid.UUID
- if err := stateId.Parse(r.PathValue("id")); err != nil {
- errorResponse(w, http.StatusBadRequest, err)
- return
- }
- state, err := db.LoadStateById(stateId)
- if err != nil {
- errorResponse(w, http.StatusInternalServerError, err)
- return
- }
- versions, err := db.LoadVersionsByState(state)
- if err != nil {
- errorResponse(w, http.StatusInternalServerError, err)
- return
- }
- usernames, err := db.LoadAccountUsernames()
- if err != nil {
- errorResponse(w, http.StatusInternalServerError, err)
- return
- }
- render(w, statesIdTemplate, http.StatusOK, StatesData{
- Page: makePage(r, &Page{
- Precedent: "/states",
- Section: "states",
- Title: state.Path,
- }),
- State: state,
- Usernames: usernames,
- Versions: versions,
- })
- })
-}
diff --git a/pkg/webui/versions.go b/pkg/webui/version.go
similarity index 70%
rename from pkg/webui/versions.go
rename to pkg/webui/version.go
index 8cb0a8b..2aa1422 100644
--- a/pkg/webui/versions.go
+++ b/pkg/webui/version.go
@@ -1,18 +1,18 @@
package webui
import (
+ "fmt"
"html/template"
"net/http"
- "path"
+ "strconv"
"git.adyxax.org/adyxax/tfstated/pkg/database"
"git.adyxax.org/adyxax/tfstated/pkg/model"
- "go.n16f.net/uuid"
)
-var versionsTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/versions.html"))
+var versionTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/version.html"))
-func handleVersionsGET(db *database.DB) http.Handler {
+func handleVersionGET(db *database.DB) http.Handler {
type VersionsData struct {
Page *Page
Account *model.Account
@@ -21,8 +21,9 @@ func handleVersionsGET(db *database.DB) http.Handler {
VersionData string
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- var versionId uuid.UUID
- if err := versionId.Parse(r.PathValue("id")); err != nil {
+ versionIdStr := r.PathValue("id")
+ versionId, err := strconv.Atoi(versionIdStr)
+ if err != nil {
errorResponse(w, http.StatusBadRequest, err)
return
}
@@ -31,10 +32,6 @@ func handleVersionsGET(db *database.DB) http.Handler {
errorResponse(w, http.StatusInternalServerError, err)
return
}
- if version == nil {
- errorResponse(w, http.StatusNotFound, err)
- return
- }
state, err := db.LoadStateById(version.StateId)
if err != nil {
errorResponse(w, http.StatusInternalServerError, err)
@@ -46,9 +43,9 @@ func handleVersionsGET(db *database.DB) http.Handler {
return
}
versionData := string(version.Data[:])
- render(w, versionsTemplate, http.StatusOK, VersionsData{
+ render(w, versionTemplate, http.StatusOK, VersionsData{
Page: makePage(r, &Page{
- Precedent: path.Join("/states/", state.Id.String()),
+ Precedent: fmt.Sprintf("/state/%d", state.Id),
Section: "states",
Title: state.Path,
}),