diff --git a/app/author_service.go b/app/author_service.go index 7b27747..64257b0 100644 --- a/app/author_service.go +++ b/app/author_service.go @@ -62,7 +62,7 @@ func (s *AuthorService) CreateToken(name string) (string, error) { 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, ".") witness := 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() _, err := hash.Write([]byte(name + s.getSecretKey())) if err != nil { - return false + return false, "" } - return fmt.Sprintf("%x", hash.Sum(nil)) == witness + return fmt.Sprintf("%x", hash.Sum(nil)) == witness, name } diff --git a/app/author_service_test.go b/app/author_service_test.go index 3c9a03c..2b419f4 100644 --- a/app/author_service_test.go +++ b/app/author_service_test.go @@ -71,9 +71,15 @@ func TestAuthorValidateToken(t *testing.T) { token, err := authorService.CreateToken("test") require.NoError(t, err) - require.True(t, authorService.ValidateToken(token)) - require.False(t, authorService.ValidateToken(token[:len(token)-2])) - require.False(t, authorService.ValidateToken("test")) - require.False(t, authorService.ValidateToken("test.test")) - require.False(t, authorService.ValidateToken(strings.Replace(token, "test", "test1", 1))) + valid, name := authorService.ValidateToken(token) + require.True(t, valid) + require.Equal(t, "test", name) + valid, _ = authorService.ValidateToken(token[:len(token)-2]) + 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) } diff --git a/cmd/owl/import_v1.go b/cmd/owl/import_v1.go index 69f9b42..1eb68a1 100644 --- a/cmd/owl/import_v1.go +++ b/cmd/owl/import_v1.go @@ -12,12 +12,15 @@ import ( ) var userPath string +var author string func init() { rootCmd.AddCommand(importCmd) importCmd.Flags().StringVarP(&userPath, "path", "p", "", "Path to the user folder") importCmd.MarkFlagRequired("path") + importCmd.Flags().StringVarP(&author, "author", "a", "", "The author name") + importCmd.MarkFlagRequired("author") } var importCmd = &cobra.Command{ @@ -56,63 +59,64 @@ var importCmd = &cobra.Command{ app.BinaryService.CreateEntryFile(file, fileData, entry) } + var entry model.Entry + switch post.Meta.Type { case "article": - article := model.Article{} - article.SetID(post.Id) - article.SetPublishedAt(&post.Meta.Date) - article.SetMetaData(&model.ArticleMetaData{ + entry = &model.Article{} + entry.SetID(post.Id) + entry.SetPublishedAt(&post.Meta.Date) + entry.SetMetaData(&model.ArticleMetaData{ Title: post.Meta.Title, Content: post.Content, }) - app.EntryService.Create(&article) case "bookmark": case "reply": case "photo": - photo := model.Image{} - photo.SetID(post.Id) - photo.SetPublishedAt(&post.Meta.Date) - photo.SetMetaData(&model.ImageMetaData{ + entry = &model.Image{} + entry.SetID(post.Id) + entry.SetPublishedAt(&post.Meta.Date) + entry.SetMetaData(&model.ImageMetaData{ Title: post.Meta.Title, Content: post.Content, ImageId: post.Meta.PhotoPath, }) - app.EntryService.Create(&photo) case "note": - note := model.Note{} - note.SetID(post.Id) - note.SetPublishedAt(&post.Meta.Date) - note.SetMetaData(&model.NoteMetaData{ + entry = &model.Note{} + entry.SetID(post.Id) + entry.SetPublishedAt(&post.Meta.Date) + entry.SetMetaData(&model.NoteMetaData{ Content: post.Content, }) - app.EntryService.Create(¬e) case "recipe": - recipe := model.Recipe{} - recipe.SetID(post.Id) - recipe.SetPublishedAt(&post.Meta.Date) - recipe.SetMetaData(&model.RecipeMetaData{ + entry = &model.Recipe{} + entry.SetID(post.Id) + entry.SetPublishedAt(&post.Meta.Date) + entry.SetMetaData(&model.RecipeMetaData{ Title: post.Meta.Title, Yield: post.Meta.Recipe.Yield, Duration: post.Meta.Recipe.Duration, Ingredients: post.Meta.Recipe.Ingredients, Content: post.Content, }) - app.EntryService.Create(&recipe) case "page": - page := model.Page{} - page.SetID(post.Id) - page.SetPublishedAt(&post.Meta.Date) - page.SetMetaData(&model.PageMetaData{ + entry = &model.Page{} + entry.SetID(post.Id) + entry.SetPublishedAt(&post.Meta.Date) + entry.SetMetaData(&model.PageMetaData{ Title: post.Meta.Title, Content: post.Content, }) - app.EntryService.Create(&page) default: panic("Unknown type") } + if entry != nil { + entry.SetAuthorId(author) + app.EntryService.Create(entry) + } } }, } diff --git a/domain/model/entry.go b/domain/model/entry.go index 4f499f8..b9372c2 100644 --- a/domain/model/entry.go +++ b/domain/model/entry.go @@ -8,6 +8,7 @@ type Entry interface { ID() string Content() EntryContent PublishedAt() *time.Time + AuthorId() string MetaData() interface{} // Optional: can return empty string @@ -16,6 +17,7 @@ type Entry interface { SetID(id string) SetPublishedAt(publishedAt *time.Time) SetMetaData(metaData interface{}) + SetAuthorId(authorId string) } type EntryMetaData interface { @@ -24,6 +26,7 @@ type EntryMetaData interface { type EntryBase struct { id string publishedAt *time.Time + authorId string } func (e *EntryBase) ID() string { @@ -41,3 +44,11 @@ func (e *EntryBase) SetID(id string) { func (e *EntryBase) SetPublishedAt(publishedAt *time.Time) { e.publishedAt = publishedAt } + +func (e *EntryBase) AuthorId() string { + return e.authorId +} + +func (e *EntryBase) SetAuthorId(authorId string) { + e.authorId = authorId +} diff --git a/infra/entry_repository.go b/infra/entry_repository.go index 6f9a7fc..3aad5bb 100644 --- a/infra/entry_repository.go +++ b/infra/entry_repository.go @@ -20,6 +20,7 @@ type sqlEntry struct { Type string `db:"type"` PublishedAt *time.Time `db:"published_at"` MetaData *string `db:"meta_data"` + AuthorId string `db:"author_id"` } type DefaultEntryRepo struct { @@ -43,7 +44,7 @@ func (r *DefaultEntryRepo) Create(entry model.Entry) error { 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 } @@ -118,7 +119,7 @@ func (r *DefaultEntryRepo) Update(entry model.Entry) error { 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 } @@ -131,6 +132,7 @@ func NewEntryRepository(db Database, register *app.EntryTypeRegistry) repository id TEXT PRIMARY KEY, type TEXT NOT NULL, published_at DATETIME, + author_id 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.SetPublishedAt(entry.PublishedAt) e.SetMetaData(metaData) + e.SetAuthorId(entry.AuthorId) return e, nil } diff --git a/infra/entry_repository_test.go b/infra/entry_repository_test.go index a6178c1..458cd42 100644 --- a/infra/entry_repository_test.go +++ b/infra/entry_repository_test.go @@ -25,6 +25,7 @@ func TestRepoCreate(t *testing.T) { entry := &test.MockEntry{} now := time.Now() entry.SetPublishedAt(&now) + entry.SetAuthorId("authorId") entry.SetMetaData(&test.MockEntryMetaData{ Str: "str", Number: 1, @@ -37,6 +38,7 @@ func TestRepoCreate(t *testing.T) { require.NoError(t, err) require.Equal(t, entry.ID(), entry2.ID()) require.Equal(t, entry.Content(), entry2.Content()) + require.Equal(t, entry.AuthorId(), entry2.AuthorId()) require.Equal(t, entry.PublishedAt().Unix(), entry2.PublishedAt().Unix()) meta := entry.MetaData().(*test.MockEntryMetaData) meta2 := entry2.MetaData().(*test.MockEntryMetaData) @@ -113,6 +115,7 @@ func TestRepoUpdate(t *testing.T) { entry := &test.MockEntry{} now := time.Now() entry.SetPublishedAt(&now) + entry.SetAuthorId("authorId") entry.SetMetaData(&test.MockEntryMetaData{ Str: "str", Number: 1, @@ -124,6 +127,7 @@ func TestRepoUpdate(t *testing.T) { entry2 := &test.MockEntry{} now2 := time.Now() entry2.SetPublishedAt(&now2) + entry.SetAuthorId("authorId2") entry2.SetMetaData(&test.MockEntryMetaData{ Str: "str2", Number: 2, @@ -138,6 +142,7 @@ func TestRepoUpdate(t *testing.T) { require.NoError(t, err) require.Equal(t, entry3.Content(), entry2.Content()) require.Equal(t, entry3.PublishedAt().Unix(), entry2.PublishedAt().Unix()) + require.Equal(t, entry3.AuthorId(), entry2.AuthorId()) meta := entry3.MetaData().(*test.MockEntryMetaData) meta2 := entry2.MetaData().(*test.MockEntryMetaData) require.Equal(t, meta.Str, meta2.Str) diff --git a/web/editor_handler.go b/web/editor_handler.go index bb75e94..1075681 100644 --- a/web/editor_handler.go +++ b/web/editor_handler.go @@ -70,6 +70,7 @@ func (h *EditorHandler) HandlePost(c *fiber.Ctx) error { // create entry now := time.Now() entry.SetPublishedAt(&now) + entry.SetAuthorId(c.Locals("author").(string)) err = h.entrySvc.Create(entry) if err != nil { diff --git a/web/entry_handler.go b/web/entry_handler.go index a7bfe1a..f8bd30c 100644 --- a/web/entry_handler.go +++ b/web/entry_handler.go @@ -32,9 +32,9 @@ func (h *EntryHandler) Handle(c *fiber.Ctx) error { return err } - author, err := h.authorSvc.FindByName("h4kor") + author, err := h.authorSvc.FindByName(entry.AuthorId()) if err != nil { - return err + author = &model.Author{} } return render.RenderTemplateWithBase(c, "views/entry", entryData{Entry: entry, Author: author}) diff --git a/web/middleware/auth.go b/web/middleware/auth.go index 5b644e6..6127489 100644 --- a/web/middleware/auth.go +++ b/web/middleware/auth.go @@ -22,10 +22,13 @@ func (m *AuthMiddleware) Handle(c *fiber.Ctx) error { } // check token - valid := m.authorService.ValidateToken(token) + valid, name := m.authorService.ValidateToken(token) if !valid { return c.Redirect("/auth/login") } + // set author name to context + c.Locals("author", name) + return c.Next() }