mirror of https://github.com/sunface/rust-course
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
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))
|
|
}
|
|
}
|
|
}
|