Upgraded to the latest go-web-kit.

This commit is contained in:
Zed A. Shaw 2025-11-03 14:09:57 -05:00
parent 051474bdc9
commit 41f31a621f
14 changed files with 124 additions and 142 deletions

2
.gitignore vendored
View file

@ -31,3 +31,5 @@ config.toml
public public
*.idx *.idx
*.sqlite3 *.sqlite3
static/videos
media

13
.ssgod.json Normal file
View file

@ -0,0 +1,13 @@
{
"views": "pages",
"layout": "views/layouts/main.html",
"target": "public",
"watch_delay": "500ms",
"sync_dir": "static",
"exclude": [
"pages/layouts/.*"
],
"meta_files": [
"pages/sitemap.html"
]
}

View file

@ -9,6 +9,7 @@ import (
) )
func SearchTable(search string, table string, the_type reflect.Type, limit uint64, page uint64) ([]any, error) { func SearchTable(search string, table string, the_type reflect.Type, limit uint64, page uint64) ([]any, error) {
var results []any var results []any
like := fmt.Sprint("%", search, "%") like := fmt.Sprint("%", search, "%")
@ -132,6 +133,7 @@ func Update(table string, value reflect.Value) error {
builder = builder.Where(sq.Eq{"id": value.FieldByName("Id").Interface()}) builder = builder.Where(sq.Eq{"id": value.FieldByName("Id").Interface()})
sql_query, args, err := builder.ToSql() sql_query, args, err := builder.ToSql()
fmt.Println("UPDATE QUERY", sql_query, args)
if err != nil { return err} if err != nil { return err}
_, err = data.DB.Exec(sql_query, args...) _, err = data.DB.Exec(sql_query, args...)

View file

@ -6,12 +6,12 @@ import (
"fmt" "fmt"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"MY/webapp/data" "MY/webapp/data"
"MY/webapp/api"
. "MY/webapp/common" . "MY/webapp/common"
"MY/webapp/auth"
) )
func GetApiTableIndex(c *fiber.Ctx) error { func GetApiTableIndex(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
var tables []string var tables []string
@ -24,7 +24,7 @@ func GetApiTableIndex(c *fiber.Ctx) error {
} }
func GetApiSelectAll(c *fiber.Ctx) error { func GetApiSelectAll(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -50,14 +50,14 @@ func GetApiSelectAll(c *fiber.Ctx) error {
} }
func GetPageSelectAll(c *fiber.Ctx) error { func GetPageSelectAll(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
return c.Render("admin/table/contents", fiber.Map{"Table": c.Params("table")}) return c.Render("admin/table/contents", fiber.Map{"Table": c.Params("table")})
} }
func GetApiSelectOne(c *fiber.Ctx) error { func GetApiSelectOne(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -73,7 +73,7 @@ func GetApiSelectOne(c *fiber.Ctx) error {
} }
func GetPageSelectOne(c *fiber.Ctx) error { func GetPageSelectOne(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -87,7 +87,7 @@ func GetPageSelectOne(c *fiber.Ctx) error {
} }
func PostApiUpdate(c *fiber.Ctx) error { func PostApiUpdate(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -102,7 +102,7 @@ func PostApiUpdate(c *fiber.Ctx) error {
} }
func GetPageInsert(c *fiber.Ctx) error { func GetPageInsert(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -110,7 +110,7 @@ func GetPageInsert(c *fiber.Ctx) error {
} }
func GetApiInsert(c *fiber.Ctx) error { func GetApiInsert(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -120,7 +120,7 @@ func GetApiInsert(c *fiber.Ctx) error {
} }
func PostApiInsert(c *fiber.Ctx) error { func PostApiInsert(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -136,7 +136,7 @@ func PostApiInsert(c *fiber.Ctx) error {
} }
func DeleteApi(c *fiber.Ctx) error { func DeleteApi(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
table := c.Params("table") table := c.Params("table")
@ -151,7 +151,7 @@ func DeleteApi(c *fiber.Ctx) error {
} }
func GetPageAdminIndex(c *fiber.Ctx) error { func GetPageAdminIndex(c *fiber.Ctx) error {
_, err := api.CheckAuthed(c, true) _, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") } if err != nil { return c.Redirect("/") }
return c.Render("admin/table/index", fiber.Map{}) return c.Render("admin/table/index", fiber.Map{})

View file

@ -11,11 +11,9 @@ import (
"MY/webapp/data" "MY/webapp/data"
. "MY/webapp/common" . "MY/webapp/common"
"MY/webapp/auth"
) )
var STORE *session.Store
func GetApiStream(c *fiber.Ctx) error { func GetApiStream(c *fiber.Ctx) error {
sql, args, err := sq.Select("*").From("stream").ToSql() sql, args, err := sq.Select("*").From("stream").ToSql()
err = data.SelectJson[data.Stream](c, err, sql, args...) err = data.SelectJson[data.Stream](c, err, sql, args...)
@ -45,7 +43,7 @@ func PostApiLink(c *fiber.Ctx) error {
var sql string var sql string
var args []interface{} var args []interface{}
_, err := CheckAuthed(c, false) _, err := auth.Check(c, false)
if err != nil { return c.Redirect("/login/") } if err != nil { return c.Redirect("/login/") }
link, err := ReceivePost[data.Link](c) link, err := ReceivePost[data.Link](c)
@ -95,12 +93,6 @@ func Setup(app *fiber.App) {
app.Get("/api/stream/:id", GetApiStreamId) app.Get("/api/stream/:id", GetApiStreamId)
app.Get("/api/stream/:id/links", GetApiStreamIdLinks) app.Get("/api/stream/:id/links", GetApiStreamIdLinks)
app.Post("/api/link", PostApiLink) app.Post("/api/link", PostApiLink)
// api/auth.go
app.Get("/api/authcheck", GetApiAuthCheck)
app.Get("/api/logout", GetApiLogout)
app.Post("/api/register", PostApiRegister)
app.Post("/api/login", PostApiLogin)
} }
func Shutdown() { func Shutdown() {

73
auth/handlers.go Normal file
View file

@ -0,0 +1,73 @@
package auth
import (
"github.com/gofiber/fiber/v2"
_ "github.com/mattn/go-sqlite3"
sq "github.com/Masterminds/squirrel"
"MY/webapp/data"
. "MY/webapp/common"
)
func GetApiAuthCheck(c *fiber.Ctx) error {
_, err := Check(c, false)
// auth failure or not authed is determined by err, with nil meaning YES AUTHED
return c.JSON(fiber.Map{"is_authed": err == nil})
}
func GetApiLogout(c *fiber.Ctx) error {
err := LogoutUser(c)
if err != nil { return IfErrNil(err, c) }
return c.Redirect("/")
}
func PostApiRegister(c *fiber.Ctx) error {
user, err := ReceivePost[data.User](c)
if err != nil { return IfErrNil(err, c) }
err = SetUserPassword(user)
if err != nil { return IfErrNil(err, c) }
sql, args, err := sq.Insert("user").
Columns("username", "email", "password").
Values(user.Username, user.Email, user.Password).ToSql()
_, err = data.Exec(err, sql, args...)
if err != nil { return IfErrNil(err, c) }
return c.Redirect("/login/")
}
func PostApiLogin(c *fiber.Ctx) error {
var user data.User
login, err := ReceivePost[data.Login](c)
if(err != nil) { return IfErrNil(err, c) }
pass_good, err := LoginUser(&user, login)
if err != nil { return IfErrNil(err, c) }
if pass_good {
sess, err := STORE.Get(c)
if err != nil { return IfErrNil(err, c) }
sess.Set("user_id", user.Id)
sess.Set("authenticated", true)
sess.Set("admin", IsAdmin(&user))
err = sess.Save()
if err != nil { return IfErrNil(err, c) }
return c.Redirect("/")
} else {
return c.Redirect("/login/")
}
}
func Setup(app *fiber.App) {
app.Get("/api/authcheck", GetApiAuthCheck)
app.Get("/api/logout", GetApiLogout)
app.Post("/api/register", PostApiRegister)
app.Post("/api/login", PostApiLogin)
}

View file

@ -1,4 +1,4 @@
package api package auth
import ( import (
"errors" "errors"
@ -12,79 +12,21 @@ import (
"MY/webapp/data" "MY/webapp/data"
"MY/webapp/config" "MY/webapp/config"
. "MY/webapp/common" "MY/webapp/common"
) )
func GetApiAuthCheck(c *fiber.Ctx) error {
_, err := CheckAuthed(c, false)
// auth failure or not authed is determined by err, with nil meaning YES AUTHED
return c.JSON(fiber.Map{"is_authed": err == nil})
}
func GetApiLogout(c *fiber.Ctx) error {
err := LogoutUser(c)
if err != nil { return IfErrNil(err, c) }
return c.Redirect("/")
}
func PostApiRegister(c *fiber.Ctx) error {
user, err := ReceivePost[data.User](c)
if err != nil { return IfErrNil(err, c) }
err = SetUserPassword(user)
if err != nil { return IfErrNil(err, c) }
sql, args, err := sq.Insert("user").
Columns("username", "email", "password").
Values(user.Username, user.Email, user.Password).ToSql()
_, err = data.Exec(err, sql, args...)
if err != nil { return IfErrNil(err, c) }
return c.Redirect("/login/")
}
func PostApiLogin(c *fiber.Ctx) error {
var user data.User
login, err := ReceivePost[data.Login](c)
if(err != nil) { return IfErrNil(err, c) }
pass_good, err := LoginUser(&user, login)
if err != nil { return IfErrNil(err, c) }
if pass_good {
sess, err := STORE.Get(c)
if err != nil { return IfErrNil(err, c) }
sess.Set("user_id", user.Id)
sess.Set("authenticated", true)
sess.Set("admin", IsAdmin(&user))
err = sess.Save()
if err != nil { return IfErrNil(err, c) }
return c.Redirect("/")
} else {
return c.Redirect("/login/")
}
}
func IsAdmin(user *data.User) bool { func IsAdmin(user *data.User) bool {
return user.Username == config.Settings.Admin return user.Username == config.Settings.Admin
} }
func CheckAuthed(c *fiber.Ctx, needs_admin bool) (*session.Session, error) { func Check(c *fiber.Ctx, needs_admin bool) (*session.Session, error) {
sess, err := STORE.Get(c) sess, err := common.STORE.Get(c)
if err != nil { return sess, err } if err != nil { return sess, err }
// BUG: this has to come from the databse, just temporary // BUG: this has to come from the databse, just temporary
admin := sess.Get("admin") == true admin := sess.Get("admin") == true
authed := sess.Get("authenticated") == true authed := sess.Get("authenticated") == true
log.Printf("session admin=%v, session authed=%v, needs_admin = %v",
sess.Get("admin"), sess.Get("authenticated"), needs_admin)
if needs_admin { if needs_admin {
authed = admin && authed authed = admin && authed
log.Printf("after needs_admin block: authed=%v", authed) log.Printf("after needs_admin block: authed=%v", authed)
@ -100,7 +42,7 @@ func CheckAuthed(c *fiber.Ctx, needs_admin bool) (*session.Session, error) {
} }
func LogoutUser(c *fiber.Ctx) error { func LogoutUser(c *fiber.Ctx) error {
sess, err := STORE.Get(c) sess, err := common.STORE.Get(c)
if err != nil { return err } if err != nil { return err }
err = sess.Destroy() err = sess.Destroy()

View file

@ -3,8 +3,11 @@ package common
import ( import (
"strings" "strings"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/session"
) )
var STORE *session.Store
func Page(path string) (func(c *fiber.Ctx) error) { func Page(path string) (func(c *fiber.Ctx) error) {
page_id := strings.ReplaceAll(path, "/", "-") + "-page" page_id := strings.ReplaceAll(path, "/", "-") + "-page"

2
go.mod
View file

@ -55,7 +55,7 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
lcthw.dev/go/ozai v0.1.0 // indirect lcthw.dev/go/ozai v0.1.0 // indirect
lcthw.dev/go/ssgod v0.1.0 // indirect lcthw.dev/go/ssgod v0.2.2 // indirect
) )
tool ( tool (

8
go.sum
View file

@ -123,11 +123,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lcthw.dev/go/ozai v0.0.0-20250914152405-53a1959fe44e h1:EAbBnwzBlusAOOs/Cq6QXbhhmMxaO7bsilKk6mU8oIc=
lcthw.dev/go/ozai v0.0.0-20250914152405-53a1959fe44e/go.mod h1:AwxRrUAb/KtUzSWgKmhv/eBg6ZjJ4tVZ9YA/DlKqtWs=
lcthw.dev/go/ozai v0.1.0 h1:LNuLMZV4m+ciHRjf1atcunR/63Jguvz3puEzD5vmFec= lcthw.dev/go/ozai v0.1.0 h1:LNuLMZV4m+ciHRjf1atcunR/63Jguvz3puEzD5vmFec=
lcthw.dev/go/ozai v0.1.0/go.mod h1:AwxRrUAb/KtUzSWgKmhv/eBg6ZjJ4tVZ9YA/DlKqtWs= lcthw.dev/go/ozai v0.1.0/go.mod h1:AwxRrUAb/KtUzSWgKmhv/eBg6ZjJ4tVZ9YA/DlKqtWs=
lcthw.dev/go/ssgod v0.0.0-20250910143122-4457e9bad2af h1:PN/XR1qhfxTn32AGOdQgyBPJs0qqnWVLcPxE5IUENgM= lcthw.dev/go/ssgod v0.2.2 h1:lvzhxOXDka9iejIQj7Db7ePjruBqYvqe7A5zzxsdank=
lcthw.dev/go/ssgod v0.0.0-20250910143122-4457e9bad2af/go.mod h1:c0cAznS0qaDUOIGU8nKODfuFLwemEi/KGDCf8guTleA= lcthw.dev/go/ssgod v0.2.2/go.mod h1:fCe4J/00a3T4pURfpUp6LZlkUeh5eHDpjApvy6HHiPk=
lcthw.dev/go/ssgod v0.1.0 h1:b1YkIc7hEgUen8zF85ZRG5YCyCeFAvx1KtmNFp1OuMg=
lcthw.dev/go/ssgod v0.1.0/go.mod h1:c0cAznS0qaDUOIGU8nKODfuFLwemEi/KGDCf8guTleA=

9
pages/sitemap.html Normal file
View file

@ -0,0 +1,9 @@
<h1>Site Map</h1>
<ul>
{{range $index, $page := .Pages}}
<li><a href="{{$page}}">{{$page}}</a></li>
{{ else }}
Nothing Here
{{end}}
</ul>

View file

@ -1,5 +0,0 @@
views = "pages"
layout = "views/layouts/main.html"
target = "public"
watch_delay = "500ms"
sync_dir = "static"

View file

@ -1,4 +0,0 @@
views = "pages/copy"
layout = "pages/layouts/copy.html"
target = "public"
watch_delay = "500ms"

View file

@ -247,9 +247,6 @@
.flex { .flex {
display: flex; display: flex;
} }
.grid {
display: grid;
}
.hidden { .hidden {
display: none; display: none;
} }
@ -314,21 +311,12 @@
.flex-1 { .flex-1 {
flex: 1; flex: 1;
} }
.flex-shrink {
flex-shrink: 1;
}
.shrink-0 { .shrink-0 {
flex-shrink: 0; flex-shrink: 0;
} }
.border-collapse {
border-collapse: collapse;
}
.transform { .transform {
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
} }
.resize {
resize: both;
}
.two-panel { .two-panel {
grid-template-columns: repeat(1, minmax(0, 1fr)); grid-template-columns: repeat(1, minmax(0, 1fr));
grid-template-rows: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr));
@ -366,9 +354,6 @@
.justify-evenly { .justify-evenly {
justify-content: space-evenly; justify-content: space-evenly;
} }
.gap-0 {
gap: calc(var(--spacing) * 0);
}
.gap-0\! { .gap-0\! {
gap: calc(var(--spacing) * 0) !important; gap: calc(var(--spacing) * 0) !important;
} }
@ -432,10 +417,6 @@
border-width: 1px !important; border-width: 1px !important;
border-color: var(--color-red-900) !important; border-color: var(--color-red-900) !important;
} }
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-1 { .border-1 {
border-style: var(--tw-border-style); border-style: var(--tw-border-style);
border-width: 1px; border-width: 1px;
@ -506,9 +487,6 @@
.bg-gray-800 { .bg-gray-800 {
background-color: var(--color-gray-800); background-color: var(--color-gray-800);
} }
.bg-green-400 {
background-color: var(--color-green-400);
}
.bg-green-400\! { .bg-green-400\! {
background-color: var(--color-green-400) !important; background-color: var(--color-green-400) !important;
} }
@ -521,9 +499,6 @@
.\!p-4 { .\!p-4 {
padding: calc(var(--spacing) * 4) !important; padding: calc(var(--spacing) * 4) !important;
} }
.p-0 {
padding: calc(var(--spacing) * 0);
}
.p-0\! { .p-0\! {
padding: calc(var(--spacing) * 0) !important; padding: calc(var(--spacing) * 0) !important;
} }
@ -551,9 +526,6 @@
.\!pb-20 { .\!pb-20 {
padding-bottom: calc(var(--spacing) * 20) !important; padding-bottom: calc(var(--spacing) * 20) !important;
} }
.pb-0 {
padding-bottom: calc(var(--spacing) * 0);
}
.pb-0\! { .pb-0\! {
padding-bottom: calc(var(--spacing) * 0) !important; padding-bottom: calc(var(--spacing) * 0) !important;
} }
@ -572,9 +544,6 @@
.pb-8 { .pb-8 {
padding-bottom: calc(var(--spacing) * 8); padding-bottom: calc(var(--spacing) * 8);
} }
.pb-10 {
padding-bottom: calc(var(--spacing) * 10);
}
.pb-10\! { .pb-10\! {
padding-bottom: calc(var(--spacing) * 10) !important; padding-bottom: calc(var(--spacing) * 10) !important;
} }
@ -623,9 +592,6 @@
--tw-font-weight: var(--font-weight-light); --tw-font-weight: var(--font-weight-light);
font-weight: var(--font-weight-light); font-weight: var(--font-weight-light);
} }
.text-wrap {
text-wrap: wrap;
}
.text-gray-50 { .text-gray-50 {
color: var(--color-gray-50); color: var(--color-gray-50);
} }
@ -644,17 +610,10 @@
.text-red-500 { .text-red-500 {
color: var(--color-red-500); color: var(--color-red-500);
} }
.underline {
text-decoration-line: underline;
}
.shadow-lg { .shadow-lg {
--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
} }
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.transition { .transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events; transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));