This commit is contained in:
Niko Abeler 2023-07-08 14:28:15 +02:00
parent 197629db9a
commit a90bcaaa2d
11 changed files with 166 additions and 26 deletions

29
cmd/owl/create_author.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"owl-blogs/infra"
"github.com/spf13/cobra"
)
var user string
var password string
func init() {
rootCmd.AddCommand(newAuthorCmd)
newAuthorCmd.Flags().StringVarP(&user, "user", "u", "", "The user name")
newAuthorCmd.MarkFlagRequired("user")
newAuthorCmd.Flags().StringVarP(&password, "password", "p", "", "The password")
newAuthorCmd.MarkFlagRequired("password")
}
var newAuthorCmd = &cobra.Command{
Use: "new-author",
Short: "Creates a new author",
Long: `Creates a new author`,
Run: func(cmd *cobra.Command, args []string) {
db := infra.NewSqliteDB(DbPath)
App(db).AuthorService.Create(user, password)
},
}

View File

@ -1,15 +1,31 @@
package main package main
import ( import (
"fmt"
"os"
"owl-blogs/app" "owl-blogs/app"
"owl-blogs/config" "owl-blogs/config"
"owl-blogs/domain/model" "owl-blogs/domain/model"
"owl-blogs/infra" "owl-blogs/infra"
"owl-blogs/web" "owl-blogs/web"
"github.com/spf13/cobra"
) )
const DbPath = "owlblogs.db" const DbPath = "owlblogs.db"
var rootCmd = &cobra.Command{
Use: "owl",
Short: "Owl Blogs is a not so static blog generator",
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func App(db infra.Database) *web.WebApp { func App(db infra.Database) *web.WebApp {
config := config.NewConfig() config := config.NewConfig()
@ -29,6 +45,5 @@ func App(db infra.Database) *web.WebApp {
} }
func main() { func main() {
db := infra.NewSqliteDB(DbPath) Execute()
App(db).Run()
} }

21
cmd/owl/web.go Normal file
View File

@ -0,0 +1,21 @@
package main
import (
"owl-blogs/infra"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(webCmd)
}
var webCmd = &cobra.Command{
Use: "web",
Short: "Start the web server",
Long: `Start the web server`,
Run: func(cmd *cobra.Command, args []string) {
db := infra.NewSqliteDB(DbPath)
App(db).Run()
},
}

3
go.mod
View File

@ -7,6 +7,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gofiber/fiber/v2 v2.47.0 // indirect github.com/gofiber/fiber/v2 v2.47.0 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmoiron/sqlx v1.3.5 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/klauspost/compress v1.16.3 // indirect github.com/klauspost/compress v1.16.3 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
@ -18,6 +19,8 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect github.com/stretchr/testify v1.8.4 // indirect
github.com/tinylib/msgp v1.1.8 // indirect github.com/tinylib/msgp v1.1.8 // indirect

8
go.sum
View File

@ -1,5 +1,6 @@
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -8,6 +9,8 @@ github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3
github.com/gofiber/fiber/v2 v2.47.0/go.mod h1:mbFMVN1lQuzziTkkakgtKKdjfsXSw9BKR5lmcNksUoU= github.com/gofiber/fiber/v2 v2.47.0/go.mod h1:mbFMVN1lQuzziTkkakgtKKdjfsXSw9BKR5lmcNksUoU=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
@ -30,11 +33,16 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4= github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4=
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=

6
run_dev.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
set -e
OWL_SECRET_KEY=test-secret-key \
go run owl-blogs/cmd/owl web

View File

@ -28,7 +28,7 @@ func NewWebApp(
entryHandler := NewEntryHandler(entryService, typeRegistry) entryHandler := NewEntryHandler(entryService, typeRegistry)
mediaHandler := NewMediaHandler(entryService) mediaHandler := NewMediaHandler(entryService)
rssHandler := NewRSSHandler(entryService) rssHandler := NewRSSHandler(entryService)
loginHandler := NewLoginHandler(entryService) loginHandler := NewLoginHandler(authorService)
editorListHandler := NewEditorListHandler(typeRegistry) editorListHandler := NewEditorListHandler(typeRegistry)
editorHandler := NewEditorHandler(entryService, typeRegistry, binService) editorHandler := NewEditorHandler(entryService, typeRegistry, binService)

View File

@ -1,19 +1,13 @@
package web package web
import ( import (
"embed"
"owl-blogs/app" "owl-blogs/app"
"text/template"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
//go:embed templates
var templates embed.FS
type EditorListHandler struct { type EditorListHandler struct {
registry *app.EntryTypeRegistry registry *app.EntryTypeRegistry
ts *template.Template
} }
type EditorListContext struct { type EditorListContext struct {
@ -21,19 +15,8 @@ type EditorListContext struct {
} }
func NewEditorListHandler(registry *app.EntryTypeRegistry) *EditorListHandler { func NewEditorListHandler(registry *app.EntryTypeRegistry) *EditorListHandler {
ts, err := template.ParseFS(
templates,
"templates/base.tmpl",
"templates/views/editor_list.tmpl",
)
if err != nil {
panic(err)
}
return &EditorListHandler{ return &EditorListHandler{
registry: registry, registry: registry,
ts: ts,
} }
} }
@ -49,5 +32,5 @@ func (h *EditorListHandler) Handle(c *fiber.Ctx) error {
typeNames = append(typeNames, name) typeNames = append(typeNames, name)
} }
return h.ts.ExecuteTemplate(c, "base", &EditorListContext{Types: typeNames}) return RenderTemplate(c, "views/editor_list", &EditorListContext{Types: typeNames})
} }

View File

@ -2,22 +2,47 @@ package web
import ( import (
"owl-blogs/app" "owl-blogs/app"
"time"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
type LoginHandler struct { type LoginHandler struct {
entrySvc *app.EntryService authorService *app.AuthorService
} }
func NewLoginHandler(entryService *app.EntryService) *LoginHandler { func NewLoginHandler(authorService *app.AuthorService) *LoginHandler {
return &LoginHandler{entrySvc: entryService} return &LoginHandler{authorService: authorService}
} }
func (h *LoginHandler) HandleGet(c *fiber.Ctx) error { func (h *LoginHandler) HandleGet(c *fiber.Ctx) error {
return c.SendString("Hello, Login!") c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
return RenderTemplate(c, "views/login", nil)
} }
func (h *LoginHandler) HandlePost(c *fiber.Ctx) error { func (h *LoginHandler) HandlePost(c *fiber.Ctx) error {
return c.SendString("Hello, Login!") c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
name := c.FormValue("name")
password := c.FormValue("password")
valid := h.authorService.Authenticate(name, password)
if !valid {
return c.Redirect("/auth/login")
}
token, err := h.authorService.CreateToken(name)
if err != nil {
return err
}
cookie := fiber.Cookie{
Name: "token",
Value: token,
Expires: time.Now().Add(30 * 24 * time.Hour),
HTTPOnly: true,
}
c.Cookie(&cookie)
return c.Redirect("/editor/")
} }

34
web/templates.go Normal file
View File

@ -0,0 +1,34 @@
package web
import (
"embed"
"io"
"text/template"
)
//go:embed templates
var templates embed.FS
func CreateTemplate(templateName string) (*template.Template, error) {
return template.ParseFS(
templates,
"templates/base.tmpl",
"templates/"+templateName+".tmpl",
)
}
func RenderTemplate(w io.Writer, templateName string, data interface{}) error {
t, err := CreateTemplate(templateName)
if err != nil {
return err
}
err = t.ExecuteTemplate(w, "base", data)
return err
}

View File

@ -0,0 +1,16 @@
{{define "title"}}Editor List{{end}}
{{define "main"}}
<h1>Login</h1>
<form action="" method="post">
<label for="name">Username</label>
<input id="name" name="name" type="text" placeholder="Username">
<label for="password">Password</label>
<input id="password" name="password" type="password" placeholder="Password">
<input type="submit" value="Login">
</form>
{{end}}