v2 #43

Merged
h4kor merged 41 commits from v2 into main 2023-07-19 19:09:19 +00:00
9 changed files with 71 additions and 38 deletions
Showing only changes of commit 033a6b4a7f - Show all commits

View File

@ -62,7 +62,7 @@ func (s *AuthorService) CreateToken(name string) (string, error) {
return fmt.Sprintf("%s.%x", name, hash.Sum(nil)), nil return fmt.Sprintf("%s.%x", name, hash.Sum(nil)), nil
} }
func (s *AuthorService) ValidateToken(token string) bool { func (s *AuthorService) ValidateToken(token string) (bool, string) {
parts := strings.Split(token, ".") parts := strings.Split(token, ".")
witness := parts[len(parts)-1] witness := parts[len(parts)-1]
name := strings.Join(parts[:len(parts)-1], ".") name := strings.Join(parts[:len(parts)-1], ".")
@ -70,7 +70,7 @@ func (s *AuthorService) ValidateToken(token string) bool {
hash := sha256.New() hash := sha256.New()
_, err := hash.Write([]byte(name + s.getSecretKey())) _, err := hash.Write([]byte(name + s.getSecretKey()))
if err != nil { if err != nil {
return false return false, ""
} }
return fmt.Sprintf("%x", hash.Sum(nil)) == witness return fmt.Sprintf("%x", hash.Sum(nil)) == witness, name
} }

View File

@ -71,9 +71,15 @@ func TestAuthorValidateToken(t *testing.T) {
token, err := authorService.CreateToken("test") token, err := authorService.CreateToken("test")
require.NoError(t, err) require.NoError(t, err)
require.True(t, authorService.ValidateToken(token)) valid, name := authorService.ValidateToken(token)
require.False(t, authorService.ValidateToken(token[:len(token)-2])) require.True(t, valid)
require.False(t, authorService.ValidateToken("test")) require.Equal(t, "test", name)
require.False(t, authorService.ValidateToken("test.test")) valid, _ = authorService.ValidateToken(token[:len(token)-2])
require.False(t, authorService.ValidateToken(strings.Replace(token, "test", "test1", 1))) require.False(t, valid)
valid, _ = authorService.ValidateToken("test")
require.False(t, valid)
valid, _ = authorService.ValidateToken("test.test")
require.False(t, valid)
valid, _ = authorService.ValidateToken(strings.Replace(token, "test", "test1", 1))
require.False(t, valid)
} }

View File

@ -12,12 +12,15 @@ import (
) )
var userPath string var userPath string
var author string
func init() { func init() {
rootCmd.AddCommand(importCmd) rootCmd.AddCommand(importCmd)
importCmd.Flags().StringVarP(&userPath, "path", "p", "", "Path to the user folder") importCmd.Flags().StringVarP(&userPath, "path", "p", "", "Path to the user folder")
importCmd.MarkFlagRequired("path") importCmd.MarkFlagRequired("path")
importCmd.Flags().StringVarP(&author, "author", "a", "", "The author name")
importCmd.MarkFlagRequired("author")
} }
var importCmd = &cobra.Command{ var importCmd = &cobra.Command{
@ -56,63 +59,64 @@ var importCmd = &cobra.Command{
app.BinaryService.CreateEntryFile(file, fileData, entry) app.BinaryService.CreateEntryFile(file, fileData, entry)
} }
var entry model.Entry
switch post.Meta.Type { switch post.Meta.Type {
case "article": case "article":
article := model.Article{} entry = &model.Article{}
article.SetID(post.Id) entry.SetID(post.Id)
article.SetPublishedAt(&post.Meta.Date) entry.SetPublishedAt(&post.Meta.Date)
article.SetMetaData(&model.ArticleMetaData{ entry.SetMetaData(&model.ArticleMetaData{
Title: post.Meta.Title, Title: post.Meta.Title,
Content: post.Content, Content: post.Content,
}) })
app.EntryService.Create(&article)
case "bookmark": case "bookmark":
case "reply": case "reply":
case "photo": case "photo":
photo := model.Image{} entry = &model.Image{}
photo.SetID(post.Id) entry.SetID(post.Id)
photo.SetPublishedAt(&post.Meta.Date) entry.SetPublishedAt(&post.Meta.Date)
photo.SetMetaData(&model.ImageMetaData{ entry.SetMetaData(&model.ImageMetaData{
Title: post.Meta.Title, Title: post.Meta.Title,
Content: post.Content, Content: post.Content,
ImageId: post.Meta.PhotoPath, ImageId: post.Meta.PhotoPath,
}) })
app.EntryService.Create(&photo)
case "note": case "note":
note := model.Note{} entry = &model.Note{}
note.SetID(post.Id) entry.SetID(post.Id)
note.SetPublishedAt(&post.Meta.Date) entry.SetPublishedAt(&post.Meta.Date)
note.SetMetaData(&model.NoteMetaData{ entry.SetMetaData(&model.NoteMetaData{
Content: post.Content, Content: post.Content,
}) })
app.EntryService.Create(&note)
case "recipe": case "recipe":
recipe := model.Recipe{} entry = &model.Recipe{}
recipe.SetID(post.Id) entry.SetID(post.Id)
recipe.SetPublishedAt(&post.Meta.Date) entry.SetPublishedAt(&post.Meta.Date)
recipe.SetMetaData(&model.RecipeMetaData{ entry.SetMetaData(&model.RecipeMetaData{
Title: post.Meta.Title, Title: post.Meta.Title,
Yield: post.Meta.Recipe.Yield, Yield: post.Meta.Recipe.Yield,
Duration: post.Meta.Recipe.Duration, Duration: post.Meta.Recipe.Duration,
Ingredients: post.Meta.Recipe.Ingredients, Ingredients: post.Meta.Recipe.Ingredients,
Content: post.Content, Content: post.Content,
}) })
app.EntryService.Create(&recipe)
case "page": case "page":
page := model.Page{} entry = &model.Page{}
page.SetID(post.Id) entry.SetID(post.Id)
page.SetPublishedAt(&post.Meta.Date) entry.SetPublishedAt(&post.Meta.Date)
page.SetMetaData(&model.PageMetaData{ entry.SetMetaData(&model.PageMetaData{
Title: post.Meta.Title, Title: post.Meta.Title,
Content: post.Content, Content: post.Content,
}) })
app.EntryService.Create(&page)
default: default:
panic("Unknown type") panic("Unknown type")
} }
if entry != nil {
entry.SetAuthorId(author)
app.EntryService.Create(entry)
}
} }
}, },
} }

