You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
6.5 KiB

package post
import (
"encoding/json"
"net/http"
"time"
"github.com/labstack/echo"
"github.com/thinkindev/im.dev/internal/ecode"
"github.com/thinkindev/im.dev/internal/misc"
"github.com/thinkindev/im.dev/internal/user"
"github.com/thinkindev/im.dev/internal/utils"
"go.uber.org/zap"
)
// ArContent represent article content
type ArContent struct {
ID string `json:"id"`
Title string `json:"title"`
Tags []string `json:"tags"`
MD string `json:"md"`
Render string `json:"render"`
Lang string `json:"lang"`
Status int `json:"status"`
}
// NewArticle create a new article
func NewArticle(c echo.Context) error {
opType := c.FormValue("type")
if opType != "1" && opType != "2" {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
content := c.FormValue("content")
ar := &ArContent{}
err := json.Unmarshal([]byte(content), &ar)
if err != nil {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
sess := user.GetSession(c)
// generate id for article
ar.ID = misc.GenID()
// modify render
ar.Render = modify(ar.Render)
err = misc.CQL.Query(`INSERT INTO article (id,uid,title,tags,md,render,status,edit_date,lang)
VALUES (?,?,?,?,?,?,?,?,?)`, ar.ID, sess.ID, ar.Title, ar.Tags, ar.MD, ar.Render, opType, time.Now().Unix(), ar.Lang).Exec()
if err != nil {
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
saveTags(ar.ID, ar.Tags)
return c.JSON(http.StatusOK, misc.HTTPResp{
Data: sess.Name + "/" + ar.ID,
})
}
// ArticleDetail contains detail data of article
type ArticleDetail struct {
ID string `json:"id"`
UID string `json:"uid"`
Title string `json:"title"`
Tags []string `json:"tags"`
Render string `json:"render"`
Status int `json:"status"`
PublishDate string `json:"publish_date"`
EditDate string `json:"edit_date"`
Lang string `json:"lang"`
pubDate int64
editDate int64
}
// GetArticleDetail return detail data of the article
func GetArticleDetail(c echo.Context) error {
arID := c.FormValue("article_id")
if arID == "" {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
detail := &ArticleDetail{ID: arID}
err := misc.CQL.Query(`SELECT uid,title,tags,render,status,publish_date,edit_date,lang FROM article WHERE id=?`, arID).Scan(
&detail.UID, &detail.Title, &detail.Tags, &detail.Render, &detail.Status, &detail.pubDate, &detail.editDate, &detail.Lang,
)
if err != nil {
if err.Error() == misc.CQLNotFound {
return c.JSON(http.StatusNotFound, misc.HTTPResp{
ErrCode: ecode.ArticleNotFound,
Message: ecode.ArticleNotFoundMsg,
})
}
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
if detail.pubDate != 0 {
detail.PublishDate = utils.Time2ReadableString(time.Unix(detail.pubDate, 0))
}
if detail.editDate != 0 {
detail.EditDate = utils.Time2ReadableString(time.Unix(detail.editDate, 0))
}
return c.JSON(http.StatusOK, misc.HTTPResp{
Data: detail,
})
}
// BeforeEditAr deal some pre-things before editing article
func BeforeEditAr(c echo.Context) error {
arID := c.FormValue("article_id")
if arID == "" {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
var uid, title, md, lang string
var tags []string
var status int
err := misc.CQL.Query(`SELECT uid,title,tags,md,lang,status FROM article WHERE id=?`, arID).Scan(
&uid, &title, &tags, &md, &lang, &status,
)
if err != nil {
if err.Error() == misc.CQLNotFound {
return c.JSON(http.StatusNotFound, misc.HTTPResp{
ErrCode: ecode.ArticleNotFound,
Message: ecode.ArticleNotFoundMsg,
})
}
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
sess := user.GetSession(c)
// check whether user has permission to do so
if uid != sess.ID {
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.NoPermission,
Message: ecode.NoPermissionMsg,
})
}
ar := &ArContent{
ID: arID,
Title: title,
MD: md,
Tags: tags,
Lang: lang,
Status: status,
}
return c.JSON(http.StatusOK, misc.HTTPResp{
Data: ar,
})
}
// SaveArticleChanges save changes when edit article
func SaveArticleChanges(c echo.Context) error {
content := c.FormValue("content")
ar := &ArContent{}
err := json.Unmarshal([]byte(content), &ar)
if err != nil {
return c.JSON(http.StatusBadRequest, misc.HTTPResp{
ErrCode: ecode.ParamInvalid,
Message: ecode.ParamInvalidMsg,
})
}
// check the article is exist and user has permission
var uid string
err = misc.CQL.Query(`SELECT uid FROM article WHERE id=?`, ar.ID).Scan(&uid)
if err != nil {
if err.Error() == misc.CQLNotFound {
return c.JSON(http.StatusNotFound, misc.HTTPResp{
ErrCode: ecode.ArticleNotFound,
Message: ecode.ArticleNotFoundMsg,
})
}
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
sess := user.GetSession(c)
if sess.ID != uid {
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.NoPermission,
Message: ecode.NoPermissionMsg,
})
}
// modify render
ar.Render = modify(ar.Render)
err = misc.CQL.Query(`UPDATE article SET title=?,tags=?,md=?,render=?,edit_date=?,lang=? WHERE id=?`,
ar.Title, ar.Tags, ar.MD, ar.Render, time.Now().Unix(), ar.Lang, ar.ID).Exec()
if err != nil {
misc.Log.Warn("access database error", zap.Error(err))
return c.JSON(http.StatusInternalServerError, misc.HTTPResp{
ErrCode: ecode.DatabaseError,
Message: ecode.CommonErrorMsg,
})
}
saveTags(ar.ID, ar.Tags)
return c.JSON(http.StatusOK, misc.HTTPResp{
Data: sess.Name + "/" + ar.ID,
})
}
func saveTags(arID string, tags []string) {
for _, tag := range tags {
err := misc.CQL.Query(`INSERT INTO tags (name,article_id) VALUES (?,?)`, tag, arID).Exec()
if err != nil {
misc.Log.Warn("access database error", zap.Error(err))
}
}
}