diff --git a/app/author_service.go b/app/author_service.go index 64257b0..835749a 100644 --- a/app/author_service.go +++ b/app/author_service.go @@ -4,7 +4,6 @@ import ( "crypto/sha256" "fmt" "owl-blogs/app/repository" - "owl-blogs/config" "owl-blogs/domain/model" "strings" @@ -12,12 +11,12 @@ import ( ) type AuthorService struct { - repo repository.AuthorRepository - config config.Config + repo repository.AuthorRepository + siteConfigRepo repository.SiteConfigRepository } -func NewAuthorService(repo repository.AuthorRepository, config config.Config) *AuthorService { - return &AuthorService{repo: repo, config: config} +func NewAuthorService(repo repository.AuthorRepository, siteConfigRepo repository.SiteConfigRepository) *AuthorService { + return &AuthorService{repo: repo, siteConfigRepo: siteConfigRepo} } func hashPassword(password string) (string, error) { @@ -50,7 +49,18 @@ func (s *AuthorService) Authenticate(name string, password string) bool { } func (s *AuthorService) getSecretKey() string { - return s.config.SECRET_KEY() + config, err := s.siteConfigRepo.Get() + if err != nil { + panic(err) + } + if config.Secret == "" { + config.Secret = RandStringRunes(64) + err = s.siteConfigRepo.Update(config) + if err != nil { + panic(err) + } + } + return config.Secret } func (s *AuthorService) CreateToken(name string) (string, error) { diff --git a/app/author_service_test.go b/app/author_service_test.go index 2b419f4..409ea49 100644 --- a/app/author_service_test.go +++ b/app/author_service_test.go @@ -2,6 +2,7 @@ package app_test import ( "owl-blogs/app" + "owl-blogs/domain/model" "owl-blogs/infra" "owl-blogs/test" "strings" @@ -10,17 +11,25 @@ import ( "github.com/stretchr/testify/require" ) -type testConfig struct { +type testConfigRepo struct { + config model.SiteConfig } -func (c *testConfig) SECRET_KEY() string { - return "test" +// Get implements repository.SiteConfigRepository. +func (c *testConfigRepo) Get() (model.SiteConfig, error) { + return c.config, nil +} + +// Update implements repository.SiteConfigRepository. +func (c *testConfigRepo) Update(siteConfig model.SiteConfig) error { + c.config = siteConfig + return nil } func getAutherService() *app.AuthorService { db := test.NewMockDb() authorRepo := infra.NewDefaultAuthorRepo(db) - authorService := app.NewAuthorService(authorRepo, &testConfig{}) + authorService := app.NewAuthorService(authorRepo, &testConfigRepo{}) return authorService } diff --git a/app/utils.go b/app/utils.go new file mode 100644 index 0000000..2797526 --- /dev/null +++ b/app/utils.go @@ -0,0 +1,15 @@ +package app + +import ( + "math/rand" +) + +var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func RandStringRunes(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return string(b) +} diff --git a/cmd/owl/editor_test.go b/cmd/owl/editor_test.go index 2639cc2..df697fe 100644 --- a/cmd/owl/editor_test.go +++ b/cmd/owl/editor_test.go @@ -9,7 +9,7 @@ import ( "net/http/httptest" "os" "owl-blogs/app" - "owl-blogs/domain/model" + entrytypes "owl-blogs/entry_types" "owl-blogs/infra" "owl-blogs/test" "path" @@ -94,8 +94,8 @@ func TestEditorFormPost(t *testing.T) { id := strings.Split(resp.Header.Get("Location"), "/")[2] entry, err := repo.FindById(id) require.NoError(t, err) - require.Equal(t, "test content", entry.MetaData().(*model.ImageMetaData).Content) - imageId := entry.MetaData().(*model.ImageMetaData).ImageId + require.Equal(t, "test content", entry.MetaData().(*entrytypes.ImageMetaData).Content) + imageId := entry.MetaData().(*entrytypes.ImageMetaData).ImageId require.NotZero(t, imageId) bin, err := binRepo.FindById(imageId) require.NoError(t, err) diff --git a/cmd/owl/import_v1.go b/cmd/owl/import_v1.go index 1eb68a1..f5004b0 100644 --- a/cmd/owl/import_v1.go +++ b/cmd/owl/import_v1.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "owl-blogs/domain/model" + entrytypes "owl-blogs/entry_types" "owl-blogs/importer" "owl-blogs/infra" "path" @@ -49,7 +50,7 @@ var importCmd = &cobra.Command{ files := importer.ListDir(mediaDir) for _, file := range files { // mock entry to pass to binary service - entry := &model.Article{} + entry := &entrytypes.Article{} entry.SetID(post.Id) fileData, err := os.ReadFile(path.Join(mediaDir, file)) @@ -63,10 +64,10 @@ var importCmd = &cobra.Command{ switch post.Meta.Type { case "article": - entry = &model.Article{} + entry = &entrytypes.Article{} entry.SetID(post.Id) entry.SetPublishedAt(&post.Meta.Date) - entry.SetMetaData(&model.ArticleMetaData{ + entry.SetMetaData(&entrytypes.ArticleMetaData{ Title: post.Meta.Title, Content: post.Content, }) @@ -75,26 +76,26 @@ var importCmd = &cobra.Command{ case "reply": case "photo": - entry = &model.Image{} + entry = &entrytypes.Image{} entry.SetID(post.Id) entry.SetPublishedAt(&post.Meta.Date) - entry.SetMetaData(&model.ImageMetaData{ + entry.SetMetaData(&entrytypes.ImageMetaData{ Title: post.Meta.Title, Content: post.Content, ImageId: post.Meta.PhotoPath, }) case "note": - entry = &model.Note{} + entry = &entrytypes.Note{} entry.SetID(post.Id) entry.SetPublishedAt(&post.Meta.Date) - entry.SetMetaData(&model.NoteMetaData{ + entry.SetMetaData(&entrytypes.NoteMetaData{ Content: post.Content, }) case "recipe": - entry = &model.Recipe{} + entry = &entrytypes.Recipe{} entry.SetID(post.Id) entry.SetPublishedAt(&post.Meta.Date) - entry.SetMetaData(&model.RecipeMetaData{ + entry.SetMetaData(&entrytypes.RecipeMetaData{ Title: post.Meta.Title, Yield: post.Meta.Recipe.Yield, Duration: post.Meta.Recipe.Duration, @@ -102,10 +103,10 @@ var importCmd = &cobra.Command{ Content: post.Content, }) case "page": - entry = &model.Page{} + entry = &entrytypes.Page{} entry.SetID(post.Id) entry.SetPublishedAt(&post.Meta.Date) - entry.SetMetaData(&model.PageMetaData{ + entry.SetMetaData(&entrytypes.PageMetaData{ Title: post.Meta.Title, Content: post.Content, }) diff --git a/cmd/owl/main.go b/cmd/owl/main.go index 4047ea0..5d43205 100644 --- a/cmd/owl/main.go +++ b/cmd/owl/main.go @@ -4,8 +4,7 @@ import ( "fmt" "os" "owl-blogs/app" - "owl-blogs/config" - "owl-blogs/domain/model" + entrytypes "owl-blogs/entry_types" "owl-blogs/infra" "owl-blogs/web" @@ -27,22 +26,21 @@ func Execute() { } func App(db infra.Database) *web.WebApp { - config := config.NewConfig() - registry := app.NewEntryTypeRegistry() - registry.Register(&model.Image{}) - registry.Register(&model.Article{}) - registry.Register(&model.Page{}) - registry.Register(&model.Recipe{}) - registry.Register(&model.Note{}) + registry.Register(&entrytypes.Image{}) + registry.Register(&entrytypes.Article{}) + registry.Register(&entrytypes.Page{}) + registry.Register(&entrytypes.Recipe{}) + registry.Register(&entrytypes.Note{}) entryRepo := infra.NewEntryRepository(db, registry) binRepo := infra.NewBinaryFileRepo(db) authorRepo := infra.NewDefaultAuthorRepo(db) + siteConfigRepo := infra.NewSiteConfigRepo(db) entryService := app.NewEntryService(entryRepo) binaryService := app.NewBinaryFileService(binRepo) - authorService := app.NewAuthorService(authorRepo, config) + authorService := app.NewAuthorService(authorRepo, siteConfigRepo) return web.NewWebApp(entryService, registry, binaryService, authorService) diff --git a/config/config.go b/config/config.go index 03ae7c8..1d0eedb 100644 --- a/config/config.go +++ b/config/config.go @@ -3,11 +3,9 @@ package config import "os" type Config interface { - SECRET_KEY() string } type EnvConfig struct { - secretKey string } func getEnvOrPanic(key string) string { @@ -19,11 +17,5 @@ func getEnvOrPanic(key string) string { } func NewConfig() Config { - return &EnvConfig{ - secretKey: getEnvOrPanic("OWL_SECRET_KEY"), - } -} - -func (c *EnvConfig) SECRET_KEY() string { - return c.secretKey + return &EnvConfig{} } diff --git a/domain/model/siteconfig.go b/domain/model/siteconfig.go index 72fc5b4..b705e8b 100644 --- a/domain/model/siteconfig.go +++ b/domain/model/siteconfig.go @@ -30,4 +30,5 @@ type SiteConfig struct { HeaderMenu []MenuItem FooterMenu []MenuItem Secret string + AvatarUrl string } diff --git a/domain/model/article.go b/entry_types/article.go similarity index 78% rename from domain/model/article.go rename to entry_types/article.go index b07120f..9849a24 100644 --- a/domain/model/article.go +++ b/entry_types/article.go @@ -1,12 +1,13 @@ -package model +package entrytypes import ( "fmt" + "owl-blogs/domain/model" "owl-blogs/render" ) type Article struct { - EntryBase + model.EntryBase meta ArticleMetaData } @@ -19,12 +20,12 @@ func (e *Article) Title() string { return e.meta.Title } -func (e *Article) Content() EntryContent { +func (e *Article) Content() model.EntryContent { str, err := render.RenderTemplateToString("entry/Article", e) if err != nil { fmt.Println(err) } - return EntryContent(str) + return model.EntryContent(str) } func (e *Article) MetaData() interface{} { diff --git a/domain/model/image.go b/entry_types/image.go similarity index 79% rename from domain/model/image.go rename to entry_types/image.go index cc77ca5..bd23e37 100644 --- a/domain/model/image.go +++ b/entry_types/image.go @@ -1,12 +1,13 @@ -package model +package entrytypes import ( "fmt" + "owl-blogs/domain/model" "owl-blogs/render" ) type Image struct { - EntryBase + model.EntryBase meta ImageMetaData } @@ -20,12 +21,12 @@ func (e *Image) Title() string { return e.meta.Title } -func (e *Image) Content() EntryContent { +func (e *Image) Content() model.EntryContent { str, err := render.RenderTemplateToString("entry/Image", e) if err != nil { fmt.Println(err) } - return EntryContent(str) + return model.EntryContent(str) } func (e *Image) MetaData() interface{} { diff --git a/domain/model/note.go b/entry_types/note.go similarity index 67% rename from domain/model/note.go rename to entry_types/note.go index f2ed50b..f7fb87d 100644 --- a/domain/model/note.go +++ b/entry_types/note.go @@ -1,7 +1,9 @@ -package model +package entrytypes + +import "owl-blogs/domain/model" type Note struct { - EntryBase + model.EntryBase meta NoteMetaData } @@ -13,8 +15,8 @@ func (e *Note) Title() string { return "" } -func (e *Note) Content() EntryContent { - return EntryContent(e.meta.Content) +func (e *Note) Content() model.EntryContent { + return model.EntryContent(e.meta.Content) } func (e *Note) MetaData() interface{} { diff --git a/domain/model/page.go b/entry_types/page.go similarity index 78% rename from domain/model/page.go rename to entry_types/page.go index 385d864..78faece 100644 --- a/domain/model/page.go +++ b/entry_types/page.go @@ -1,12 +1,13 @@ -package model +package entrytypes import ( "fmt" + "owl-blogs/domain/model" "owl-blogs/render" ) type Page struct { - EntryBase + model.EntryBase meta PageMetaData } @@ -19,12 +20,12 @@ func (e *Page) Title() string { return e.meta.Title } -func (e *Page) Content() EntryContent { +func (e *Page) Content() model.EntryContent { str, err := render.RenderTemplateToString("entry/Page", e) if err != nil { fmt.Println(err) } - return EntryContent(str) + return model.EntryContent(str) } func (e *Page) MetaData() interface{} { diff --git a/domain/model/recipe.go b/entry_types/recipe.go similarity index 82% rename from domain/model/recipe.go rename to entry_types/recipe.go index ff83edb..20b0a87 100644 --- a/domain/model/recipe.go +++ b/entry_types/recipe.go @@ -1,12 +1,13 @@ -package model +package entrytypes import ( "fmt" + "owl-blogs/domain/model" "owl-blogs/render" ) type Recipe struct { - EntryBase + model.EntryBase meta RecipeMetaData } @@ -22,12 +23,12 @@ func (e *Recipe) Title() string { return e.meta.Title } -func (e *Recipe) Content() EntryContent { +func (e *Recipe) Content() model.EntryContent { str, err := render.RenderTemplateToString("entry/Recipe", e) if err != nil { fmt.Println(err) } - return EntryContent(str) + return model.EntryContent(str) } func (e *Recipe) MetaData() interface{} { diff --git a/render/templates.go b/render/templates.go index a9a88ce..b9e5c87 100644 --- a/render/templates.go +++ b/render/templates.go @@ -4,6 +4,7 @@ import ( "bytes" "embed" "io" + "owl-blogs/domain/model" "text/template" "github.com/yuin/goldmark" @@ -12,6 +13,11 @@ import ( "github.com/yuin/goldmark/renderer/html" ) +type TemplateData struct { + Data interface{} + SiteConfig model.SiteConfig +} + //go:embed templates var templates embed.FS @@ -42,7 +48,10 @@ func RenderTemplateWithBase(w io.Writer, templateName string, data interface{}) return err } - err = t.ExecuteTemplate(w, "base", data) + err = t.ExecuteTemplate(w, "base", TemplateData{ + Data: data, + SiteConfig: model.SiteConfig{}, + }) return err diff --git a/render/templates/base.tmpl b/render/templates/base.tmpl index 07f37c2..ba79a5f 100644 --- a/render/templates/base.tmpl +++ b/render/templates/base.tmpl @@ -3,15 +3,94 @@ - {{template "title" .}} - Owl Blog + + {{template "title" .Data}} - {{ .SiteConfig.Title }} + + + -
- Owl Blog +
+
+
+

{{ .SiteConfig.Title }}

+

{{ .SiteConfig.SubTitle }}

+
+ +
+ {{ if .SiteConfig.AvatarUrl }} + + {{ end }} +
+ {{ range $me := .SiteConfig.Me }} +
  • {{$me.Name}} +
  • + {{ end }} +
    +
    +
    +
    + +
    - {{template "main" .}} + {{template "main" .Data}}