Compare commits

...

5 commits

13 changed files with 102 additions and 21 deletions

View file

@ -60,6 +60,16 @@ export default class PosteditController extends Controller {
try { try {
const formData = new FormData(this.element); const formData = new FormData(this.element);
let data = Object.fromEntries(formData.entries()); let data = Object.fromEntries(formData.entries());
// Special handling for categories
let categoryIDs = [];
for (let i of formData.entries()) {
if (i[0] === "category_ids") {
categoryIDs.push(parseInt(i[1]))
}
}
data["category_ids"] = categoryIDs;
data = {...data, action: action || 'save'}; data = {...data, action: action || 'save'};
const response = await fetch(this.element.getAttribute("action"), { const response = await fetch(this.element.getAttribute("action"), {

View file

@ -37,9 +37,8 @@ func (lh *LoginHandler) Logout(c fiber.Ctx) error {
func (lh *LoginHandler) DoLogin(c fiber.Ctx) error { func (lh *LoginHandler) DoLogin(c fiber.Ctx) error {
var req struct { var req struct {
Username string `form:"username"` Username string `form:"username"`
Password string `form:"password"` Password string `form:"password"`
LoginChallenge string `form:"_login_challenge"`
} }
if err := c.Bind().Body(&req); err != nil { if err := c.Bind().Body(&req); err != nil {
return c.Status(fiber.StatusBadRequest).SendString("Failed to parse request body") return c.Status(fiber.StatusBadRequest).SendString("Failed to parse request body")
@ -51,11 +50,6 @@ func (lh *LoginHandler) DoLogin(c fiber.Ctx) error {
sess := session.FromContext(c) sess := session.FromContext(c)
challenge, _ := sess.Get("_login_challenge").(string)
if challenge != req.LoginChallenge {
return c.Redirect().To("/login")
}
user, err := lh.AuthService.Login(c.Context(), req.Username, req.Password) user, err := lh.AuthService.Login(c.Context(), req.Username, req.Password)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString("Failed to login") return c.Status(fiber.StatusInternalServerError).SendString("Failed to login")

View file

@ -82,8 +82,8 @@ func (db *Provider) SelectCategoriesOfPost(ctx context.Context, postID int64) ([
return cats, nil return cats, nil
} }
func (db *Provider) SelectPostsOfCategory(ctx context.Context, categoryID int64, pp PagingParams) ([]*models.Post, error) { func (db *Provider) SelectPublishedPostsOfCategory(ctx context.Context, categoryID int64, pp PagingParams) ([]*models.Post, error) {
rows, err := db.queries.SelectPostsOfCategory(ctx, sqlgen.SelectPostsOfCategoryParams{ rows, err := db.queries.SelectPublishedPostsOfCategory(ctx, sqlgen.SelectPublishedPostsOfCategoryParams{
CategoryID: categoryID, CategoryID: categoryID,
Limit: pp.Limit, Limit: pp.Limit,
Offset: pp.Offset, Offset: pp.Offset,

View file

@ -227,7 +227,7 @@ func (q *Queries) SelectCategoryBySlugAndSite(ctx context.Context, arg SelectCat
return i, err return i, err
} }
const selectPostsOfCategory = `-- name: SelectPostsOfCategory :many const selectPublishedPostsOfCategory = `-- name: SelectPublishedPostsOfCategory :many
SELECT p.id, p.site_id, p.state, p.guid, p.title, p.body, p.slug, p.created_at, p.updated_at, p.published_at, p.deleted_at FROM posts p SELECT p.id, p.site_id, p.state, p.guid, p.title, p.body, p.slug, p.created_at, p.updated_at, p.published_at, p.deleted_at FROM posts p
INNER JOIN post_categories pc ON pc.post_id = p.id INNER JOIN post_categories pc ON pc.post_id = p.id
WHERE pc.category_id = ? AND p.state = 0 AND p.deleted_at = 0 WHERE pc.category_id = ? AND p.state = 0 AND p.deleted_at = 0
@ -235,14 +235,14 @@ ORDER BY p.published_at DESC
LIMIT ? OFFSET ? LIMIT ? OFFSET ?
` `
type SelectPostsOfCategoryParams struct { type SelectPublishedPostsOfCategoryParams struct {
CategoryID int64 CategoryID int64
Limit int64 Limit int64
Offset int64 Offset int64
} }
func (q *Queries) SelectPostsOfCategory(ctx context.Context, arg SelectPostsOfCategoryParams) ([]Post, error) { func (q *Queries) SelectPublishedPostsOfCategory(ctx context.Context, arg SelectPublishedPostsOfCategoryParams) ([]Post, error) {
rows, err := q.db.QueryContext(ctx, selectPostsOfCategory, arg.CategoryID, arg.Limit, arg.Offset) rows, err := q.db.QueryContext(ctx, selectPublishedPostsOfCategory, arg.CategoryID, arg.Limit, arg.Offset)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -200,6 +200,54 @@ func (q *Queries) SelectPostsOfSite(ctx context.Context, arg SelectPostsOfSitePa
return items, nil return items, nil
} }
const selectPublishedPostsOfSite = `-- name: SelectPublishedPostsOfSite :many
SELECT id, site_id, state, guid, title, body, slug, created_at, updated_at, published_at, deleted_at
FROM posts
WHERE site_id = ?1 AND state = 0 AND deleted_at = 0
ORDER BY published_at DESC LIMIT ?3 OFFSET ?2
`
type SelectPublishedPostsOfSiteParams struct {
SiteID int64
Offset int64
Limit int64
}
func (q *Queries) SelectPublishedPostsOfSite(ctx context.Context, arg SelectPublishedPostsOfSiteParams) ([]Post, error) {
rows, err := q.db.QueryContext(ctx, selectPublishedPostsOfSite, arg.SiteID, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Post
for rows.Next() {
var i Post
if err := rows.Scan(
&i.ID,
&i.SiteID,
&i.State,
&i.Guid,
&i.Title,
&i.Body,
&i.Slug,
&i.CreatedAt,
&i.UpdatedAt,
&i.PublishedAt,
&i.DeletedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const softDeletePost = `-- name: SoftDeletePost :exec const softDeletePost = `-- name: SoftDeletePost :exec
UPDATE posts SET deleted_at = ? WHERE id = ? UPDATE posts SET deleted_at = ? WHERE id = ?
` `

View file

@ -47,6 +47,23 @@ func (db *Provider) SelectPostsOfSite(ctx context.Context, siteID int64, showDel
return posts, nil return posts, nil
} }
func (db *Provider) SelectPublishedPostsOfSite(ctx context.Context, siteID int64, pp PagingParams) ([]*models.Post, error) {
rows, err := db.queries.SelectPublishedPostsOfSite(ctx, sqlgen.SelectPublishedPostsOfSiteParams{
SiteID: siteID,
Limit: pp.Limit,
Offset: pp.Offset,
})
if err != nil {
return nil, err
}
posts := make([]*models.Post, len(rows))
for i, row := range rows {
posts[i] = dbPostToPost(row)
}
return posts, nil
}
func (db *Provider) SelectPost(ctx context.Context, postID int64) (*models.Post, error) { func (db *Provider) SelectPost(ctx context.Context, postID int64) (*models.Post, error) {
row, err := db.queries.SelectPost(ctx, postID) row, err := db.queries.SelectPost(ctx, postID)
if err != nil { if err != nil {

View file

@ -22,7 +22,7 @@ type Renderer struct {
func NewRendererForUI() *Renderer { func NewRendererForUI() *Renderer {
mdParser := goldmark.New( mdParser := goldmark.New(
goldmark.WithExtensions(extension.GFM), goldmark.WithExtensions(extension.GFM, extension.Footnote),
goldmark.WithRendererOptions( goldmark.WithRendererOptions(
gm_html.WithUnsafe(), gm_html.WithUnsafe(),
), ),
@ -48,7 +48,7 @@ func NewRendererForUI() *Renderer {
func NewRendererForSite() *Renderer { func NewRendererForSite() *Renderer {
mdParser := goldmark.New( mdParser := goldmark.New(
goldmark.WithExtensions(extension.GFM), goldmark.WithExtensions(extension.GFM, extension.Footnote),
goldmark.WithParserOptions( goldmark.WithParserOptions(
parser.WithAutoHeadingID(), parser.WithAutoHeadingID(),
), ),

View file

@ -49,6 +49,7 @@ func New(site pubmodel.Site, opts Options) (*Builder, error) {
mdRenderer: markdown.NewRendererForSite(), mdRenderer: markdown.NewRendererForSite(),
postMDProcessors: []postMDProcessor{ postMDProcessors: []postMDProcessor{
uploadAbsoluteURL, uploadAbsoluteURL,
removeFootnoteHRs,
}, },
}, nil }, nil
} }

View file

@ -35,3 +35,8 @@ func uploadAbsoluteURL(site pubmodel.Site, dom *goquery.Document) error {
}) })
return nil return nil
} }
func removeFootnoteHRs(site pubmodel.Site, dom *goquery.Document) error {
dom.Find("div.footnotes > hr").Remove()
return nil
}

View file

@ -9,10 +9,10 @@ import (
) )
// postIter returns a post iterator which returns posts in reverse chronological order. // postIter returns a post iterator which returns posts in reverse chronological order.
func (s *Publisher) postIter(ctx context.Context, site int64) iter.Seq[models.Maybe[*models.Post]] { func (s *Publisher) publishedPostIter(ctx context.Context, site int64) iter.Seq[models.Maybe[*models.Post]] {
return func(yield func(models.Maybe[*models.Post]) bool) { return func(yield func(models.Maybe[*models.Post]) bool) {
paging := db.PagingParams{Offset: 0, Limit: 50} paging := db.PagingParams{Offset: 0, Limit: 50}
page, err := s.db.SelectPostsOfSite(ctx, site, false, paging) page, err := s.db.SelectPublishedPostsOfSite(ctx, site, paging)
if err != nil { if err != nil {
yield(models.Maybe[*models.Post]{Err: err}) yield(models.Maybe[*models.Post]{Err: err})
return return
@ -45,7 +45,7 @@ func (s *Publisher) postIterByCategory(ctx context.Context, categoryID int64) it
return func(yield func(models.Maybe[*models.Post]) bool) { return func(yield func(models.Maybe[*models.Post]) bool) {
paging := db.PagingParams{Offset: 0, Limit: 50} paging := db.PagingParams{Offset: 0, Limit: 50}
for { for {
page, err := s.db.SelectPostsOfCategory(ctx, categoryID, paging) page, err := s.db.SelectPublishedPostsOfCategory(ctx, categoryID, paging)
if err != nil { if err != nil {
yield(models.Maybe[*models.Post]{Err: err}) yield(models.Maybe[*models.Post]{Err: err})
return return

View file

@ -79,7 +79,7 @@ func (p *Publisher) Publish(ctx context.Context, site models.Site) error {
pubSite := pubmodel.Site{ pubSite := pubmodel.Site{
Site: site, Site: site,
PostIter: func(ctx context.Context) iter.Seq[models.Maybe[*models.Post]] { PostIter: func(ctx context.Context) iter.Seq[models.Maybe[*models.Post]] {
return p.postIter(ctx, site.ID) return p.publishedPostIter(ctx, site.ID)
}, },
BaseURL: target.BaseURL, BaseURL: target.BaseURL,
Uploads: uploads, Uploads: uploads,

View file

@ -17,7 +17,7 @@ INNER JOIN post_categories pc ON pc.category_id = c.id
WHERE pc.post_id = ? WHERE pc.post_id = ?
ORDER BY c.name ASC; ORDER BY c.name ASC;
-- name: SelectPostsOfCategory :many -- name: SelectPublishedPostsOfCategory :many
SELECT p.* FROM posts p SELECT p.* FROM posts p
INNER JOIN post_categories pc ON pc.post_id = p.id INNER JOIN post_categories pc ON pc.post_id = p.id
WHERE pc.category_id = ? AND p.state = 0 AND p.deleted_at = 0 WHERE pc.category_id = ? AND p.state = 0 AND p.deleted_at = 0

View file

@ -17,6 +17,12 @@ WHERE site_id = sqlc.arg(site_id) AND (
END END
) ORDER BY created_at DESC LIMIT sqlc.arg(limit) OFFSET sqlc.arg(offset); ) ORDER BY created_at DESC LIMIT sqlc.arg(limit) OFFSET sqlc.arg(offset);
-- name: SelectPublishedPostsOfSite :many
SELECT *
FROM posts
WHERE site_id = sqlc.arg(site_id) AND state = 0 AND deleted_at = 0
ORDER BY published_at DESC LIMIT sqlc.arg(limit) OFFSET sqlc.arg(offset);
-- name: SelectPost :one -- name: SelectPost :one
SELECT * FROM posts WHERE id = ? LIMIT 1; SELECT * FROM posts WHERE id = ? LIMIT 1;