View File

@ -8,6 +8,7 @@ type Entry interface {
ID() string ID() string
Content() EntryContent Content() EntryContent
PublishedAt() *time.Time PublishedAt() *time.Time
AuthorId() string
MetaData() interface{} MetaData() interface{}
// Optional: can return empty string // Optional: can return empty string
@ -16,6 +17,7 @@ type Entry interface {
SetID(id string) SetID(id string)
SetPublishedAt(publishedAt *time.Time) SetPublishedAt(publishedAt *time.Time)
SetMetaData(metaData interface{}) SetMetaData(metaData interface{})
SetAuthorId(authorId string)
} }
type EntryMetaData interface { type EntryMetaData interface {
@ -24,6 +26,7 @@ type EntryMetaData interface {
type EntryBase struct { type EntryBase struct {
id string id string
publishedAt *time.Time publishedAt *time.Time
authorId string
} }
func (e *EntryBase) ID() string { func (e *EntryBase) ID() string {
@ -41,3 +44,11 @@ func (e *EntryBase) SetID(id string) {
func (e *EntryBase) SetPublishedAt(publishedAt *time.Time) { func (e *EntryBase) SetPublishedAt(publishedAt *time.Time) {
e.publishedAt = publishedAt e.publishedAt = publishedAt
} }
func (e *EntryBase) AuthorId() string {
return e.authorId
}
func (e *EntryBase) SetAuthorId(authorId string) {
e.authorId = authorId
}

View File

@ -20,6 +20,7 @@ type sqlEntry struct {
Type string `db:"type"` Type string `db:"type"`
PublishedAt *time.Time `db:"published_at"` PublishedAt *time.Time `db:"published_at"`
MetaData *string `db:"meta_data"` MetaData *string `db:"meta_data"`
AuthorId string `db:"author_id"`
} }
type DefaultEntryRepo struct { type DefaultEntryRepo struct {
@ -43,7 +44,7 @@ func (r *DefaultEntryRepo) Create(entry model.Entry) error {
entry.SetID(uuid.New().String()) entry.SetID(uuid.New().String())
} }
_, err = r.db.Exec("INSERT INTO entries (id, type, published_at, meta_data) VALUES (?, ?, ?, ?)", entry.ID(), t, entry.PublishedAt(), metaDataJson) _, err = r.db.Exec("INSERT INTO entries (id, type, published_at, author_id, meta_data) VALUES (?, ?, ?, ?, ?)", entry.ID(), t, entry.PublishedAt(), entry.AuthorId(), metaDataJson)
return err return err
} }
@ -118,7 +119,7 @@ func (r *DefaultEntryRepo) Update(entry model.Entry) error {
metaDataJson, _ = json.Marshal(entry.MetaData()) metaDataJson, _ = json.Marshal(entry.MetaData())
} }
_, err = r.db.Exec("UPDATE entries SET published_at = ?, meta_data = ? WHERE id = ?", entry.PublishedAt(), metaDataJson, entry.ID()) _, err = r.db.Exec("UPDATE entries SET published_at = ?, author_id = ?, meta_data = ? WHERE id = ?", entry.PublishedAt(), entry.AuthorId(), metaDataJson, entry.ID())
return err return err
} }
@ -131,6 +132,7 @@ func NewEntryRepository(db Database, register *app.EntryTypeRegistry) repository
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
type TEXT NOT NULL, type TEXT NOT NULL,
published_at DATETIME, published_at DATETIME,
author_id TEXT NOT NULL,
meta_data TEXT NOT NULL meta_data TEXT NOT NULL
); );
`) `)
@ -151,5 +153,6 @@ func (r *DefaultEntryRepo) sqlEntryToEntry(entry sqlEntry) (model.Entry, error)
e.SetID(entry.Id) e.SetID(entry.Id)
e.SetPublishedAt(entry.PublishedAt) e.SetPublishedAt(entry.PublishedAt)
e.SetMetaData(metaData) e.SetMetaData(metaData)
e.SetAuthorId(entry.AuthorId)
return e, nil return e, nil
} }

