diff options
author | Julien Dessaux | 2025-01-28 00:30:30 +0100 |
---|---|---|
committer | Julien Dessaux | 2025-01-28 00:30:30 +0100 |
commit | 21c8d6601a274262074e39845be24d8020d2e5aa (patch) | |
tree | cad793b4984574c0763e148fb2ac6008a11951a6 /pkg | |
parent | feat(webui): implement state versions list (diff) | |
download | tfstated-21c8d6601a274262074e39845be24d8020d2e5aa.tar.gz tfstated-21c8d6601a274262074e39845be24d8020d2e5aa.tar.bz2 tfstated-21c8d6601a274262074e39845be24d8020d2e5aa.zip |
feat(webui): bootstrap state version page
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/database/versions.go | 32 | ||||
-rw-r--r-- | pkg/webui/html/version.html | 10 | ||||
-rw-r--r-- | pkg/webui/routes.go | 1 | ||||
-rw-r--r-- | pkg/webui/version.go | 58 |
4 files changed, 101 insertions, 0 deletions
diff --git a/pkg/database/versions.go b/pkg/database/versions.go index 5a6f11f..f05d230 100644 --- a/pkg/database/versions.go +++ b/pkg/database/versions.go @@ -1,12 +1,44 @@ package database import ( + "database/sql" + "errors" "fmt" "time" "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) { rows, err := db.Query( `SELECT account_id, created, data, id, lock 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" }} +<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 }} diff --git a/pkg/webui/routes.go b/pkg/webui/routes.go index 4330630..84017dd 100644 --- a/pkg/webui/routes.go +++ b/pkg/webui/routes.go @@ -19,5 +19,6 @@ func addRoutes( mux.Handle("GET /states", requireLogin(handleStatesGET(db))) mux.Handle("GET /state/{id}", requireLogin(handleStateGET(db))) mux.Handle("GET /static/", cache(http.FileServer(http.FS(staticFS)))) + mux.Handle("GET /version/{id}", requireLogin(handleVersionGET(db))) mux.Handle("GET /", requireLogin(handleIndexGET())) } diff --git a/pkg/webui/version.go b/pkg/webui/version.go new file mode 100644 index 0000000..04c3e6d --- /dev/null +++ b/pkg/webui/version.go @@ -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, + }) + }) +} |