list definitions in user config

This commit is contained in:
Niko Abeler 2022-12-01 19:10:08 +01:00
parent 3fe828d31d
commit 58cd92a4b4
6 changed files with 188 additions and 6 deletions

View File

@ -64,6 +64,40 @@ func userIndexHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Requ
} }
} }
func postListHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
listId := ps.ByName("list")
user, err := getUserFromRepo(repo, ps)
if err != nil {
println("Error getting user: ", err.Error())
notFoundHandler(repo)(w, r)
return
}
list, err := user.GetPostList(listId)
if err != nil {
println("Error getting post list: ", err.Error())
notFoundUserHandler(repo, user)(w, r)
return
}
html, err := owl.RenderPostList(user, list)
if err != nil {
println("Error rendering index page: ", err.Error())
w.WriteHeader(http.StatusInternalServerError)
html, _ := owl.RenderUserError(user, owl.ErrorMessage{
Error: "Internal server error",
Message: "Internal server error",
})
w.Write([]byte(html))
return
}
println("Rendering index page for user", user.Name())
w.Write([]byte(html))
}
}
func userWebmentionHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) { func userWebmentionHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user, err := getUserFromRepo(repo, ps) user, err := getUserFromRepo(repo, ps)

View File

@ -14,6 +14,7 @@ func Router(repo *owl.Repository) http.Handler {
router.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir())) router.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir()))
router.GET("/", repoIndexHandler(repo)) router.GET("/", repoIndexHandler(repo))
router.GET("/user/:user/", userIndexHandler(repo)) router.GET("/user/:user/", userIndexHandler(repo))
router.GET("/user/:user/lists/:list/", postListHandler(repo))
// Editor // Editor
router.GET("/user/:user/editor/auth/", userLoginGetHandler(repo)) router.GET("/user/:user/editor/auth/", userLoginGetHandler(repo))
router.POST("/user/:user/editor/auth/", userLoginPostHandler(repo)) router.POST("/user/:user/editor/auth/", userLoginPostHandler(repo))
@ -44,6 +45,7 @@ func SingleUserRouter(repo *owl.Repository) http.Handler {
router := httprouter.New() router := httprouter.New()
router.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir())) router.ServeFiles("/static/*filepath", http.Dir(repo.StaticDir()))
router.GET("/", userIndexHandler(repo)) router.GET("/", userIndexHandler(repo))
router.GET("/lists/:list/", postListHandler(repo))
// Editor // Editor
router.GET("/editor/auth/", userLoginGetHandler(repo)) router.GET("/editor/auth/", userLoginGetHandler(repo))
router.POST("/editor/auth/", userLoginPostHandler(repo)) router.POST("/editor/auth/", userLoginPostHandler(repo))

View File

@ -99,3 +99,34 @@ func TestHasNoDraftsInList(t *testing.T) {
// Check if title is in the response body // Check if title is in the response body
assertions.AssertNotContains(t, rr.Body.String(), "Articles September 2019") assertions.AssertNotContains(t, rr.Body.String(), "Articles September 2019")
} }
func TestSingleUserUserPostListHandler(t *testing.T) {
repo, user := getSingleUserTestRepo()
user.CreateNewPostFull(owl.PostMeta{
Title: "post-1",
Type: "article",
}, "hi")
user.CreateNewPostFull(owl.PostMeta{
Title: "post-2",
Type: "note",
}, "hi")
list := owl.PostList{
Title: "list-1",
Id: "list-1",
Include: []string{"article"},
}
user.AddPostList(list)
// Create Request and Response
req, err := http.NewRequest("GET", user.ListUrl(list), nil)
assertions.AssertNoError(t, err, "Error creating request")
rr := httptest.NewRecorder()
router := main.SingleUserRouter(&repo)
router.ServeHTTP(rr, req)
assertions.AssertStatus(t, rr, http.StatusOK)
// Check the response body contains names of users
assertions.AssertContains(t, rr.Body.String(), "post-1")
assertions.AssertNotContains(t, rr.Body.String(), "post-2")
}

View File

@ -133,6 +133,19 @@ func RenderIndexPage(user User) (string, error) {
}) })
} }
func RenderPostList(user User, list *PostList) (string, error) {
posts, _ := user.GetPostsOfList(*list)
postHtml, err := renderEmbedTemplate("embed/post-list.html", posts)
if err != nil {
return "", err
}
return renderIntoBaseTemplate(user, PageContent{
Title: "Index",
Content: template.HTML(postHtml),
})
}
func RenderUserAuthPage(reqData AuthRequestData) (string, error) { func RenderUserAuthPage(reqData AuthRequestData) (string, error) {
reqData.Scopes = strings.Split(reqData.Scope, " ") reqData.Scopes = strings.Split(reqData.Scope, " ")
authHtml, err := renderEmbedTemplate("embed/auth.html", reqData) authHtml, err := renderEmbedTemplate("embed/auth.html", reqData)

View File

@ -77,6 +77,53 @@ func TestRendererUsesBaseTemplate(t *testing.T) {
assertions.AssertContains(t, result, "<html") assertions.AssertContains(t, result, "<html")
} }
func TestCanRenderPostList(t *testing.T) {
user := getTestUser()
user.CreateNewPost("testpost1", false)
user.CreateNewPost("testpost2", false)
result, _ := owl.RenderPostList(user, &owl.PostList{
Id: "testlist",
Title: "Test List",
Include: []string{
"article",
},
})
assertions.AssertContains(t, result, "testpost1")
assertions.AssertContains(t, result, "testpost2")
}
func TestCanRenderPostListNotIncludeOther(t *testing.T) {
user := getTestUser()
user.CreateNewPostFull(owl.PostMeta{Title: "testpost1", Type: "article"}, "testpost1")
user.CreateNewPostFull(owl.PostMeta{Title: "testpost2", Type: "note"}, "testpost2")
result, _ := owl.RenderPostList(user, &owl.PostList{
Id: "testlist",
Title: "Test List",
Include: []string{
"article",
},
})
assertions.AssertContains(t, result, "testpost1")
assertions.AssertNotContains(t, result, "testpost2")
}
func TestCanRenderPostListNotIncludeMultiple(t *testing.T) {
user := getTestUser()
user.CreateNewPostFull(owl.PostMeta{Title: "testpost1", Type: "article"}, "testpost1")
user.CreateNewPostFull(owl.PostMeta{Title: "testpost2", Type: "note"}, "testpost2")
user.CreateNewPostFull(owl.PostMeta{Title: "testpost3", Type: "recipe"}, "testpost3")
result, _ := owl.RenderPostList(user, &owl.PostList{
Id: "testlist",
Title: "Test List",
Include: []string{
"article", "recipe",
},
})
assertions.AssertContains(t, result, "testpost1")
assertions.AssertNotContains(t, result, "testpost2")
assertions.AssertContains(t, result, "testpost3")
}
func TestCanRenderIndexPage(t *testing.T) { func TestCanRenderIndexPage(t *testing.T) {
user := getTestUser() user := getTestUser()
user.CreateNewPost("testpost1", false) user.CreateNewPost("testpost1", false)

67
user.go
View File

@ -20,12 +20,28 @@ type User struct {
} }
type UserConfig struct { type UserConfig struct {
Title string `yaml:"title"` Title string `yaml:"title"`
SubTitle string `yaml:"subtitle"` SubTitle string `yaml:"subtitle"`
HeaderColor string `yaml:"header_color"` HeaderColor string `yaml:"header_color"`
AuthorName string `yaml:"author_name"` AuthorName string `yaml:"author_name"`
Me []UserMe `yaml:"me"` Me []UserMe `yaml:"me"`
PassworHash string `yaml:"password_hash"` PassworHash string `yaml:"password_hash"`
Lists []PostList `yaml:"lists"`
}
type PostList struct {
Id string `yaml:"id"`
Title string `yaml:"title"`
Include []string `yaml:"include"`
}
func (l *PostList) ContainsType(t string) bool {
for _, t2 := range l.Include {
if t2 == t {
return true
}
}
return false
} }
type UserMe struct { type UserMe struct {
@ -66,6 +82,11 @@ func (user User) UrlPath() string {
return user.repo.UserUrlPath(user) return user.repo.UserUrlPath(user)
} }
func (user User) ListUrl(list PostList) string {
url, _ := url.JoinPath(user.UrlPath(), "lists/"+list.Id+"/")
return url
}
func (user User) FullUrl() string { func (user User) FullUrl() string {
url, _ := url.JoinPath(user.repo.FullUrl(), user.UrlPath()) url, _ := url.JoinPath(user.repo.FullUrl(), user.UrlPath())
return url return url
@ -234,6 +255,22 @@ func (user User) PrimaryFeedPosts() ([]*Post, error) {
return posts, nil return posts, nil
} }
func (user User) GetPostsOfList(list PostList) ([]*Post, error) {
posts, _ := user.PublishedPosts()
// remove posts not included
n := 0
for _, post := range posts {
meta := post.Meta()
if list.ContainsType(meta.Type) {
posts[n] = post
n++
}
}
posts = posts[:n]
return posts, nil
}
func (user User) GetPost(id string) (*Post, error) { func (user User) GetPost(id string) (*Post, error) {
// check if posts index.md exists // check if posts index.md exists
if !fileExists(path.Join(user.Dir(), "public", id, "index.md")) { if !fileExists(path.Join(user.Dir(), "public", id, "index.md")) {
@ -337,6 +374,24 @@ func (user User) PostAliases() (map[string]*Post, error) {
return post_aliases, nil return post_aliases, nil
} }
func (user User) GetPostList(id string) (*PostList, error) {
lists := user.Config().Lists
for _, list := range lists {
if list.Id == id {
return &list, nil
}
}
return &PostList{}, fmt.Errorf("list %s does not exist", id)
}
func (user User) AddPostList(list PostList) error {
config := user.Config()
config.Lists = append(config.Lists, list)
return user.SetConfig(config)
}
func (user User) ResetPassword(password string) error { func (user User) ResetPassword(password string) error {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 10) bytes, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil { if err != nil {