feat(webui): bootstrap state version page

This commit is contained in:
Julien Dessaux 2025-01-28 00:30:30 +01:00
parent 26e10a9399
commit 21c8d6601a
Signed by: adyxax
GPG key ID: F92E51B86E07177E
4 changed files with 101 additions and 0 deletions

View file

@ -1,12 +1,44 @@
package database package database
import ( import (
"database/sql"
"errors"
"fmt" "fmt"
"time" "time"
"git.adyxax.org/adyxax/tfstated/pkg/model" "git.adyxax.org/adyxax/tfstated/pkg/model"
) )
func (db *DB) LoadVersionById(id int) (*model.Version, error) {
version := model.Version{
Id: id,
}
var (
created int64
encryptedData []byte
)
err := db.QueryRow(
`SELECT account_id, state_id, data, lock, created FROM versions WHERE id = ?;`,
id).Scan(
&version.AccountId,
&version.StateId,
&encryptedData,
&version.Lock,
&created)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, fmt.Errorf("failed to load version id %d from database: %w", id, err)
}
version.Created = time.Unix(created, 0)
version.Data, err = db.dataEncryptionKey.DecryptAES256(encryptedData)
if err != nil {
return nil, fmt.Errorf("failed to decrypt version %d data: %w", id, err)
}
return &version, nil
}
func (db *DB) LoadVersionsByState(state *model.State) ([]model.Version, error) { func (db *DB) LoadVersionsByState(state *model.State) ([]model.Version, error) {
rows, err := db.Query( rows, err := db.Query(
`SELECT account_id, created, data, id, lock `SELECT account_id, created, data, id, lock

View file

@ -0,0 +1,10 @@
{{ define "main" }}
<main class="responsive" id="main">
<p>
Created by
<a href="/users/{{ .Account.Id }}">{{ .Account.Username }}</a>
at {{ .Version.Created }}
</p>
<pre>{{ .VersionData }}</pre>
</main>
{{ end }}

View file

@ -19,5 +19,6 @@ func addRoutes(
mux.Handle("GET /states", requireLogin(handleStatesGET(db))) mux.Handle("GET /states", requireLogin(handleStatesGET(db)))
mux.Handle("GET /state/{id}", requireLogin(handleStateGET(db))) mux.Handle("GET /state/{id}", requireLogin(handleStateGET(db)))
mux.Handle("GET /static/", cache(http.FileServer(http.FS(staticFS)))) mux.Handle("GET /static/", cache(http.FileServer(http.FS(staticFS))))
mux.Handle("GET /version/{id}", requireLogin(handleVersionGET(db)))
mux.Handle("GET /", requireLogin(handleIndexGET())) mux.Handle("GET /", requireLogin(handleIndexGET()))
} }

58
pkg/webui/version.go Normal file
View file

@ -0,0 +1,58 @@
package webui
import (
"fmt"
"html/template"
"net/http"
"strconv"
"git.adyxax.org/adyxax/tfstated/pkg/database"
"git.adyxax.org/adyxax/tfstated/pkg/model"
)
var versionTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/version.html"))
func handleVersionGET(db *database.DB) http.Handler {
type VersionsData struct {
Page
Account *model.Account
State *model.State
Version *model.Version
VersionData string
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
versionIdStr := r.PathValue("id")
versionId, err := strconv.Atoi(versionIdStr)
if err != nil {
errorResponse(w, http.StatusBadRequest, err)
return
}
version, err := db.LoadVersionById(versionId)
if err != nil {
errorResponse(w, http.StatusInternalServerError, err)
return
}
state, err := db.LoadStateById(version.StateId)
if err != nil {
errorResponse(w, http.StatusInternalServerError, err)
return
}
account, err := db.LoadAccountById(version.AccountId)
if err != nil {
errorResponse(w, http.StatusInternalServerError, err)
return
}
versionData := string(version.Data[:])
render(w, versionTemplate, http.StatusOK, VersionsData{
Page: Page{
Precedent: fmt.Sprintf("/state/%d", state.Id),
Section: "versions",
Title: state.Path,
},
Account: account,
State: state,
Version: version,
VersionData: versionData,
})
})
}