v2 #43
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¬e)
|
|
||||||
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue