v2 #43
|
@ -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)
|
||||
},
|
||||
}
|
|
@ -1,15 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"owl-blogs/app"
|
||||
"owl-blogs/config"
|
||||
"owl-blogs/domain/model"
|
||||
"owl-blogs/infra"
|
||||
"owl-blogs/web"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
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 {
|
||||
config := config.NewConfig()
|
||||
|
||||
|
@ -29,6 +45,5 @@ func App(db infra.Database) *web.WebApp {
|
|||
}
|
||||
|
||||
func main() {
|
||||
db := infra.NewSqliteDB(DbPath)
|
||||
App(db).Run()
|
||||
Execute()
|
||||
}
|
||||
|
|
|
@ -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
3
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gofiber/fiber/v2 v2.47.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/klauspost/compress v1.16.3 // 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/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // 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/testify v1.8.4 // indirect
|
||||
github.com/tinylib/msgp v1.1.8 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -1,5 +1,6 @@
|
|||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
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/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||
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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
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/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-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||
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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
OWL_SECRET_KEY=test-secret-key \
|
||||
go run owl-blogs/cmd/owl web
|
|
@ -28,7 +28,7 @@ func NewWebApp(
|
|||
entryHandler := NewEntryHandler(entryService, typeRegistry)
|
||||
mediaHandler := NewMediaHandler(entryService)
|
||||
rssHandler := NewRSSHandler(entryService)
|
||||
loginHandler := NewLoginHandler(entryService)
|
||||
loginHandler := NewLoginHandler(authorService)
|
||||
editorListHandler := NewEditorListHandler(typeRegistry)
|
||||
editorHandler := NewEditorHandler(entryService, typeRegistry, binService)
|
||||
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"owl-blogs/app"
|
||||
"text/template"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
//go:embed templates
|
||||
var templates embed.FS
|
||||
|
||||
type EditorListHandler struct {
|
||||
registry *app.EntryTypeRegistry
|
||||
ts *template.Template
|
||||
}
|
||||
|
||||
type EditorListContext struct {
|
||||
|
@ -21,19 +15,8 @@ type EditorListContext struct {
|
|||
}
|
||||
|
||||
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{
|
||||
registry: registry,
|
||||
ts: ts,
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,5 +32,5 @@ func (h *EditorListHandler) Handle(c *fiber.Ctx) error {
|
|||
typeNames = append(typeNames, name)
|
||||
}
|
||||
|
||||
return h.ts.ExecuteTemplate(c, "base", &EditorListContext{Types: typeNames})
|
||||
return RenderTemplate(c, "views/editor_list", &EditorListContext{Types: typeNames})
|
||||
}
|
||||
|
|
|
@ -2,22 +2,47 @@ package web
|
|||
|
||||
import (
|
||||
"owl-blogs/app"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type LoginHandler struct {
|
||||
entrySvc *app.EntryService
|
||||
authorService *app.AuthorService
|
||||
}
|
||||
|
||||
func NewLoginHandler(entryService *app.EntryService) *LoginHandler {
|
||||
return &LoginHandler{entrySvc: entryService}
|
||||
func NewLoginHandler(authorService *app.AuthorService) *LoginHandler {
|
||||
return &LoginHandler{authorService: authorService}
|
||||
}
|
||||
|
||||
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 {
|
||||
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/")
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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}}
|
Loading…
Reference in New Issue