diff --git a/.air.toml b/.air.toml
index d8c5605..b155769 100644
--- a/.air.toml
+++ b/.air.toml
@@ -3,7 +3,9 @@ testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
-args_bin = []
+args_bin = [
+ "-no-auth"
+]
bin = "./build/hugo-cms"
cmd = "make compile"
delay = 1000
@@ -12,7 +14,7 @@ exclude_file = []
exclude_regex = ["_test.go", "build/.*"]
exclude_unchanged = false
follow_symlink = false
-full_bin = "export $(cat .env | xargs) ; make prep-dev init-db ; cd build ; ./hugo-cms"
+full_bin = "export $(cat .env | xargs) ; cd build ; ./hugo-cms"
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "gohtml", "css", "js"]
include_file = []
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 5e97acb..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM golang:1.23.3 AS builder
-
-WORKDIR /usr/src/app
-
-COPY go.mod go.sum ./
-RUN go mod download && go mod verify
-
-COPY . .
-RUN make compile
-
-
-FROM scratch
-
-COPY --from=builder /usr/src/app/build/ /.
-COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
-
-WORKDIR /
-
-ENV DATA_DIR=/data
-ENV PORT=3000
-
-CMD ["/hugo-cms"]
\ No newline at end of file
diff --git a/Makefile b/Makefile
index c7f2386..ced17bd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,13 @@
.Phony: clean
clean:
-docker-compose down -v
- -rm -rf build
+ -rm -r build
.Phony: prep
prep:
+ -docker-compose up -d
mkdir -p build
.Phony: compile
compile: prep
- CGO_ENABLED=0 go build -o ./build/hugo-cms
-
-.Phony: prep-dev
-prep-dev:
- docker-compose up -d
-
-.Phony: init-db
-init-db:
- go run . -user test@example.com -password test123
\ No newline at end of file
+ go build -o ./build/hugo-cms
\ No newline at end of file
diff --git a/assets/css/main.css b/assets/css/main.css
index 8fd49e2..143bbbe 100644
--- a/assets/css/main.css
+++ b/assets/css/main.css
@@ -40,11 +40,6 @@ body.role-site main {
}
-div.post {
- border-bottom: solid thin grey;
-}
-
-
form.post-form {
display: flex;
diff --git a/config/config.go b/config/config.go
index e7bd671..1eecf8c 100644
--- a/config/config.go
+++ b/config/config.go
@@ -6,13 +6,11 @@ import (
)
type Config struct {
- DatabaseURL string `env:"DATABASE_URL"`
- NetlifyAuthToken string `env:"NETLIFY_AUTH_TOKEN"`
- DataDir string `env:"DATA_DIR"`
- EncryptedCookieKey string `env:"ENCRYPTED_COOKIE_KEY"`
-
- DataStagingDir string `env:"DATA_STAGING_DIR,default=staging"`
- DataScratchDir string `env:"DATA_SCRATCH_DIR,default=scratch"`
+ DatabaseURL string `env:"DATABASE_URL"`
+ NetlifyAuthToken string `env:"NETLIFY_AUTH_TOKEN"`
+ DataDir string `env:"DATA_DIR"`
+ DataStagingDir string `env:"DATA_STAGING_DIR,default=staging"`
+ DataScratchDir string `env:"DATA_SCRATCH_DIR,default=scratch"`
}
func Load() (cfg Config, err error) {
diff --git a/gen/sqlc/dbq/models.go b/gen/sqlc/dbq/models.go
index d4052a2..b723142 100644
--- a/gen/sqlc/dbq/models.go
+++ b/gen/sqlc/dbq/models.go
@@ -156,16 +156,10 @@ type PublishTarget struct {
}
type Site struct {
- ID int64
- OwnerUserID int64
- Name string
- Title string
- Theme string
- Props []byte
-}
-
-type User struct {
- ID int64
- Email string
- Password string
+ ID int64
+ Name string
+ Title string
+ Url string
+ Theme string
+ Props []byte
}
diff --git a/gen/sqlc/dbq/posts.sql.go b/gen/sqlc/dbq/posts.sql.go
index 6724a64..de5a4b3 100644
--- a/gen/sqlc/dbq/posts.sql.go
+++ b/gen/sqlc/dbq/posts.sql.go
@@ -11,17 +11,8 @@ import (
"github.com/jackc/pgx/v5/pgtype"
)
-const deletePost = `-- name: DeletePost :exec
-DELETE FROM posts WHERE id = $1
-`
-
-func (q *Queries) DeletePost(ctx context.Context, id int64) error {
- _, err := q.db.Exec(ctx, deletePost, id)
- return err
-}
-
const getPostWithID = `-- name: GetPostWithID :one
-SELECT id, site_id, title, body, state, props, post_date, created_at FROM posts WHERE id = $1 LIMIT 1
+SELECT id, site_id, title, body, state, props, post_date, created_at FROM post WHERE id = $1 LIMIT 1
`
func (q *Queries) GetPostWithID(ctx context.Context, id int64) (Post, error) {
@@ -41,7 +32,7 @@ func (q *Queries) GetPostWithID(ctx context.Context, id int64) (Post, error) {
}
const insertPost = `-- name: InsertPost :one
-INSERT INTO posts (
+INSERT INTO post (
site_id,
title,
body,
@@ -79,7 +70,7 @@ func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (int64,
}
const listPosts = `-- name: ListPosts :many
-SELECT id, site_id, title, body, state, props, post_date, created_at FROM posts WHERE site_id = $1 ORDER BY post_date DESC LIMIT 25
+SELECT id, site_id, title, body, state, props, post_date, created_at FROM post WHERE site_id = $1 ORDER BY post_date DESC LIMIT 25
`
func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) {
@@ -113,7 +104,7 @@ func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) {
const listPublishablePosts = `-- name: ListPublishablePosts :many
SELECT id, site_id, title, body, state, props, post_date, created_at
-FROM posts
+FROM post
WHERE id > $1 AND site_id = $2 AND state = 'published' AND post_date <= $3
ORDER BY id LIMIT 100
`
@@ -154,7 +145,7 @@ func (q *Queries) ListPublishablePosts(ctx context.Context, arg ListPublishableP
}
const updatePost = `-- name: UpdatePost :exec
-UPDATE posts SET
+UPDATE post SET
site_id = $2,
title = $3,
body = $4,
diff --git a/gen/sqlc/dbq/sites.sql.go b/gen/sqlc/dbq/sites.sql.go
index 3ba7978..3aea488 100644
--- a/gen/sqlc/dbq/sites.sql.go
+++ b/gen/sqlc/dbq/sites.sql.go
@@ -10,7 +10,7 @@ import (
)
const getSiteWithID = `-- name: GetSiteWithID :one
-SELECT id, owner_user_id, name, title, theme, props FROM sites WHERE id = $1 LIMIT 1
+SELECT id, name, title, url, theme, props FROM site WHERE id = $1 LIMIT 1
`
func (q *Queries) GetSiteWithID(ctx context.Context, id int64) (Site, error) {
@@ -18,9 +18,9 @@ func (q *Queries) GetSiteWithID(ctx context.Context, id int64) (Site, error) {
var i Site
err := row.Scan(
&i.ID,
- &i.OwnerUserID,
&i.Name,
&i.Title,
+ &i.Url,
&i.Theme,
&i.Props,
)
@@ -28,7 +28,7 @@ func (q *Queries) GetSiteWithID(ctx context.Context, id int64) (Site, error) {
}
const listSites = `-- name: ListSites :one
-SELECT id, owner_user_id, name, title, theme, props FROM sites
+SELECT id, name, title, url, theme, props FROM site
`
func (q *Queries) ListSites(ctx context.Context) (Site, error) {
@@ -36,9 +36,9 @@ func (q *Queries) ListSites(ctx context.Context) (Site, error) {
var i Site
err := row.Scan(
&i.ID,
- &i.OwnerUserID,
&i.Name,
&i.Title,
+ &i.Url,
&i.Theme,
&i.Props,
)
@@ -46,10 +46,10 @@ func (q *Queries) ListSites(ctx context.Context) (Site, error) {
}
const newSite = `-- name: NewSite :one
-INSERT INTO sites (
+INSERT INTO site (
name,
- owner_user_id,
title,
+ url,
theme,
props
) VALUES ($1, $2, $3, $4, $5)
@@ -57,18 +57,18 @@ RETURNING id
`
type NewSiteParams struct {
- Name string
- OwnerUserID int64
- Title string
- Theme string
- Props []byte
+ Name string
+ Title string
+ Url string
+ Theme string
+ Props []byte
}
func (q *Queries) NewSite(ctx context.Context, arg NewSiteParams) (int64, error) {
row := q.db.QueryRow(ctx, newSite,
arg.Name,
- arg.OwnerUserID,
arg.Title,
+ arg.Url,
arg.Theme,
arg.Props,
)
diff --git a/gen/sqlc/dbq/targets.sql.go b/gen/sqlc/dbq/targets.sql.go
index 6470e95..12712bd 100644
--- a/gen/sqlc/dbq/targets.sql.go
+++ b/gen/sqlc/dbq/targets.sql.go
@@ -9,31 +9,8 @@ import (
"context"
)
-const getTargetOfSiteRole = `-- name: GetTargetOfSiteRole :one
-SELECT id, site_id, role, target_type, url, target_ref FROM publish_targets WHERE site_id = $1 AND role = $2 LIMIT 1
-`
-
-type GetTargetOfSiteRoleParams struct {
- SiteID int64
- Role TargetRole
-}
-
-func (q *Queries) GetTargetOfSiteRole(ctx context.Context, arg GetTargetOfSiteRoleParams) (PublishTarget, error) {
- row := q.db.QueryRow(ctx, getTargetOfSiteRole, arg.SiteID, arg.Role)
- var i PublishTarget
- err := row.Scan(
- &i.ID,
- &i.SiteID,
- &i.Role,
- &i.TargetType,
- &i.Url,
- &i.TargetRef,
- )
- return i, err
-}
-
const insertPublishTarget = `-- name: InsertPublishTarget :one
-INSERT INTO publish_targets (
+INSERT INTO publish_target (
site_id,
role,
target_type,
@@ -64,12 +41,12 @@ func (q *Queries) InsertPublishTarget(ctx context.Context, arg InsertPublishTarg
return id, err
}
-const listTargetsOfSite = `-- name: ListTargetsOfSite :many
-SELECT id, site_id, role, target_type, url, target_ref FROM publish_targets WHERE site_id = $1
+const listPublishTargetsOfRole = `-- name: ListPublishTargetsOfRole :many
+SELECT id, site_id, role, target_type, url, target_ref FROM publish_target WHERE site_id = $1 AND role = 'production'
`
-func (q *Queries) ListTargetsOfSite(ctx context.Context, siteID int64) ([]PublishTarget, error) {
- rows, err := q.db.Query(ctx, listTargetsOfSite, siteID)
+func (q *Queries) ListPublishTargetsOfRole(ctx context.Context, siteID int64) ([]PublishTarget, error) {
+ rows, err := q.db.Query(ctx, listPublishTargetsOfRole, siteID)
if err != nil {
return nil, err
}
diff --git a/gen/sqlc/dbq/users.sql.go b/gen/sqlc/dbq/users.sql.go
deleted file mode 100644
index c48133a..0000000
--- a/gen/sqlc/dbq/users.sql.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Code generated by sqlc. DO NOT EDIT.
-// versions:
-// sqlc v1.28.0
-// source: users.sql
-
-package dbq
-
-import (
- "context"
-)
-
-const addUser = `-- name: AddUser :one
-INSERT INTO users (
- email,
- password
-) VALUES ($1, $2)
-ON CONFLICT (email) DO UPDATE SET password = $2
-RETURNING id
-`
-
-type AddUserParams struct {
- Email string
- Password string
-}
-
-func (q *Queries) AddUser(ctx context.Context, arg AddUserParams) (int64, error) {
- row := q.db.QueryRow(ctx, addUser, arg.Email, arg.Password)
- var id int64
- err := row.Scan(&id)
- return id, err
-}
-
-const getUserByEmail = `-- name: GetUserByEmail :one
-SELECT id, email, password FROM users WHERE email = $1 LIMIT 1
-`
-
-func (q *Queries) GetUserByEmail(ctx context.Context, email string) (User, error) {
- row := q.db.QueryRow(ctx, getUserByEmail, email)
- var i User
- err := row.Scan(&i.ID, &i.Email, &i.Password)
- return i, err
-}
-
-const getUserByID = `-- name: GetUserByID :one
-SELECT id, email, password FROM users WHERE id = $1 LIMIT 1
-`
-
-func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
- row := q.db.QueryRow(ctx, getUserByID, id)
- var i User
- err := row.Scan(&i.ID, &i.Email, &i.Password)
- return i, err
-}
diff --git a/go.mod b/go.mod
index f64997c..3eaf20e 100644
--- a/go.mod
+++ b/go.mod
@@ -10,9 +10,7 @@ require (
require (
github.com/Netflix/go-env v0.1.2 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
- github.com/coreos/go-oidc/v3 v3.12.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
- github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/gofiber/fiber/v2 v2.52.6 // indirect
github.com/gofiber/fiber/v3 v3.0.0-beta.4 // indirect
github.com/gofiber/schema v1.2.0 // indirect
@@ -20,7 +18,6 @@ require (
github.com/gofiber/template/html/v2 v2.1.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.7 // indirect
- github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -43,7 +40,6 @@ require (
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/net v0.34.0 // indirect
- golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect
diff --git a/go.sum b/go.sum
index 9d4e412..b5d4c9b 100644
--- a/go.sum
+++ b/go.sum
@@ -2,14 +2,10 @@ github.com/Netflix/go-env v0.1.2 h1:0DRoLR9lECQ9Zqvkswuebm3jJ/2enaDX6Ei8/Z+EnK0=
github.com/Netflix/go-env v0.1.2/go.mod h1:WlIhYi++8FlKNJtrop1mjXYAJMzv1f43K4MqCoh0yGE=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
-github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
-github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
-github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
-github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/fiber/v3 v3.0.0-beta.4 h1:KzDSavvhG7m81NIsmnu5l3ZDbVS4feCidl4xlIfu6V0=
@@ -24,8 +20,6 @@ github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/gofiber/utils/v2 v2.0.0-beta.7 h1:NnHFrRHvhrufPABdWajcKZejz9HnCWmT/asoxRsiEbQ=
github.com/gofiber/utils/v2 v2.0.0-beta.7/go.mod h1:J/M03s+HMdZdvhAeyh76xT72IfVqBzuz/OJkrMa7cwU=
-github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
-github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y=
github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -82,8 +76,6 @@ golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
-golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
-golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/handlers/auth.go b/handlers/auth.go
deleted file mode 100644
index 64da6c1..0000000
--- a/handlers/auth.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package handlers
-
-import (
- "encoding/json"
- "errors"
- "github.com/gofiber/fiber/v2"
- "lmika.dev/lmika/hugo-cms/models"
- "lmika.dev/lmika/hugo-cms/services/users"
- "net/http"
-)
-
-type AuthHandler struct {
- UserService *users.Service
-}
-
-func (h *AuthHandler) ShowLogin(c *fiber.Ctx) error {
- return c.Render("auth/login", fiber.Map{}, "layouts/login")
-}
-
-func (h *AuthHandler) Login(c *fiber.Ctx) error {
- var req struct {
- Email string `form:"email"`
- Password string `form:"password"`
- }
-
- if err := c.BodyParser(&req); err != nil {
- return errors.New("invalid email or password")
- }
-
- user, err := h.UserService.VerifyLogin(c.UserContext(), req.Email, req.Password)
- if err != nil {
- return errors.New("invalid email or password")
- }
-
- bts, err := json.Marshal(models.AuthCookie{UserID: user.ID})
- if err != nil {
- return err
- }
-
- c.Cookie(&fiber.Cookie{
- Name: models.AuthCookieName,
- Value: string(bts),
- })
- return c.Redirect("/", http.StatusFound)
-}
-
-func (h *AuthHandler) RequireAuth(c *fiber.Ctx) error {
- user, err := h.readAuthCookie(c)
- if err != nil {
- return c.Redirect("/auth/login", http.StatusFound)
- }
-
- c.Locals("user", user)
- return c.Next()
-}
-
-func (h *AuthHandler) readAuthCookie(c *fiber.Ctx) (user models.User, err error) {
- authData := c.Cookies(models.AuthCookieName)
- if authData == "" {
- return models.User{}, errors.New("no auth cookie")
- }
-
- var ac models.AuthCookie
- if err := json.Unmarshal([]byte(authData), &ac); err != nil {
- return models.User{}, err
- }
-
- return h.UserService.GetUserByID(c.UserContext(), ac.UserID)
-}
diff --git a/handlers/ctx.go b/handlers/ctx.go
index 9a18d63..4846d87 100644
--- a/handlers/ctx.go
+++ b/handlers/ctx.go
@@ -1,57 +1,14 @@
package handlers
import (
- "encoding/json"
- "errors"
"github.com/gofiber/fiber/v2"
"lmika.dev/lmika/hugo-cms/models"
- "log"
)
-func GetUser(c *fiber.Ctx) models.User {
- u, ok := c.Locals("user").(models.User)
- if !ok {
- panic(errors.New("user not found in context"))
- }
- return u
-}
+type siteKeyType struct{}
+
+var siteKey siteKeyType
func GetSite(c *fiber.Ctx) models.Site {
- s, ok := c.Locals("site").(models.Site)
- if !ok {
- panic(errors.New("no site in context"))
- }
- return s
-}
-
-func UpdatePrefCookie(c *fiber.Ctx, update func(prefs *models.PrefCookie)) {
- cookie := GetPrefCookie(c)
- update(&cookie)
- setPrefCookie(c, cookie)
-}
-
-func GetPrefCookie(c *fiber.Ctx) models.PrefCookie {
- prefCookieValue := c.Cookies(models.PrefCookieName)
- if prefCookieValue == "" {
- return models.PrefCookie{}
- }
-
- var prefCookie models.PrefCookie
- err := json.Unmarshal([]byte(prefCookieValue), &prefCookie)
- if err != nil {
- return models.PrefCookie{}
- }
-
- return prefCookie
-}
-
-func setPrefCookie(c *fiber.Ctx, prefCookie models.PrefCookie) {
- if prefJson, err := json.Marshal(prefCookie); err == nil {
- c.Cookie(&fiber.Cookie{
- Name: models.PrefCookieName,
- Value: string(prefJson),
- })
- } else {
- log.Printf("unable to save pref cookie: %v", err)
- }
+ return c.UserContext().Value(siteKey).(models.Site)
}
diff --git a/handlers/index.go b/handlers/index.go
deleted file mode 100644
index dfd4aad..0000000
--- a/handlers/index.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package handlers
-
-import (
- "fmt"
- "github.com/gofiber/fiber/v2"
- "net/http"
-)
-
-type IndexHandler struct {
-}
-
-func (h IndexHandler) Index(c *fiber.Ctx) error {
- prefs := GetPrefCookie(c)
- if prefs.SiteID > 0 {
- return c.Redirect(fmt.Sprintf("/sites/%v/posts", prefs.SiteID), http.StatusFound)
- }
-
- return c.Render("index", fiber.Map{}, "layouts/main")
-}
diff --git a/handlers/mimeselectors.go b/handlers/mimeselectors.go
deleted file mode 100644
index 6a47e8b..0000000
--- a/handlers/mimeselectors.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package handlers
-
-import "github.com/gofiber/fiber/v2"
-
-type mimeTypeHandler interface {
- CanHandle(c *fiber.Ctx) bool
- Handle(c *fiber.Ctx) error
-}
-
-type HTMX func(c *fiber.Ctx) error
-
-func (h HTMX) CanHandle(c *fiber.Ctx) bool {
- return c.Get("Hx-request") == "true"
-}
-
-func (h HTMX) Handle(c *fiber.Ctx) error {
- return h(c)
-}
-
-type Otherwise func(c *fiber.Ctx) error
-
-func (h Otherwise) CanHandle(c *fiber.Ctx) bool {
- return true
-}
-
-func (h Otherwise) Handle(c *fiber.Ctx) error {
- return h(c)
-}
-
-func Select(c *fiber.Ctx, mimeTypes ...mimeTypeHandler) error {
- for _, mt := range mimeTypes {
- if mt.CanHandle(c) {
- return mt.Handle(c)
- }
- }
- return c.Status(fiber.StatusInternalServerError).SendString("cant handle response")
-}
diff --git a/handlers/post.go b/handlers/post.go
index cf5bff5..62964db 100644
--- a/handlers/post.go
+++ b/handlers/post.go
@@ -5,125 +5,121 @@ import (
"github.com/gofiber/fiber/v2"
"lmika.dev/lmika/hugo-cms/models"
"lmika.dev/lmika/hugo-cms/services/posts"
- "net/http"
)
type Post struct {
Post *posts.Service
}
-func (h *Post) Posts(c *fiber.Ctx) error {
- site := GetSite(c)
+func (h *Post) Posts() fiber.Handler {
+ return func(c *fiber.Ctx) error {
+ site := GetSite(c)
- posts, err := h.Post.ListPostOfSite(c.UserContext(), site)
- if err != nil {
- return err
+ posts, err := h.Post.ListPostOfSite(c.UserContext(), site)
+ if err != nil {
+ return err
+ }
+
+ return c.Render("posts/index", fiber.Map{
+ "site": site,
+ "posts": posts,
+ }, "layouts/site")
}
-
- return c.Render("posts/index", fiber.Map{
- "posts": posts,
- }, "layouts/site")
}
-func (h *Post) New(c *fiber.Ctx) error {
- return c.Render("posts/new", fiber.Map{
- "post": models.Post{},
- }, "layouts/site")
+func (h *Post) New() fiber.Handler {
+ return func(c *fiber.Ctx) error {
+ site := GetSite(c)
+
+ return c.Render("posts/new", fiber.Map{
+ "site": site,
+ "post": models.Post{},
+ }, "layouts/site")
+ }
}
-func (h *Post) Create(c *fiber.Ctx) error {
- site := GetSite(c)
-
- var req struct {
+func (h *Post) Create() fiber.Handler {
+ type Req struct {
Title string `json:"title" form:"title"`
Body string `json:"body" form:"body"`
}
- if err := c.BodyParser(&req); err != nil {
- return err
- }
- _, err := h.Post.Create(c.UserContext(), site, posts.NewPost{
- Title: req.Title,
- Body: req.Body,
- })
- if err != nil {
- return err
- }
+ return func(c *fiber.Ctx) error {
+ site := GetSite(c)
- return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID))
+ var req Req
+ if err := c.BodyParser(&req); err != nil {
+ return err
+ }
+
+ _, err := h.Post.Create(c.UserContext(), site, posts.NewPost{
+ Title: req.Title,
+ Body: req.Body,
+ })
+ if err != nil {
+ return err
+ }
+
+ return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID))
+ }
}
-func (h *Post) Edit(c *fiber.Ctx) error {
- site := GetSite(c)
+func (h *Post) Edit() fiber.Handler {
+ return func(c *fiber.Ctx) error {
+ site := GetSite(c)
- postID, err := c.ParamsInt("postId")
- if err != nil {
- return err
+ postID, err := c.ParamsInt("postId")
+ if err != nil {
+ return err
+ }
+
+ post, err := h.Post.GetPost(c.UserContext(), postID)
+ if err != nil {
+ return err
+ } else if post.SiteID != site.ID {
+ return fmt.Errorf("post id %v not equal to site id %v", postID, site.ID)
+ }
+
+ return c.Render("posts/new", fiber.Map{
+ "site": site,
+ "post": post,
+ }, "layouts/site")
}
-
- post, err := h.Post.GetPost(c.UserContext(), postID)
- if err != nil {
- return err
- } else if post.SiteID != site.ID {
- return fmt.Errorf("post id %v not equal to site id %v", postID, site.ID)
- }
-
- return c.Render("posts/new", fiber.Map{
- "post": post,
- }, "layouts/site")
}
-func (h *Post) Update(c *fiber.Ctx) error {
- site := GetSite(c)
-
- postID, err := c.ParamsInt("postId")
- if err != nil {
- return err
- }
-
- var req struct {
+func (h *Post) Update() fiber.Handler {
+ type Req struct {
Title string `json:"title" form:"title"`
Body string `json:"body" form:"body"`
}
- if err := c.BodyParser(&req); err != nil {
- return err
+
+ return func(c *fiber.Ctx) error {
+ site := GetSite(c)
+
+ postID, err := c.ParamsInt("postId")
+ if err != nil {
+ return err
+ }
+
+ var req Req
+ if err := c.BodyParser(&req); err != nil {
+ return err
+ }
+
+ post, err := h.Post.GetPost(c.UserContext(), postID)
+ if err != nil {
+ return err
+ } else if post.SiteID != site.ID {
+ return fmt.Errorf("post id %v not equal to site id %v", postID, site.ID)
+ }
+
+ post.Title = req.Title
+ post.Body = req.Body
+
+ if err := h.Post.Save(c.UserContext(), site, &post); err != nil {
+ return err
+ }
+
+ return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID))
}
-
- post, err := h.Post.GetPost(c.UserContext(), postID)
- if err != nil {
- return err
- } else if post.SiteID != site.ID {
- return fmt.Errorf("post id %v not equal to site id %v", postID, site.ID)
- }
-
- post.Title = req.Title
- post.Body = req.Body
-
- if err := h.Post.Save(c.UserContext(), site, &post); err != nil {
- return err
- }
-
- return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID))
-}
-
-func (h *Post) Delete(c *fiber.Ctx) error {
- site := GetSite(c)
-
- postID, err := c.ParamsInt("postId")
- if err != nil {
- return err
- }
-
- if err := h.Post.DeletePost(c.UserContext(), site, postID); err != nil {
- return err
- }
-
- return Select(c,
- HTMX(func(c *fiber.Ctx) error {
- return c.Status(http.StatusOK).SendString("")
- }),
- Otherwise(func(c *fiber.Ctx) error {
- return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID), http.StatusSeeOther)
- }),
- )
}
diff --git a/handlers/site.go b/handlers/site.go
index cded58a..8a6c701 100644
--- a/handlers/site.go
+++ b/handlers/site.go
@@ -1,13 +1,10 @@
package handlers
import (
- "errors"
+ "context"
"fmt"
"github.com/gofiber/fiber/v2"
- "github.com/jackc/pgx/v5"
- "lmika.dev/lmika/hugo-cms/models"
"lmika.dev/lmika/hugo-cms/services/sites"
- "net/http"
"time"
)
@@ -15,47 +12,19 @@ type Site struct {
Site *sites.Service
}
-func (s *Site) Create(c *fiber.Ctx) error {
- user := GetUser(c)
+func (s *Site) Create() fiber.Handler {
+ return func(c *fiber.Ctx) error {
+ site, err := s.Site.CreateSite(c.UserContext(), "New Site "+time.Now().Format("2006-01-02 15:04:05"))
+ if err != nil {
+ return err
+ }
- site, err := s.Site.CreateSite(c.UserContext(), user, "New Site "+time.Now().Format("2006-01-02 15:04:05"))
- if err != nil {
- return err
+ return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID))
}
-
- UpdatePrefCookie(c, func(prefs *models.PrefCookie) {
- prefs.SiteID = site.ID
- })
-
- return c.Redirect(fmt.Sprintf("/sites/%v/posts", site.ID))
}
-func (s *Site) Show(c *fiber.Ctx) error {
- id, err := c.ParamsInt("siteId")
- if err != nil {
- return err
- }
-
- site, err := s.Site.GetSite(c.UserContext(), id)
- if err != nil {
- return err
- }
-
- return c.Render("sites/index", fiber.Map{
- "site": site,
- }, "layouts/main")
-}
-
-func (s *Site) Rebuild(c *fiber.Ctx) error {
- if err := s.Site.Rebuild(c.UserContext(), GetSite(c)); err != nil {
- return err
- }
-
- return c.Redirect(fmt.Sprintf("/sites/%v/posts", GetSite(c).ID))
-}
-
-func (s *Site) WithSite() fiber.Handler {
- return func(c *fiber.Ctx) (err error) {
+func (s *Site) Show() fiber.Handler {
+ return func(c *fiber.Ctx) error {
id, err := c.ParamsInt("siteId")
if err != nil {
return err
@@ -66,19 +35,35 @@ func (s *Site) WithSite() fiber.Handler {
return err
}
- user := GetUser(c)
- if site.OwnerUserID != user.ID {
- return c.Status(http.StatusForbidden).SendString("not permitted")
- }
+ return c.Render("sites/index", fiber.Map{
+ "site": site,
+ }, "layouts/main")
+ }
+}
- c.Locals("site", site)
-
- if prodTarget, err := s.Site.GetProdTargetOfSite(c.UserContext(), int(site.ID)); err == nil {
- c.Locals("prodTarget", prodTarget)
- } else if !errors.Is(err, pgx.ErrNoRows) {
+func (s *Site) Rebuild() fiber.Handler {
+ return func(c *fiber.Ctx) error {
+ if err := s.Site.Rebuild(c.UserContext(), GetSite(c)); err != nil {
return err
}
+ return c.Redirect(fmt.Sprintf("/sites/%v/posts", GetSite(c).ID))
+ }
+}
+
+func (s *Site) WithSite() fiber.Handler {
+ return func(c *fiber.Ctx) error {
+ id, err := c.ParamsInt("siteId")
+ if err != nil {
+ return err
+ }
+
+ site, err := s.Site.GetSite(c.UserContext(), id)
+ if err != nil {
+ return err
+ }
+
+ c.SetUserContext(context.WithValue(c.UserContext(), siteKey, site))
return c.Next()
}
}
diff --git a/main.go b/main.go
index 0badf3f..bde6e26 100644
--- a/main.go
+++ b/main.go
@@ -3,10 +3,7 @@ package main
import (
"bytes"
"context"
- "flag"
- "fmt"
"github.com/gofiber/fiber/v2"
- "github.com/gofiber/fiber/v2/middleware/encryptcookie"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/gofiber/template/html/v2"
"github.com/yuin/goldmark"
@@ -23,23 +20,12 @@ import (
"lmika.dev/lmika/hugo-cms/services/posts"
"lmika.dev/lmika/hugo-cms/services/sitebuilder"
"lmika.dev/lmika/hugo-cms/services/sites"
- "lmika.dev/lmika/hugo-cms/services/users"
"lmika.dev/lmika/hugo-cms/templates"
"log"
"net/http"
)
func main() {
- flagGenKey := flag.Bool("gen-key", false, "Generate a new key")
- flagUser := flag.String("user", "", "add new user")
- flagPassword := flag.String("password", "", "add new password")
- flag.Parse()
-
- if *flagGenKey {
- fmt.Println(encryptcookie.GenerateKey())
- return
- }
-
cfg, err := config.Load()
if err != nil {
log.Fatal(err)
@@ -51,25 +37,6 @@ func main() {
}
defer dbp.Close()
- log.Println("Connected to database")
- if err := dbp.Migrate(context.Background()); err != nil {
- log.Fatal(err)
- }
- log.Println("Database migrated")
-
- userService := users.NewService(dbp)
-
- if *flagUser != "" {
- if _, err := userService.AddUser(context.Background(), users.NewUser{
- Email: *flagUser,
- Password: *flagPassword,
- }); err != nil {
- log.Fatal(err)
- }
- log.Println("User added")
- return
- }
-
hugoProvider, err := hugo.New(cfg.StagingDir(), cfg.ScratchDir())
if err != nil {
log.Fatal(err)
@@ -84,10 +51,15 @@ func main() {
siteService := sites.NewService(cfg, dbp, themesProvider, siteBuilderService, jobService)
postService := posts.New(dbp, siteBuilderService, jobService)
- indexHandlers := handlers.IndexHandler{}
siteHandlers := handlers.Site{Site: siteService}
postHandlers := handlers.Post{Post: postService}
- authHandlers := handlers.AuthHandler{UserService: userService}
+
+ log.Println("Connected to database")
+ if err := dbp.Migrate(context.Background()); err != nil {
+ log.Fatal(err)
+ }
+
+ log.Println("Database migrated")
tmplEngine := html.NewFileSystem(http.FS(templates.FS), ".html")
tmplEngine.Funcmap["markdown"] = func(s string) (template.HTML, error) {
@@ -98,39 +70,33 @@ func main() {
return template.HTML(buf.String()), nil
}
- if cfg.EncryptedCookieKey == "" {
- log.Println("No encrypt cookie key defined. Generating random key")
- cfg.EncryptedCookieKey = encryptcookie.GenerateKey()
- }
-
app := fiber.New(fiber.Config{
- Views: tmplEngine,
- PassLocalsToViews: true,
+ Views: tmplEngine,
})
- app.Use(encryptcookie.New(encryptcookie.Config{Key: cfg.EncryptedCookieKey}))
- app.Use("/assets", filesystem.New(filesystem.Config{Root: http.FS(assets.FS)}))
+ app.Get("/", func(c *fiber.Ctx) error {
+ return c.Render("index", fiber.Map{}, "layouts/main")
+ })
- app.Get("/auth/login", authHandlers.ShowLogin)
- app.Post("/auth/login", authHandlers.Login)
- app.Use(authHandlers.RequireAuth)
-
- app.Get("/", indexHandlers.Index)
- app.Post("/sites", siteHandlers.Create)
- app.Get("/sites/:siteId", siteHandlers.Show)
+ app.Post("/sites", siteHandlers.Create())
+ app.Get("/sites/:siteId", siteHandlers.Show())
app.Route("/sites/:siteId", func(r fiber.Router) {
r.Use(siteHandlers.WithSite())
- r.Post("/rebuild", siteHandlers.Rebuild)
+ r.Post("/rebuild", siteHandlers.Rebuild())
- r.Get("/posts", postHandlers.Posts)
- r.Get("/posts/new", postHandlers.New)
- r.Post("/posts", postHandlers.Create)
- r.Get("/posts/:postId", postHandlers.Edit)
- r.Post("/posts/:postId", postHandlers.Update)
- r.Delete("/posts/:postId", postHandlers.Delete)
+ r.Get("/posts", postHandlers.Posts())
+ r.Get("/posts/:postId", postHandlers.Edit())
+ r.Get("/posts/new", postHandlers.New())
+ r.Post("/posts", postHandlers.Create())
+ r.Post("/posts/:postId", postHandlers.Update())
})
+ app.Use("/assets", filesystem.New(filesystem.Config{
+ Root: http.FS(assets.FS),
+ }))
+ app.Static("/assets", "./assets")
+
jobService.Start()
defer jobService.Stop()
diff --git a/models/cookie.go b/models/cookie.go
deleted file mode 100644
index 918a7b4..0000000
--- a/models/cookie.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package models
-
-const (
- AuthCookieName = "hugocrm_auth"
- PrefCookieName = "hugocrm_pref"
-)
-
-type AuthCookie struct {
- UserID int64 `json:"uid"`
-}
-
-type PrefCookie struct {
- SiteID int64 `json:"siteId"`
-}
diff --git a/models/posts.go b/models/posts.go
index a95fb36..104625f 100644
--- a/models/posts.go
+++ b/models/posts.go
@@ -12,7 +12,6 @@ const (
type Post struct {
ID int64
SiteID int64
- OwnerID int64
Title string
Body string
State PostState
diff --git a/models/sites.go b/models/sites.go
index 3da9fc6..9685c60 100644
--- a/models/sites.go
+++ b/models/sites.go
@@ -1,9 +1,9 @@
package models
type Site struct {
- ID int64
- OwnerUserID int64
- Name string
- Title string
- Theme string
+ ID int64
+ Name string
+ Title string
+ URL string
+ Theme string
}
diff --git a/models/user.go b/models/user.go
deleted file mode 100644
index 7d50a4f..0000000
--- a/models/user.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package models
-
-type User struct {
- ID int64
- Email string
- PasswordHash string
-}
diff --git a/providers/db/posts.go b/providers/db/posts.go
index a647453..e838c3a 100644
--- a/providers/db/posts.go
+++ b/providers/db/posts.go
@@ -27,10 +27,6 @@ func (db *DB) GetPost(ctx context.Context, postID int64) (models.Post, error) {
return dbPostToPost(res), nil
}
-func (db *DB) DeletePost(ctx context.Context, postID int64) error {
- return db.q.DeletePost(ctx, postID)
-}
-
func (db *DB) ListPublishablePosts(ctx context.Context, fromID, siteID int64, now time.Time) ([]models.Post, error) {
res, err := db.q.ListPublishablePosts(ctx, dbq.ListPublishablePostsParams{
ID: fromID,
diff --git a/providers/db/publish.go b/providers/db/publish.go
new file mode 100644
index 0000000..51f035f
--- /dev/null
+++ b/providers/db/publish.go
@@ -0,0 +1,42 @@
+package db
+
+import (
+ "context"
+ "lmika.dev/lmika/hugo-cms/gen/sqlc/dbq"
+ "lmika.dev/lmika/hugo-cms/models"
+ "lmika.dev/pkg/modash/moslice"
+)
+
+func (db *DB) InsertPublishTarget(ctx context.Context, target *models.PublishTarget) error {
+ id, err := db.q.InsertPublishTarget(ctx, dbq.InsertPublishTargetParams{
+ SiteID: target.SiteID,
+ Role: dbq.TargetRole(target.Role),
+ TargetType: dbq.TargetType(target.Type),
+ Url: target.URL,
+ TargetRef: target.TargetRef,
+ })
+ if err != nil {
+ return err
+ }
+ target.ID = id
+
+ return nil
+}
+
+func (db *DB) GetPublishTargets(ctx context.Context, siteID int64) ([]models.PublishTarget, error) {
+ res, err := db.q.ListPublishTargetsOfRole(ctx, siteID)
+ if err != nil {
+ return nil, err
+ }
+
+ return moslice.Map(res, func(m dbq.PublishTarget) models.PublishTarget {
+ return models.PublishTarget{
+ ID: m.ID,
+ SiteID: m.SiteID,
+ Role: models.TargetRole(m.Role),
+ Type: models.TargetType(m.TargetType),
+ URL: m.Url,
+ TargetRef: m.TargetRef,
+ }
+ }), nil
+}
diff --git a/providers/db/sites.go b/providers/db/sites.go
index fac59fa..8e8cc55 100644
--- a/providers/db/sites.go
+++ b/providers/db/sites.go
@@ -8,11 +8,11 @@ import (
func (db *DB) InsertSite(ctx context.Context, site *models.Site) error {
id, err := db.q.NewSite(ctx, dbq.NewSiteParams{
- Name: site.Name,
- Title: site.Title,
- OwnerUserID: site.OwnerUserID,
- Theme: site.Theme,
- Props: []byte("{}"),
+ Name: site.Name,
+ Title: site.Title,
+ Url: site.URL,
+ Theme: site.Theme,
+ Props: []byte("{}"),
})
if err != nil {
return err
@@ -28,10 +28,9 @@ func (db *DB) GetSite(ctx context.Context, id int64) (models.Site, error) {
}
return models.Site{
- ID: site.ID,
- OwnerUserID: site.OwnerUserID,
- Name: site.Name,
- Title: site.Title,
- Theme: site.Theme,
+ ID: site.ID,
+ Name: site.Name,
+ Title: site.Title,
+ Theme: site.Theme,
}, nil
}
diff --git a/providers/db/targets.go b/providers/db/targets.go
deleted file mode 100644
index 6f004cd..0000000
--- a/providers/db/targets.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package db
-
-import (
- "context"
- "lmika.dev/lmika/hugo-cms/gen/sqlc/dbq"
- "lmika.dev/lmika/hugo-cms/models"
- "lmika.dev/pkg/modash/moslice"
-)
-
-func (db *DB) InsertPublishTarget(ctx context.Context, target *models.PublishTarget) error {
- id, err := db.q.InsertPublishTarget(ctx, dbq.InsertPublishTargetParams{
- SiteID: target.SiteID,
- Role: dbq.TargetRole(target.Role),
- TargetType: dbq.TargetType(target.Type),
- Url: target.URL,
- TargetRef: target.TargetRef,
- })
- if err != nil {
- return err
- }
- target.ID = id
-
- return nil
-}
-
-func (db *DB) GetPublishTargets(ctx context.Context, siteID int64) ([]models.PublishTarget, error) {
- res, err := db.q.ListTargetsOfSite(ctx, siteID)
- if err != nil {
- return nil, err
- }
-
- return moslice.Map(res, dbTargetToTarget), nil
-}
-
-func (db *DB) GetPublishTargetBySiteRole(ctx context.Context, siteID int64, role models.TargetRole) (models.PublishTarget, error) {
- target, err := db.q.GetTargetOfSiteRole(ctx, dbq.GetTargetOfSiteRoleParams{
- SiteID: siteID,
- Role: dbq.TargetRole(role),
- })
- if err != nil {
- return models.PublishTarget{}, err
- }
-
- return dbTargetToTarget(target), nil
-}
-
-func dbTargetToTarget(m dbq.PublishTarget) models.PublishTarget {
- return models.PublishTarget{
- ID: m.ID,
- SiteID: m.SiteID,
- Role: models.TargetRole(m.Role),
- Type: models.TargetType(m.TargetType),
- URL: m.Url,
- TargetRef: m.TargetRef,
- }
-}
diff --git a/providers/db/user.go b/providers/db/user.go
deleted file mode 100644
index 1962ad3..0000000
--- a/providers/db/user.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package db
-
-import (
- "context"
- "lmika.dev/lmika/hugo-cms/gen/sqlc/dbq"
- "lmika.dev/lmika/hugo-cms/models"
-)
-
-func (db *DB) AddUser(ctx context.Context, user *models.User) error {
- id, err := db.q.AddUser(ctx, dbq.AddUserParams{
- Email: user.Email,
- Password: user.PasswordHash,
- })
- if err != nil {
- return err
- }
- user.ID = id
- return nil
-}
-
-func (db *DB) GetUserByID(ctx context.Context, id int64) (models.User, error) {
- res, err := db.q.GetUserByID(ctx, id)
- if err != nil {
- return models.User{}, err
- }
-
- return dbUserToUser(res), nil
-}
-
-func (db *DB) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
- res, err := db.q.GetUserByEmail(ctx, email)
- if err != nil {
- return models.User{}, err
- }
-
- return dbUserToUser(res), nil
-}
-
-func dbUserToUser(u dbq.User) models.User {
- return models.User{
- ID: u.ID,
- Email: u.Email,
- PasswordHash: u.Password,
- }
-}
diff --git a/services/posts/services.go b/services/posts/services.go
index 902c14c..ce3cd5a 100644
--- a/services/posts/services.go
+++ b/services/posts/services.go
@@ -40,19 +40,6 @@ func (s *Service) GetPost(ctx context.Context, id int) (models.Post, error) {
return post, nil
}
-func (s *Service) DeletePost(ctx context.Context, site models.Site, id int) error {
- post, err := s.db.GetPost(ctx, int64(id))
- if err != nil {
- return err
- }
-
- if err := s.db.DeletePost(ctx, int64(id)); err != nil {
- return err
- }
-
- return s.jobs.Queue(ctx, s.sb.DeletePost(site, post))
-}
-
func (s *Service) Create(ctx context.Context, site models.Site, req NewPost) (models.Post, error) {
post := models.Post{
SiteID: site.ID,
diff --git a/services/sitebuilder/posts.go b/services/sitebuilder/posts.go
index 1a7a135..9dd7829 100644
--- a/services/sitebuilder/posts.go
+++ b/services/sitebuilder/posts.go
@@ -47,41 +47,13 @@ func (s *Service) WriteAllPosts(site models.Site) models.Job {
}
}
-func (s *Service) DeletePost(site models.Site, post models.Post) models.Job {
- return models.Jobs(
- models.Job{
- Do: func(ctx context.Context) error {
- themeMeta, ok := s.themes.Lookup(site.Theme)
- if !ok {
- return errors.New("theme not found")
- }
-
- postFilename := s.postFilename(site, themeMeta, post)
-
- if _, err := os.Stat(postFilename); err != nil {
- if errors.Is(err, os.ErrNotExist) {
- return nil
- }
- return err
- }
-
- if os.Remove(postFilename) != nil {
- return nil
- }
- return nil
- },
- },
- s.Publish(site),
- )
-}
-
func (s *Service) writePost(site models.Site, post models.Post) error {
themeMeta, ok := s.themes.Lookup(site.Theme)
if !ok {
return errors.New("theme not found")
}
- postFilename := s.postFilename(site, themeMeta, post)
+ postFilename := filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), themeMeta.PostDir, post.CreatedAt.Format("2006-01-02-150405.md"))
log.Printf(" .. post %v", postFilename)
@@ -124,7 +96,3 @@ func (s *Service) writePost(site models.Site, post models.Post) error {
return nil
}
-
-func (s *Service) postFilename(site models.Site, themeMeta models.ThemeMeta, post models.Post) string {
- return filepath.Join(s.hugo.SiteStagingDir(site, hugo.ContentSiteDir), themeMeta.PostDir, post.CreatedAt.Format("2006-01-02-150405.md"))
-}
diff --git a/services/sites/service.go b/services/sites/service.go
index 53a0492..346f749 100644
--- a/services/sites/service.go
+++ b/services/sites/service.go
@@ -41,16 +41,11 @@ func (s *Service) GetSite(ctx context.Context, id int) (models.Site, error) {
return s.db.GetSite(ctx, int64(id))
}
-func (s *Service) GetProdTargetOfSite(ctx context.Context, siteID int) (models.PublishTarget, error) {
- return s.db.GetPublishTargetBySiteRole(ctx, int64(siteID), models.TargetRoleProduction)
-}
-
-func (s *Service) CreateSite(ctx context.Context, user models.User, name string) (models.Site, error) {
+func (s *Service) CreateSite(ctx context.Context, name string) (models.Site, error) {
newSite := models.Site{
- Name: normaliseName(name),
- OwnerUserID: user.ID,
- Title: name,
- Theme: "bear",
+ Name: normaliseName(name),
+ Title: name,
+ Theme: "bear",
}
_, ok := s.themes.Lookup(newSite.Theme)
@@ -67,7 +62,7 @@ func (s *Service) CreateSite(ctx context.Context, user models.User, name string)
SiteID: newSite.ID,
Role: models.TargetRoleProduction,
Type: models.TargetTypeNetlify,
- URL: "https://meek-meringue-060cfc.netlify.app/",
+ URL: "https://meek-meringue-060cfc.netlify.app",
TargetRef: "e628dc6e-e6e1-45a9-847a-982adef940a8",
}); err != nil {
return models.Site{}, err
diff --git a/services/users/service.go b/services/users/service.go
deleted file mode 100644
index 1fcd925..0000000
--- a/services/users/service.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package users
-
-import (
- "context"
- "encoding/base64"
- "golang.org/x/crypto/bcrypt"
- "lmika.dev/lmika/hugo-cms/models"
- "lmika.dev/lmika/hugo-cms/providers/db"
- "log"
-)
-
-type Service struct {
- dbp *db.DB
-}
-
-func NewService(dbp *db.DB) *Service {
- return &Service{
- dbp: dbp,
- }
-}
-
-func (s *Service) AddUser(ctx context.Context, newUser NewUser) (models.User, error) {
- passwd, err := bcrypt.GenerateFromPassword([]byte(newUser.Password), bcrypt.DefaultCost)
- if err != nil {
- return models.User{}, err
- }
-
- user := models.User{
- Email: newUser.Email,
- PasswordHash: base64.StdEncoding.EncodeToString(passwd),
- }
- if err := s.dbp.AddUser(ctx, &user); err != nil {
- return models.User{}, err
- }
-
- return user, nil
-}
-
-func (s *Service) GetUserByID(ctx context.Context, id int64) (models.User, error) {
- return s.dbp.GetUserByID(ctx, id)
-}
-
-func (s *Service) VerifyLogin(ctx context.Context, email string, password string) (models.User, error) {
- user, err := s.dbp.GetUserByEmail(ctx, email)
- if err != nil {
- log.Println("User not found")
- return models.User{}, err
- }
-
- pwdHash, err := base64.StdEncoding.DecodeString(user.PasswordHash)
- if err != nil {
- return models.User{}, err
- }
-
- err = bcrypt.CompareHashAndPassword(pwdHash, []byte(password))
- if err != nil {
- log.Println("Password incorrect")
- return models.User{}, err
- }
-
- return user, nil
-}
-
-func (s *Service) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
- user, err := s.dbp.GetUserByEmail(ctx, email)
- if err != nil {
- return models.User{}, err
- }
-
- return user, nil
-}
-
-type NewUser struct {
- Email string `json:"email"`
- Password string `json:"password"`
-}
diff --git a/sql/queries/posts.sql b/sql/queries/posts.sql
index 1ddf3cf..34130ad 100644
--- a/sql/queries/posts.sql
+++ b/sql/queries/posts.sql
@@ -1,17 +1,17 @@
-- name: ListPosts :many
-SELECT * FROM posts WHERE site_id = $1 ORDER BY post_date DESC LIMIT 25;
+SELECT * FROM post WHERE site_id = $1 ORDER BY post_date DESC LIMIT 25;
-- name: GetPostWithID :one
-SELECT * FROM posts WHERE id = $1 LIMIT 1;
+SELECT * FROM post WHERE id = $1 LIMIT 1;
-- name: ListPublishablePosts :many
SELECT *
-FROM posts
+FROM post
WHERE id > $1 AND site_id = $2 AND state = 'published' AND post_date <= $3
ORDER BY id LIMIT 100;
-- name: InsertPost :one
-INSERT INTO posts (
+INSERT INTO post (
site_id,
title,
body,
@@ -23,7 +23,7 @@ INSERT INTO posts (
RETURNING id;
-- name: UpdatePost :exec
-UPDATE posts SET
+UPDATE post SET
site_id = $2,
title = $3,
body = $4,
@@ -31,7 +31,4 @@ UPDATE posts SET
props = $6,
post_date = $7
-- updated_at = $7
-WHERE id = $1;
-
--- name: DeletePost :exec
-DELETE FROM posts WHERE id = $1;
\ No newline at end of file
+WHERE id = $1;
\ No newline at end of file
diff --git a/sql/queries/sites.sql b/sql/queries/sites.sql
index c71346c..d03f924 100644
--- a/sql/queries/sites.sql
+++ b/sql/queries/sites.sql
@@ -1,14 +1,14 @@
-- name: ListSites :one
-SELECT * FROM sites;
+SELECT * FROM site;
-- name: GetSiteWithID :one
-SELECT * FROM sites WHERE id = $1 LIMIT 1;
+SELECT * FROM site WHERE id = $1 LIMIT 1;
-- name: NewSite :one
-INSERT INTO sites (
+INSERT INTO site (
name,
- owner_user_id,
title,
+ url,
theme,
props
) VALUES ($1, $2, $3, $4, $5)
diff --git a/sql/queries/targets.sql b/sql/queries/targets.sql
index 011cc4d..55be1d6 100644
--- a/sql/queries/targets.sql
+++ b/sql/queries/targets.sql
@@ -1,11 +1,8 @@
--- name: ListTargetsOfSite :many
-SELECT * FROM publish_targets WHERE site_id = $1;
-
--- name: GetTargetOfSiteRole :one
-SELECT * FROM publish_targets WHERE site_id = $1 AND role = $2 LIMIT 1;
+-- name: ListPublishTargetsOfRole :many
+SELECT * FROM publish_target WHERE site_id = $1 AND role = 'production';
-- name: InsertPublishTarget :one
-INSERT INTO publish_targets (
+INSERT INTO publish_target (
site_id,
role,
target_type,
diff --git a/sql/queries/users.sql b/sql/queries/users.sql
deleted file mode 100644
index cb01e46..0000000
--- a/sql/queries/users.sql
+++ /dev/null
@@ -1,13 +0,0 @@
--- name: AddUser :one
-INSERT INTO users (
- email,
- password
-) VALUES ($1, $2)
-ON CONFLICT (email) DO UPDATE SET password = $2
-RETURNING id;
-
--- name: GetUserByID :one
-SELECT * FROM users WHERE id = $1 LIMIT 1;
-
--- name: GetUserByEmail :one
-SELECT * FROM users WHERE email = $1 LIMIT 1;
\ No newline at end of file
diff --git a/sql/schema/1_init.up.sql b/sql/schema/1_init.up.sql
index 38492d1..15b6253 100644
--- a/sql/schema/1_init.up.sql
+++ b/sql/schema/1_init.up.sql
@@ -11,24 +11,16 @@ CREATE TYPE target_type AS ENUM (
'netlify'
);
-CREATE TABLE users (
- id BIGSERIAL NOT NULL PRIMARY KEY,
- email TEXT NOT NULL UNIQUE,
- password TEXT NOT NULL
+CREATE TABLE site (
+ id BIGSERIAL NOT NULL PRIMARY KEY,
+ name TEXT NOT NULL UNIQUE,
+ title TEXT NOT NULL,
+ url TEXT NOT NULL,
+ theme TEXT NOT NULL,
+ props JSON NOT NULL
);
-CREATE TABLE sites (
- id BIGSERIAL NOT NULL PRIMARY KEY,
- owner_user_id BIGINT NOT NULL,
- name TEXT NOT NULL UNIQUE,
- title TEXT NOT NULL,
- theme TEXT NOT NULL,
- props JSON NOT NULL,
-
- FOREIGN KEY (owner_user_id) REFERENCES users (id)
-);
-
-CREATE TABLE posts (
+CREATE TABLE post (
id BIGSERIAL NOT NULL PRIMARY KEY,
site_id BIGINT NOT NULL,
title TEXT,
@@ -38,10 +30,10 @@ CREATE TABLE posts (
post_date TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP NOT NULL,
- FOREIGN KEY (site_id) REFERENCES sites (id) ON DELETE CASCADE
+ FOREIGN KEY (site_id) REFERENCES site (id)
);
-CREATE TABLE publish_targets (
+CREATE TABLE publish_target (
id BIGSERIAL NOT NULL PRIMARY KEY,
site_id BIGINT NOT NULL,
role target_role NOT NULL,
@@ -49,6 +41,5 @@ CREATE TABLE publish_targets (
url TEXT NOT NULL,
target_ref TEXT NOT NULL,
- FOREIGN KEY (site_id) REFERENCES sites (id) ON DELETE CASCADE,
- UNIQUE (site_id, role)
+ FOREIGN KEY (site_id) REFERENCES site (id)
);
\ No newline at end of file
diff --git a/templates/auth/login.html b/templates/auth/login.html
deleted file mode 100644
index 1cd4f0a..0000000
--- a/templates/auth/login.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
\ No newline at end of file
diff --git a/templates/fs.go b/templates/fs.go
index aedde93..64b74d4 100644
--- a/templates/fs.go
+++ b/templates/fs.go
@@ -3,7 +3,6 @@ package templates
import "embed"
//go:embed *.html
-//go:embed auth/*.html
//go:embed layouts/*.html
//go:embed posts/*.html
var FS embed.FS
diff --git a/templates/index.html b/templates/index.html
index 614290c..0c4d297 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -1,7 +1,5 @@
Thing
-User = {{.user.Email}}
-
diff --git a/templates/layouts/login.html b/templates/layouts/login.html
deleted file mode 100644
index 822b957..0000000
--- a/templates/layouts/login.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
- Hugo CRM
-
-
- {{embed}}
-
-
\ No newline at end of file
diff --git a/templates/layouts/main.html b/templates/layouts/main.html
index 66bfca4..822b957 100644
--- a/templates/layouts/main.html
+++ b/templates/layouts/main.html
@@ -6,7 +6,6 @@
Hugo CRM
-
{{embed}}
diff --git a/templates/layouts/site.html b/templates/layouts/site.html
index 789354e..5539345 100644
--- a/templates/layouts/site.html
+++ b/templates/layouts/site.html
@@ -6,16 +6,12 @@
Hugo CMS
-
Hugo CMS
diff --git a/templates/posts/index.html b/templates/posts/index.html
index 87b2647..c297bba 100644
--- a/templates/posts/index.html
+++ b/templates/posts/index.html
@@ -3,18 +3,18 @@
{{range .posts}}
-
- {{if .Title}}
-
{{.Title}}
- {{end}}
+ {{if .Title}}
+
{{.Title}}
+ {{end}}
+
+
{{else}}
No posts yet
{{end}}
\ No newline at end of file
diff --git a/templates/posts/new.html b/templates/posts/new.html
index 350d71e..72769fa 100644
--- a/templates/posts/new.html
+++ b/templates/posts/new.html
@@ -1,5 +1,5 @@
{{- $postTarget := printf "/sites/%v/posts" .site.ID -}}
-{{- if (ne .post.ID 0) -}}
+{{- if .post.ID -}}
{{- $postTarget = printf "/sites/%v/posts/%v" .site.ID .post.ID -}}
{{- end -}}