View File

@ -25,6 +25,7 @@ func TestRepoCreate(t *testing.T) {
entry := &test.MockEntry{} entry := &test.MockEntry{}
now := time.Now() now := time.Now()
entry.SetPublishedAt(&now) entry.SetPublishedAt(&now)
entry.SetAuthorId("authorId")
entry.SetMetaData(&test.MockEntryMetaData{ entry.SetMetaData(&test.MockEntryMetaData{
Str: "str", Str: "str",
Number: 1, Number: 1,
@ -37,6 +38,7 @@ func TestRepoCreate(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, entry.ID(), entry2.ID()) require.Equal(t, entry.ID(), entry2.ID())
require.Equal(t, entry.Content(), entry2.Content()) require.Equal(t, entry.Content(), entry2.Content())
require.Equal(t, entry.AuthorId(), entry2.AuthorId())
require.Equal(t, entry.PublishedAt().Unix(), entry2.PublishedAt().Unix()) require.Equal(t, entry.PublishedAt().Unix(), entry2.PublishedAt().Unix())
meta := entry.MetaData().(*test.MockEntryMetaData) meta := entry.MetaData().(*test.MockEntryMetaData)
meta2 := entry2.MetaData().(*test.MockEntryMetaData) meta2 := entry2.MetaData().(*test.MockEntryMetaData)
@ -113,6 +115,7 @@ func TestRepoUpdate(t *testing.T) {
entry := &test.MockEntry{} entry := &test.MockEntry{}
now := time.Now() now := time.Now()
entry.SetPublishedAt(&now) entry.SetPublishedAt(&now)
entry.SetAuthorId("authorId")
entry.SetMetaData(&test.MockEntryMetaData{ entry.SetMetaData(&test.MockEntryMetaData{
Str: "str", Str: "str",
Number: 1, Number: 1,
@ -124,6 +127,7 @@ func TestRepoUpdate(t *testing.T) {
entry2 := &test.MockEntry{} entry2 := &test.MockEntry{}
now2 := time.Now() now2 := time.Now()
entry2.SetPublishedAt(&now2) entry2.SetPublishedAt(&now2)
entry.SetAuthorId("authorId2")
entry2.SetMetaData(&test.MockEntryMetaData{ entry2.SetMetaData(&test.MockEntryMetaData{
Str: "str2", Str: "str2",
Number: 2, Number: 2,
@ -138,6 +142,7 @@ func TestRepoUpdate(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, entry3.Content(), entry2.Content()) require.Equal(t, entry3.Content(), entry2.Content())
require.Equal(t, entry3.PublishedAt().Unix(), entry2.PublishedAt().Unix()) require.Equal(t, entry3.PublishedAt().Unix(), entry2.PublishedAt().Unix())
require.Equal(t, entry3.AuthorId(), entry2.AuthorId())
meta := entry3.MetaData().(*test.MockEntryMetaData) meta := entry3.MetaData().(*test.MockEntryMetaData)
meta2 := entry2.MetaData().(*test.MockEntryMetaData) meta2 := entry2.MetaData().(*test.MockEntryMetaData)
require.Equal(t, meta.Str, meta2.Str) require.Equal(t, meta.Str, meta2.Str)

View File

@ -70,6 +70,7 @@ func (h *EditorHandler) HandlePost(c *fiber.Ctx) error {
// create entry // create entry
now := time.Now() now := time.Now()
entry.SetPublishedAt(&now) entry.SetPublishedAt(&now)
entry.SetAuthorId(c.Locals("author").(string))
err = h.entrySvc.Create(entry) err = h.entrySvc.Create(entry)
if err != nil { if err != nil {

View File

@ -32,9 +32,9 @@ func (h *EntryHandler) Handle(c *fiber.Ctx) error {
return err return err
} }
author, err := h.authorSvc.FindByName("h4kor") author, err := h.authorSvc.FindByName(entry.AuthorId())
if err != nil { if err != nil {
return err author = &model.Author{}
} }
return render.RenderTemplateWithBase(c, "views/entry", entryData{Entry: entry, Author: author}) return render.RenderTemplateWithBase(c, "views/entry", entryData{Entry: entry, Author: author})

View File

@ -22,10 +22,13 @@ func (m *AuthMiddleware) Handle(c *fiber.Ctx) error {
} }
// check token // check token
valid := m.authorService.ValidateToken(token) valid, name := m.authorService.ValidateToken(token)
if !valid { if !valid {
return c.Redirect("/auth/login") return c.Redirect("/auth/login")
} }
// set author name to context
c.Locals("author", name)
return c.Next() return c.Next()
} }