mindoc/controllers/DocumentController.go

1475 lines
41 KiB
Go
Raw Permalink Normal View History

2017-04-20 18:19:32 +08:00
package controllers
2017-04-26 18:17:38 +08:00
import (
"context"
2017-05-13 13:04:53 +08:00
"encoding/json"
"fmt"
"html/template"
"image/png"
"io"
"mime/multipart"
"net/http"
"net/url"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web"
"github.com/beego/i18n"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
"github.com/mindoc-org/mindoc/conf"
"github.com/mindoc-org/mindoc/models"
"github.com/mindoc-org/mindoc/utils"
"github.com/mindoc-org/mindoc/utils/cryptil"
"github.com/mindoc-org/mindoc/utils/filetil"
"github.com/mindoc-org/mindoc/utils/gopool"
"github.com/mindoc-org/mindoc/utils/pagination"
"github.com/russross/blackfriday/v2"
2017-04-26 18:17:38 +08:00
)
// DocumentController struct
2017-04-20 18:19:32 +08:00
type DocumentController struct {
BaseController
}
// Document prev&next
type DocumentTreeFlatten struct {
DocumentId int `json:"id"`
DocumentName string `json:"text"`
// ParentId interface{} `json:"parent"`
Identify string `json:"identify"`
// BookIdentify string `json:"-"`
// Version int64 `json:"version"`
}
// 文档首页
2017-05-13 13:04:53 +08:00
func (c *DocumentController) Index() {
c.Prepare()
identify := c.Ctx.Input.Param(":key")
token := c.GetString("token")
if identify == "" {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
}
// 如果没有开启匿名访问则跳转到登录
2018-11-14 15:57:55 +08:00
if !c.EnableAnonymous && !c.isUserLoggedIn() {
promptUserToLogIn(c)
return
}
2018-11-14 15:57:55 +08:00
bookResult := c.isReadable(identify, token)
c.TplName = "document/" + bookResult.Theme + "_read.tpl"
selected := 0
if bookResult.IsUseFirstDocument {
doc, err := bookResult.FindFirstDocumentByBookId(bookResult.BookId)
if err == nil {
selected = doc.DocumentId
c.Data["Title"] = doc.DocumentName
c.Data["Content"] = template.HTML(doc.Release)
c.Data["Description"] = utils.AutoSummary(doc.Release, 120)
c.Data["FoldSetting"] = "first"
2022-05-14 20:54:59 +08:00
if bookResult.Editor == EditorCherryMarkdown {
c.Data["MarkdownTheme"] = doc.MarkdownTheme
}
if bookResult.IsDisplayComment {
// 获取评论、分页
comments, count, _ := models.NewComment().QueryCommentByDocumentId(doc.DocumentId, 1, conf.PageSize, c.Member)
page := pagination.PageUtil(int(count), 1, conf.PageSize, comments)
c.Data["Page"] = page
}
}
} else {
c.Data["Title"] = i18n.Tr(c.Lang, "blog.summary")
c.Data["Content"] = template.HTML(blackfriday.Run([]byte(bookResult.Description)))
c.Data["FoldSetting"] = "closed"
}
tree, err := models.NewDocument().CreateDocumentTreeForHtml(bookResult.BookId, selected)
if err != nil {
2018-07-25 17:47:06 +08:00
if err == orm.ErrNoRows {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.no_doc_in_cur_proj"))
2018-07-25 17:47:06 +08:00
} else {
logs.Error("生成项目文档树时出错 -> ", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error"))
2018-07-25 17:47:06 +08:00
}
}
2022-05-14 20:54:59 +08:00
c.Data["IS_DOCUMENT_INDEX"] = true
c.Data["Model"] = bookResult
c.Data["Result"] = template.HTML(tree)
2017-04-20 18:19:32 +08:00
}
2017-05-12 11:41:59 +08:00
// CheckPassword : Handles password verification for private documents,
// and front-end requests are made through Ajax.
func (c *DocumentController) CheckPassword() {
identify := c.Ctx.Input.Param(":key")
password := c.GetString("bPassword")
if identify == "" || password == "" {
c.JsonResult(http.StatusBadRequest, i18n.Tr(c.Lang, "message.param_error"))
}
// You have not logged in and need to log in again.
if !c.EnableAnonymous && !c.isUserLoggedIn() {
logs.Info("You have not logged in and need to log in again(SessionId: %s).",
c.CruSession.SessionID(context.TODO()))
c.JsonResult(6000, i18n.Tr(c.Lang, "message.need_relogin"))
return
}
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error(err)
c.JsonResult(500, i18n.Tr(c.Lang, "message.item_not_exist"))
}
if book.BookPassword != password {
c.JsonResult(5001, i18n.Tr(c.Lang, "message.wrong_password"))
} else {
c.SetSession(identify, password)
c.JsonResult(0, "OK")
}
}
// 阅读文档
func (c *DocumentController) Read() {
identify := c.Ctx.Input.Param(":key")
token := c.GetString("token")
2017-05-13 13:04:53 +08:00
id := c.GetString(":id")
2017-05-13 13:04:53 +08:00
if identify == "" || id == "" {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
}
// 如果没有开启匿名访问则跳转到登录
2018-11-14 15:57:55 +08:00
if !c.EnableAnonymous && !c.isUserLoggedIn() {
promptUserToLogIn(c)
return
}
2018-11-14 15:57:55 +08:00
bookResult := c.isReadable(identify, token)
c.TplName = fmt.Sprintf("document/%s_read.tpl", bookResult.Theme)
doc := models.NewDocument()
2018-03-23 11:17:52 +08:00
if docId, err := strconv.Atoi(id); err == nil {
doc, err = doc.FromCacheById(docId)
if err != nil || doc == nil {
logs.Error("从缓存中读取文档时失败 ->", err)
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist"))
return
}
2017-05-13 13:04:53 +08:00
} else {
doc, err = doc.FromCacheByIdentify(id, bookResult.BookId)
if err != nil || doc == nil {
2018-07-25 17:47:06 +08:00
if err == orm.ErrNoRows {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist"))
} else {
logs.Error("从数据库查询文档时出错 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.unknown_exception"))
2018-07-25 17:47:06 +08:00
}
return
}
}
if doc.BookId != bookResult.BookId {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist"))
}
doc.Lang = c.Lang
doc.Processor()
2017-05-13 13:04:53 +08:00
attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId)
2017-05-13 12:12:37 +08:00
if err == nil {
doc.AttachList = attach
}
// prev,next
treeJson, err := models.NewDocument().FindDocumentTree2(bookResult.BookId)
if err != nil {
logs.Error("生成项目文档树时出错 ->", err)
}
res := getTreeRecursive(treeJson, 0)
flat := make([]DocumentTreeFlatten, 0)
Flatten(res, &flat)
var index int
for i, v := range flat {
if v.Identify == id {
index = i
}
}
var PrevName, PrevPath, NextName, NextPath string
if index == 0 {
c.Data["PrevName"] = "没有了"
PrevName = "没有了"
} else {
c.Data["PrevPath"] = identify + "/" + flat[index-1].Identify
c.Data["PrevName"] = flat[index-1].DocumentName
PrevPath = identify + "/" + flat[index-1].Identify
PrevName = flat[index-1].DocumentName
}
if index == len(flat)-1 {
c.Data["NextName"] = "没有了"
NextName = "没有了"
} else {
c.Data["NextPath"] = identify + "/" + flat[index+1].Identify
c.Data["NextName"] = flat[index+1].DocumentName
NextPath = identify + "/" + flat[index+1].Identify
NextName = flat[index+1].DocumentName
}
2021-04-01 09:23:55 +08:00
doc.IncrViewCount(doc.DocumentId)
doc.ViewCount = doc.ViewCount + 1
doc.PutToCache()
2021-03-31 19:32:18 +08:00
if c.IsAjax() {
2017-05-13 13:04:53 +08:00
var data struct {
DocId int `json:"doc_id"`
DocIdentify string `json:"doc_identify"`
DocTitle string `json:"doc_title"`
Body string `json:"body"`
Title string `json:"title"`
Version int64 `json:"version"`
ViewCount int `json:"view_count"`
MarkdownTheme string `json:"markdown_theme"`
IsMarkdown bool `json:"is_markdown"`
}
2022-05-14 20:54:59 +08:00
data.DocId = doc.DocumentId
data.DocIdentify = doc.Identify
data.DocTitle = doc.DocumentName
data.Body = doc.Release + "<div class='wiki-bottom-left'>上一篇: <a href='/docs/" + PrevPath + "' rel='prev'>" + PrevName + "</a><br />下一篇: <a href='/docs/" + NextPath + "' rel='next'>" + NextName + "</a><br /></div>"
data.Title = doc.DocumentName + " - Powered by MinDoc"
data.Version = doc.Version
data.ViewCount = doc.ViewCount
data.MarkdownTheme = doc.MarkdownTheme
if bookResult.Editor == EditorCherryMarkdown {
data.IsMarkdown = true
}
2017-05-13 13:04:53 +08:00
c.JsonResult(0, "ok", data)
2022-05-14 20:54:59 +08:00
} else {
c.Data["DocumentId"] = doc.DocumentId
c.Data["DocIdentify"] = doc.Identify
if bookResult.IsDisplayComment {
// 获取评论、分页
comments, count, _ := models.NewComment().QueryCommentByDocumentId(doc.DocumentId, 1, conf.PageSize, c.Member)
page := pagination.PageUtil(int(count), 1, conf.PageSize, comments)
c.Data["Page"] = page
}
}
2017-05-13 13:04:53 +08:00
tree, err := models.NewDocument().CreateDocumentTreeForHtml(bookResult.BookId, doc.DocumentId)
2018-07-25 17:47:06 +08:00
if err != nil && err != orm.ErrNoRows {
logs.Error("生成项目文档树时出错 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error"))
}
c.Data["Description"] = utils.AutoSummary(doc.Release, 120)
c.Data["Model"] = bookResult
c.Data["Result"] = template.HTML(tree)
c.Data["Title"] = doc.DocumentName
c.Data["Content"] = template.HTML(doc.Release + "<div class='wiki-bottom-left'>上一篇: <a href='/docs/" + PrevPath + "' rel='prev'>" + PrevName + "</a><br />下一篇: <a href='/docs/" + NextPath + "' rel='next'>" + NextName + "</a><br /></div>")
c.Data["ViewCount"] = doc.ViewCount
c.Data["FoldSetting"] = "closed"
if bookResult.Editor == EditorCherryMarkdown {
c.Data["MarkdownTheme"] = doc.MarkdownTheme
}
if doc.IsOpen == 1 {
c.Data["FoldSetting"] = "open"
} else if doc.IsOpen == 2 {
c.Data["FoldSetting"] = "empty"
}
2017-04-20 18:19:32 +08:00
}
2017-04-26 18:17:38 +08:00
// 递归得到树状结构体
func getTreeRecursive(list []*models.DocumentTree, parentId int) (res []*models.DocumentTree) {
for _, v := range list {
if v.ParentId == parentId {
v.Children = getTreeRecursive(list, v.DocumentId)
res = append(res, v)
}
}
return res
}
// 递归将树状结构体转换为扁平结构体数组
// func Flatten(list []*models.DocumentTree, flattened *[]DocumentTreeFlatten) (flatten *[]DocumentTreeFlatten) {
func Flatten(list []*models.DocumentTree, flattened *[]DocumentTreeFlatten) {
// Treeslice := make([]*DocumentTreeFlatten, 0)
for _, v := range list {
tree := make([]DocumentTreeFlatten, 1)
tree[0].DocumentId = v.DocumentId
tree[0].DocumentName = v.DocumentName
tree[0].Identify = v.Identify
*flattened = append(*flattened, tree...)
if len(v.Children) > 0 {
Flatten(v.Children, flattened)
}
}
return
}
// 编辑文档
2017-05-13 13:04:53 +08:00
func (c *DocumentController) Edit() {
2017-04-26 18:17:38 +08:00
c.Prepare()
identify := c.Ctx.Input.Param(":key")
2017-04-27 18:19:37 +08:00
if identify == "" {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.project_id_error"))
2017-04-27 18:19:37 +08:00
}
2017-04-26 18:17:38 +08:00
bookResult := models.NewBookResult()
2017-05-12 11:41:59 +08:00
var err error
2018-11-26 18:54:50 +08:00
// 如果是管理者,则不判断权限
2017-06-05 10:52:14 +08:00
if c.Member.IsAdministrator() {
2017-05-13 13:04:53 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
}
2017-04-26 18:17:38 +08:00
bookResult = models.NewBookResult().ToBookResult(*book)
2017-05-13 13:04:53 +08:00
} else {
2017-05-12 11:41:59 +08:00
bookResult, err = models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
2017-04-27 18:19:37 +08:00
if err != nil {
if err == orm.ErrNoRows || err == models.ErrPermissionDenied {
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
} else {
logs.Error("查询项目时出错 -> ", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
2018-07-25 17:47:06 +08:00
}
return
}
if bookResult.RoleId == conf.BookObserver {
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
}
}
c.TplName = fmt.Sprintf("document/%s_edit_template.tpl", bookResult.Editor)
2017-04-26 18:17:38 +08:00
c.Data["Model"] = bookResult
2017-04-27 18:19:37 +08:00
2017-05-13 13:04:53 +08:00
r, _ := json.Marshal(bookResult)
2017-04-27 18:19:37 +08:00
c.Data["ModelResult"] = template.JS(string(r))
c.Data["Result"] = template.JS("[]")
2017-05-13 13:04:53 +08:00
trees, err := models.NewDocument().FindDocumentTree(bookResult.BookId)
2017-04-27 18:19:37 +08:00
if err != nil {
logs.Error("FindDocumentTree => ", err)
2017-05-13 13:04:53 +08:00
} else {
2017-04-27 18:19:37 +08:00
if len(trees) > 0 {
if jtree, err := json.Marshal(trees); err == nil {
c.Data["Result"] = template.JS(string(jtree))
}
2017-05-13 13:04:53 +08:00
} else {
2017-04-27 18:19:37 +08:00
c.Data["Result"] = template.JS("[]")
}
}
c.Data["BaiDuMapKey"] = web.AppConfig.DefaultString("baidumapkey", "")
if conf.GetUploadFileSize() > 0 {
c.Data["UploadFileSize"] = conf.GetUploadFileSize()
2018-11-14 15:57:55 +08:00
} else {
c.Data["UploadFileSize"] = "undefined"
}
2017-04-27 18:19:37 +08:00
}
// 创建一个文档
2017-04-27 18:19:37 +08:00
func (c *DocumentController) Create() {
identify := c.GetString("identify")
2018-03-23 11:17:52 +08:00
docIdentify := c.GetString("doc_identify")
docName := c.GetString("doc_name")
parentId, _ := c.GetInt("parent_id", 0)
docId, _ := c.GetInt("doc_id", 0)
isOpen, _ := c.GetInt("is_open", 0)
2017-04-27 18:19:37 +08:00
if identify == "" {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-04-27 18:19:37 +08:00
}
2018-03-23 11:17:52 +08:00
if docName == "" {
c.JsonResult(6004, i18n.Tr(c.Lang, "message.doc_name_empty"))
2017-04-27 18:19:37 +08:00
}
2018-03-23 11:17:52 +08:00
bookId := 0
// 如果是超级管理员则不判断权限
2017-06-05 10:52:14 +08:00
if c.Member.IsAdministrator() {
2017-05-13 13:04:53 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error(err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_existed_or_no_permit"))
}
2018-03-23 11:17:52 +08:00
bookId = book.BookId
2017-05-13 13:04:53 +08:00
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
2017-04-27 18:19:37 +08:00
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("FindByIdentify => ", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_existed_or_no_permit"))
}
2018-03-23 11:17:52 +08:00
bookId = bookResult.BookId
2017-04-27 18:19:37 +08:00
}
2018-03-23 11:17:52 +08:00
if docIdentify != "" {
if ok, err := regexp.MatchString(`[a-z]+[a-zA-Z0-9_.\-]*$`, docIdentify); !ok || err != nil {
c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips"))
2018-03-23 11:17:52 +08:00
}
d, _ := models.NewDocument().FindByIdentityFirst(docIdentify, bookId)
2018-03-23 11:17:52 +08:00
if d.DocumentId > 0 && d.DocumentId != docId {
c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed"))
2018-03-23 11:17:52 +08:00
}
}
if parentId > 0 {
doc, err := models.NewDocument().Find(parentId)
if err != nil || doc.BookId != bookId {
c.JsonResult(6003, i18n.Tr(c.Lang, "message.parent_id_not_existed"))
2017-04-27 18:19:37 +08:00
}
}
2018-03-23 11:17:52 +08:00
document, _ := models.NewDocument().Find(docId)
2017-04-28 18:08:01 +08:00
2017-04-27 18:19:37 +08:00
document.MemberId = c.Member.MemberId
2018-03-23 11:17:52 +08:00
document.BookId = bookId
2018-03-23 11:17:52 +08:00
document.Identify = docIdentify
2017-04-28 18:08:01 +08:00
document.Version = time.Now().Unix()
2018-03-23 11:17:52 +08:00
document.DocumentName = docName
document.ParentId = parentId
2017-04-28 18:08:01 +08:00
if isOpen == 1 {
document.IsOpen = 1
} else if isOpen == 2 {
document.IsOpen = 2
} else {
document.IsOpen = 0
}
2017-05-13 13:04:53 +08:00
if err := document.InsertOrUpdate(); err != nil {
logs.Error("添加或更新文档时出错 -> ", err)
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
2017-05-13 13:04:53 +08:00
} else {
c.JsonResult(0, "ok", document)
2017-04-27 18:19:37 +08:00
}
}
// 上传附件或图片
2017-05-13 13:04:53 +08:00
func (c *DocumentController) Upload() {
2017-04-27 18:19:37 +08:00
identify := c.GetString("identify")
docId, _ := c.GetInt("doc_id")
isAttach := true
2017-04-27 18:19:37 +08:00
if identify == "" {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-04-27 18:19:37 +08:00
}
names := []string{"editormd-file-file", "editormd-image-file", "file", "editormd-resource-file"}
var files []*multipart.FileHeader
for _, name := range names {
file, err := c.GetFiles(name)
if err != nil {
continue
}
if len(file) > 0 && err == nil {
files = append(files, file...)
2017-04-27 18:19:37 +08:00
}
}
if len(files) == 0 {
c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_empty"))
return
}
result2 := []map[string]interface{}{}
var result map[string]interface{}
for i, _ := range files {
//for each fileheader, get a handle to the actual file
file, err := files[i].Open()
defer file.Close()
2017-04-27 18:19:37 +08:00
if err != nil {
c.JsonResult(6002, err.Error())
}
// defer file.Close()
type Size interface {
Size() int64
}
// if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() {
if conf.GetUploadFileSize() > 0 && files[i].Size > conf.GetUploadFileSize() {
c.JsonResult(6009, i18n.Tr(c.Lang, "message.upload_file_size_limit"))
}
// ext := filepath.Ext(moreFile.Filename)
ext := filepath.Ext(files[i].Filename)
//文件必须带有后缀名
if ext == "" {
c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_type_error"))
}
//如果文件类型设置为 * 标识不限制文件类型
if conf.IsAllowUploadFileExt(ext) == false {
c.JsonResult(6004, i18n.Tr(c.Lang, "message.upload_file_type_error"))
}
2017-04-27 18:19:37 +08:00
bookId := 0
2017-04-27 18:19:37 +08:00
// 如果是超级管理员,则不判断权限
if c.Member.IsAdministrator() {
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
c.JsonResult(6006, i18n.Tr(c.Lang, "message.doc_not_exist_or_no_permit"))
}
bookId = book.BookId
} else {
book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
if err != nil {
logs.Error("DocumentController.Edit => ", err)
if err == orm.ErrNoRows {
c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission"))
}
c.JsonResult(6001, err.Error())
}
// 如果没有编辑权限
if book.RoleId != conf.BookEditor && book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder {
c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission"))
}
bookId = book.BookId
}
2017-04-27 18:19:37 +08:00
if docId > 0 {
doc, err := models.NewDocument().Find(docId)
if err != nil {
c.JsonResult(6007, i18n.Tr(c.Lang, "message.doc_not_exist"))
}
if doc.BookId != bookId {
c.JsonResult(6008, i18n.Tr(c.Lang, "message.doc_not_belong_project"))
}
}
fileName := "m_" + cryptil.UniqueId() + "_r"
filePath := filepath.Join(conf.WorkingDirectory, "uploads", identify)
//将图片和文件分开存放
attachment := models.NewAttachment()
var strategy filetil.FileTypeStrategy
if filetil.IsImageExt(files[i].Filename) {
strategy = filetil.ImageStrategy{}
attachment.ResourceType = "image"
} else if filetil.IsVideoExt(files[i].Filename) {
strategy = filetil.VideoStrategy{}
attachment.ResourceType = "video"
} else {
strategy = filetil.DefaultStrategy{}
attachment.ResourceType = "file"
}
filePath = strategy.GetFilePath(filePath, fileName, ext)
path := filepath.Dir(filePath)
2017-04-27 18:19:37 +08:00
_ = os.MkdirAll(path, os.ModePerm)
//copy the uploaded file to the destination file
dst, err := os.Create(filePath)
defer dst.Close()
if _, err := io.Copy(dst, file); err != nil {
logs.Error("保存文件失败 -> ", err)
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
}
attachment.BookId = bookId
// attachment.FileName = moreFile.Filename
attachment.FileName = files[i].Filename
attachment.CreateAt = c.Member.MemberId
attachment.FileExt = ext
attachment.FilePath = strings.TrimPrefix(filePath, conf.WorkingDirectory)
attachment.DocumentId = docId
2017-04-27 18:19:37 +08:00
if fileInfo, err := os.Stat(filePath); err == nil {
attachment.FileSize = float64(fileInfo.Size())
2017-06-05 13:38:06 +08:00
}
if docId > 0 {
attachment.DocumentId = docId
}
2017-04-27 18:19:37 +08:00
if filetil.IsImageExt(files[i].Filename) || filetil.IsVideoExt(files[i].Filename) {
attachment.HttpPath = "/" + strings.Replace(strings.TrimPrefix(filePath, conf.WorkingDirectory), "\\", "/", -1)
if strings.HasPrefix(attachment.HttpPath, "//") {
attachment.HttpPath = conf.URLForWithCdnImage(string(attachment.HttpPath[1:]))
}
2017-04-27 18:19:37 +08:00
isAttach = false
}
err = attachment.Insert()
2017-04-27 18:19:37 +08:00
if err != nil {
os.Remove(filePath)
logs.Error("文件保存失败 ->", err)
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
2017-04-27 18:19:37 +08:00
}
if attachment.HttpPath == "" {
attachment.HttpPath = conf.URLForNotHost("DocumentController.DownloadAttachment", ":key", identify, ":attach_id", attachment.AttachmentId)
if err := attachment.Update(); err != nil {
logs.Error("保存文件失败 ->", err)
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
}
}
result = map[string]interface{}{
"errcode": 0,
"success": 1,
"message": "ok",
"url": attachment.HttpPath,
"link": attachment.HttpPath,
"alt": attachment.FileName,
"is_attach": isAttach,
"attach": attachment,
"resource_type": attachment.ResourceType,
}
result2 = append(result2, result)
2017-04-27 18:19:37 +08:00
}
if len(files) == 1 {
// froala单文件上传
c.Ctx.Output.JSON(result, true, false)
} else {
c.Ctx.Output.JSON(result2, true, false)
}
2017-04-27 18:19:37 +08:00
c.StopRun()
}
// 下载附件
2017-05-13 13:04:53 +08:00
func (c *DocumentController) DownloadAttachment() {
2017-04-27 18:19:37 +08:00
c.Prepare()
identify := c.Ctx.Input.Param(":key")
2018-03-13 14:14:56 +08:00
attachId, _ := strconv.Atoi(c.Ctx.Input.Param(":attach_id"))
2017-04-27 18:19:37 +08:00
token := c.GetString("token")
2018-03-13 14:14:56 +08:00
memberId := 0
2017-04-27 18:19:37 +08:00
if c.Member != nil {
2018-03-13 14:14:56 +08:00
memberId = c.Member.MemberId
2017-04-27 18:19:37 +08:00
}
2018-03-13 14:14:56 +08:00
bookId := 0
2017-04-27 18:19:37 +08:00
// 判断用户是否参与了项目
2018-03-13 14:14:56 +08:00
bookResult, err := models.NewBookResult().FindByIdentify(identify, memberId)
2017-04-27 18:19:37 +08:00
if err != nil {
// 判断项目公开状态
book, err := models.NewBook().FindByFieldFirst("identify", identify)
2017-04-27 18:19:37 +08:00
if err != nil {
2018-07-25 17:47:06 +08:00
if err == orm.ErrNoRows {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
} else {
logs.Error("查找项目时出错 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
2018-07-25 17:47:06 +08:00
}
2017-04-27 18:19:37 +08:00
}
// 如果不是超级管理员则判断权限
if c.Member == nil || c.Member.Role != conf.MemberSuperRole {
// 如果项目是私有的,并且 token 不正确
2017-05-13 13:04:53 +08:00
if (book.PrivatelyOwned == 1 && token == "") || (book.PrivatelyOwned == 1 && book.PrivateToken != token) {
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
}
2017-04-27 18:19:37 +08:00
}
2018-03-13 14:14:56 +08:00
bookId = book.BookId
2017-05-13 13:04:53 +08:00
} else {
2018-03-13 14:14:56 +08:00
bookId = bookResult.BookId
2017-04-27 18:19:37 +08:00
}
// 查找附件
2018-03-13 14:14:56 +08:00
attachment, err := models.NewAttachment().Find(attachId)
2017-04-27 18:19:37 +08:00
if err != nil {
logs.Error("查找附件时出错 -> ", err)
2017-04-27 18:19:37 +08:00
if err == orm.ErrNoRows {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
2017-04-27 18:19:37 +08:00
} else {
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
2017-04-27 18:19:37 +08:00
}
}
2018-03-13 14:14:56 +08:00
if attachment.BookId != bookId {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
2017-04-27 18:19:37 +08:00
}
c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName)
2017-04-27 18:19:37 +08:00
c.StopRun()
}
2017-04-28 18:08:01 +08:00
// 删除附件
2017-05-13 13:04:53 +08:00
func (c *DocumentController) RemoveAttachment() {
2017-05-12 19:14:29 +08:00
c.Prepare()
attachId, _ := c.GetInt("attach_id")
2017-05-12 19:14:29 +08:00
if attachId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-12 19:14:29 +08:00
}
attach, err := models.NewAttachment().Find(attachId)
2017-05-12 19:14:29 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.attachment_not_exist"))
2017-05-12 19:14:29 +08:00
}
2017-05-13 13:04:53 +08:00
document, err := models.NewDocument().Find(attach.DocumentId)
2017-05-12 19:14:29 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist"))
2017-05-12 19:14:29 +08:00
}
2017-05-12 19:14:29 +08:00
if c.Member.Role != conf.MemberSuperRole {
2017-05-13 13:04:53 +08:00
rel, err := models.NewRelationship().FindByBookIdAndMemberId(document.BookId, c.Member.MemberId)
2017-05-12 19:14:29 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6004, i18n.Tr(c.Lang, "message.no_permission"))
2017-05-12 19:14:29 +08:00
}
2017-05-12 19:14:29 +08:00
if rel.RoleId == conf.BookObserver {
c.JsonResult(6004, i18n.Tr(c.Lang, "message.no_permission"))
2017-05-12 19:14:29 +08:00
}
}
err = attach.Delete()
2017-05-12 19:14:29 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
2017-05-12 19:14:29 +08:00
}
os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath))
2017-06-05 13:38:06 +08:00
2017-05-13 13:04:53 +08:00
c.JsonResult(0, "ok", attach)
2017-05-12 19:14:29 +08:00
}
2017-05-13 13:04:53 +08:00
// 删除文档
2017-04-28 18:08:01 +08:00
func (c *DocumentController) Delete() {
c.Prepare()
identify := c.GetString("identify")
docId, err := c.GetInt("doc_id", 0)
2017-04-28 18:08:01 +08:00
bookId := 0
// 如果是超级管理员则忽略权限判断
2017-06-05 10:52:14 +08:00
if c.Member.IsAdministrator() {
2017-05-13 13:04:53 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error("FindByIdentify => ", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
}
bookId = book.BookId
2017-05-13 13:04:53 +08:00
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
2017-04-28 18:08:01 +08:00
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("FindByIdentify => ", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
}
bookId = bookResult.BookId
2017-04-28 18:08:01 +08:00
}
if docId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-04-28 18:08:01 +08:00
}
doc, err := models.NewDocument().Find(docId)
2017-04-28 18:08:01 +08:00
if err != nil {
logs.Error("Delete => ", err)
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
2017-04-28 18:08:01 +08:00
}
// 如果文档所属项目错误
if doc.BookId != bookId {
c.JsonResult(6004, i18n.Tr(c.Lang, "message.param_error"))
2017-04-28 18:08:01 +08:00
}
// 递归删除项目下的文档以及子文档
2017-04-28 18:08:01 +08:00
err = doc.RecursiveDocument(doc.DocumentId)
if err != nil {
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
2017-04-28 18:08:01 +08:00
}
// 重置文档数量统计
models.NewBook().ResetDocumentNumber(doc.BookId)
2017-05-13 13:04:53 +08:00
c.JsonResult(0, "ok")
2017-04-28 18:08:01 +08:00
}
// 获取文档内容
2017-05-13 13:04:53 +08:00
func (c *DocumentController) Content() {
2017-04-28 18:08:01 +08:00
c.Prepare()
identify := c.Ctx.Input.Param(":key")
docId, err := c.GetInt("doc_id")
2017-04-28 18:08:01 +08:00
if err != nil {
docId, _ = strconv.Atoi(c.Ctx.Input.Param(":id"))
2017-04-28 18:08:01 +08:00
}
bookId := 0
autoRelease := false
// 如果是超级管理员,则忽略权限
2017-05-26 14:19:27 +08:00
if c.Member.IsAdministrator() {
2017-05-13 13:04:53 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil || book == nil {
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
return
}
bookId = book.BookId
autoRelease = book.AutoRelease == 1
2017-05-13 13:04:53 +08:00
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
2017-04-28 18:08:01 +08:00
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("项目不存在或权限不足 -> ", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
}
bookId = bookResult.BookId
autoRelease = bookResult.AutoRelease
2017-04-28 18:08:01 +08:00
}
if docId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-04-28 18:08:01 +08:00
}
if c.Ctx.Input.IsPost() {
2017-05-13 13:04:53 +08:00
markdown := strings.TrimSpace(c.GetString("markdown", ""))
2017-04-28 18:08:01 +08:00
content := c.GetString("html")
markdownTheme := c.GetString("markdown_theme", "theme__light")
2017-05-13 13:04:53 +08:00
version, _ := c.GetInt64("version", 0)
isCover := c.GetString("cover")
2017-04-28 18:08:01 +08:00
doc, err := models.NewDocument().Find(docId)
if err != nil || doc == nil {
c.JsonResult(6003, i18n.Tr(c.Lang, "message.read_file_error"))
return
2017-04-28 18:08:01 +08:00
}
if doc.BookId != bookId {
c.JsonResult(6004, i18n.Tr(c.Lang, "message.dock_not_belong_project"))
2017-04-28 18:08:01 +08:00
}
if doc.Version != version && !strings.EqualFold(isCover, "yes") {
logs.Info("%d|", version, doc.Version)
c.JsonResult(6005, i18n.Tr(c.Lang, "message.confirm_override_doc"))
2017-04-28 18:08:01 +08:00
}
2017-05-20 15:27:03 +08:00
history := models.NewDocumentHistory()
history.DocumentId = docId
2017-05-20 15:27:03 +08:00
history.Content = doc.Content
history.Markdown = doc.Markdown
history.DocumentName = doc.DocumentName
history.ModifyAt = c.Member.MemberId
history.MemberId = doc.MemberId
history.ParentId = doc.ParentId
history.Version = time.Now().Unix()
history.Action = "modify"
history.ActionName = i18n.Tr(c.Lang, "doc.modify_doc")
2017-05-20 15:27:03 +08:00
2017-05-13 13:04:53 +08:00
if markdown == "" && content != "" {
2017-04-28 18:08:01 +08:00
doc.Markdown = content
2017-05-13 13:04:53 +08:00
} else {
2017-04-28 18:08:01 +08:00
doc.Markdown = markdown
doc.MarkdownTheme = markdownTheme
2017-04-28 18:08:01 +08:00
}
2017-04-28 18:08:01 +08:00
doc.Version = time.Now().Unix()
doc.Content = content
doc.ModifyAt = c.Member.MemberId
2017-05-13 13:04:53 +08:00
if err := doc.InsertOrUpdate(); err != nil {
logs.Error("InsertOrUpdate => ", err)
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
2017-04-28 18:08:01 +08:00
}
// 如果启用了文档历史,则添加历史文档
///如果两次保存的MD5值不同则保存为历史否则忽略
go func(history *models.DocumentHistory) {
if c.EnableDocumentHistory && cryptil.Md5Crypt(history.Markdown) != cryptil.Md5Crypt(doc.Markdown) {
_, err = history.InsertOrUpdate()
if err != nil {
logs.Error("DocumentHistory InsertOrUpdate => ", err)
}
2017-05-20 15:27:03 +08:00
}
}(history)
//如果启用了自动发布
if autoRelease {
2018-08-13 19:05:49 +08:00
go func() {
doc.Lang = c.Lang
2018-08-13 19:05:49 +08:00
err := doc.ReleaseContent()
if err == nil {
logs.Informational(i18n.Tr(c.Lang, "message.doc_auto_published")+"-> document_id=%d;document_name=%s", doc.DocumentId, doc.DocumentName)
2018-08-13 19:05:49 +08:00
}
}()
}
2017-05-13 13:04:53 +08:00
c.JsonResult(0, "ok", doc)
2017-04-28 18:08:01 +08:00
}
doc, err := models.NewDocument().Find(docId)
2017-04-28 18:08:01 +08:00
if err != nil {
c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist"))
return
2017-04-28 18:08:01 +08:00
}
2017-05-13 13:04:53 +08:00
attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId)
2017-05-12 19:14:29 +08:00
if err == nil {
doc.AttachList = attach
}
2017-05-13 13:04:53 +08:00
c.JsonResult(0, "ok", doc)
2017-04-28 18:08:01 +08:00
}
// Export 导出
func (c *DocumentController) Export() {
2017-05-06 16:16:27 +08:00
c.Prepare()
identify := c.Ctx.Input.Param(":key")
if identify == "" {
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error"))
}
2017-05-09 10:04:56 +08:00
2017-05-06 16:16:27 +08:00
output := c.GetString("output")
token := c.GetString("token")
// 如果没有开启匿名访问则跳转到登录
2018-11-14 15:57:55 +08:00
if !c.EnableAnonymous && !c.isUserLoggedIn() {
promptUserToLogIn(c)
2017-05-06 16:16:27 +08:00
return
}
if !conf.GetEnableExport() {
c.ShowErrorPage(500, i18n.Tr(c.Lang, "export_func_disable"))
}
2017-05-12 14:21:29 +08:00
bookResult := models.NewBookResult()
2017-06-05 10:52:14 +08:00
if c.Member != nil && c.Member.IsAdministrator() {
2017-05-13 13:04:53 +08:00
book, err := models.NewBook().FindByIdentify(identify)
2017-05-12 14:21:29 +08:00
if err != nil {
2018-07-25 17:47:06 +08:00
if err == orm.ErrNoRows {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
2018-07-25 17:47:06 +08:00
} else {
logs.Error("查找项目时出错 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
2018-07-25 17:47:06 +08:00
}
2017-05-12 14:21:29 +08:00
}
bookResult = models.NewBookResult().ToBookResult(*book)
2017-05-13 13:04:53 +08:00
} else {
2018-11-14 15:57:55 +08:00
bookResult = c.isReadable(identify, token)
2017-05-12 14:21:29 +08:00
}
if !bookResult.IsDownload {
c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.cur_project_export_func_disable"))
}
if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") {
2018-03-13 19:20:50 +08:00
bookResult.Cover = conf.URLForWithCdnImage(bookResult.Cover)
}
if output == Markdown {
if bookResult.Editor != EditorMarkdown && bookResult.Editor != EditorCherryMarkdown {
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.cur_project_not_support_md"))
2018-03-12 18:24:58 +08:00
}
p, err := bookResult.ExportMarkdown(c.CruSession.SessionID(context.TODO()))
2018-03-12 18:24:58 +08:00
if err != nil {
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.failed"))
2018-03-12 18:24:58 +08:00
}
c.Ctx.Output.Download(p, bookResult.BookName+".zip")
c.StopRun()
return
}
outputPath := filepath.Join(conf.GetExportOutputPath(), strconv.Itoa(bookResult.BookId))
pdfpath := filepath.Join(outputPath, "book.pdf")
epubpath := filepath.Join(outputPath, "book.epub")
mobipath := filepath.Join(outputPath, "book.mobi")
docxpath := filepath.Join(outputPath, "book.docx")
if output == "pdf" && filetil.FileExists(pdfpath) {
c.Ctx.Output.Download(pdfpath, bookResult.BookName+".pdf")
c.Abort("200")
} else if output == "epub" && filetil.FileExists(epubpath) {
c.Ctx.Output.Download(epubpath, bookResult.BookName+".epub")
c.Abort("200")
} else if output == "mobi" && filetil.FileExists(mobipath) {
c.Ctx.Output.Download(mobipath, bookResult.BookName+".mobi")
c.Abort("200")
} else if output == "docx" && filetil.FileExists(docxpath) {
c.Ctx.Output.Download(docxpath, bookResult.BookName+".docx")
c.Abort("200")
} else if output == "pdf" || output == "epub" || output == "docx" || output == "mobi" {
if err := models.BackgroundConvert(c.CruSession.SessionID(context.TODO()), bookResult); err != nil && err != gopool.ErrHandlerIsExist {
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.export_failed"))
2018-07-11 14:18:27 +08:00
}
c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.file_converting"))
} else {
c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.unsupport_file_type"))
2017-05-06 16:16:27 +08:00
}
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.no_exportable_file"))
2017-05-06 16:16:27 +08:00
}
// 生成项目访问的二维码
2017-05-13 13:04:53 +08:00
func (c *DocumentController) QrCode() {
c.Prepare()
2017-05-13 13:04:53 +08:00
identify := c.GetString(":key")
book, err := models.NewBook().FindByIdentify(identify)
if err != nil || book.BookId <= 0 {
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
2017-05-13 13:04:53 +08:00
}
2018-03-13 19:20:50 +08:00
uri := conf.URLFor("DocumentController.Index", ":key", identify)
2017-05-13 13:04:53 +08:00
code, err := qr.Encode(uri, qr.L, qr.Unicode)
if err != nil {
logs.Error("生成二维码失败 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed"))
2017-05-13 13:04:53 +08:00
}
code, err = barcode.Scale(code, 150, 150)
2017-05-13 13:04:53 +08:00
if err != nil {
logs.Error("生成二维码失败 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed"))
2017-05-13 13:04:53 +08:00
}
2017-05-13 13:04:53 +08:00
c.Ctx.ResponseWriter.Header().Set("Content-Type", "image/png")
2017-05-13 13:15:21 +08:00
// imgpath := filepath.Join("cache","qrcode",identify + ".png")
2017-05-13 13:15:21 +08:00
2017-05-13 13:04:53 +08:00
err = png.Encode(c.Ctx.ResponseWriter, code)
if err != nil {
logs.Error("生成二维码失败 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed"))
2017-05-13 13:04:53 +08:00
}
}
// 项目内搜索
2017-06-05 10:52:14 +08:00
func (c *DocumentController) Search() {
2017-05-13 17:41:17 +08:00
c.Prepare()
2017-05-15 14:59:23 +08:00
identify := c.Ctx.Input.Param(":key")
token := c.GetString("token")
keyword := strings.TrimSpace(c.GetString("keyword"))
2017-06-05 10:52:14 +08:00
if identify == "" {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-15 14:59:23 +08:00
}
2018-11-14 15:57:55 +08:00
if !c.EnableAnonymous && !c.isUserLoggedIn() {
promptUserToLogIn(c)
2017-05-15 14:59:23 +08:00
return
}
2018-11-14 15:57:55 +08:00
bookResult := c.isReadable(identify, token)
2017-05-15 14:59:23 +08:00
2017-06-05 10:52:14 +08:00
docs, err := models.NewDocumentSearchResult().SearchDocument(keyword, bookResult.BookId)
2017-05-15 14:59:23 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.search_result_error"))
2017-05-15 14:59:23 +08:00
}
2017-05-15 14:59:23 +08:00
if len(docs) < 0 {
c.JsonResult(404, i18n.Tr(c.Lang, "message.no_data"))
2017-05-15 14:59:23 +08:00
}
2017-06-05 10:52:14 +08:00
for _, doc := range docs {
2017-05-15 14:59:23 +08:00
doc.BookId = bookResult.BookId
doc.BookName = bookResult.BookName
doc.Description = bookResult.Description
doc.BookIdentify = bookResult.Identify
}
2017-06-05 10:52:14 +08:00
c.JsonResult(0, "ok", docs)
2017-05-13 17:41:17 +08:00
}
// 文档历史列表
2017-05-20 15:27:03 +08:00
func (c *DocumentController) History() {
c.Prepare()
2017-05-25 15:19:17 +08:00
c.TplName = "document/history.tpl"
2017-05-20 15:27:03 +08:00
identify := c.GetString("identify")
2018-03-23 11:17:52 +08:00
docId, err := c.GetInt("doc_id", 0)
2017-05-20 15:27:03 +08:00
pageIndex, _ := c.GetInt("page", 1)
bookId := 0
// 如果是超级管理员则忽略权限判断
2017-06-05 10:52:14 +08:00
if c.Member.IsAdministrator() {
2017-05-20 15:27:03 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error("查找项目失败 ->", err)
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")
2017-05-25 15:19:17 +08:00
return
2017-05-20 15:27:03 +08:00
}
bookId = book.BookId
2017-05-25 15:19:17 +08:00
c.Data["Model"] = book
2017-05-20 15:27:03 +08:00
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("查找项目失败 ->", err)
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")
2017-05-25 15:19:17 +08:00
return
2017-05-20 15:27:03 +08:00
}
bookId = bookResult.BookId
2017-05-25 15:19:17 +08:00
c.Data["Model"] = bookResult
2017-05-20 15:27:03 +08:00
}
2018-03-23 11:17:52 +08:00
if docId <= 0 {
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.param_error")
2017-05-25 15:19:17 +08:00
return
2017-05-20 15:27:03 +08:00
}
2018-03-23 11:17:52 +08:00
doc, err := models.NewDocument().Find(docId)
2017-05-20 15:27:03 +08:00
if err != nil {
logs.Error("Delete => ", err)
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.get_doc_his_failed")
2017-05-25 15:19:17 +08:00
return
2017-05-20 15:27:03 +08:00
}
// 如果文档所属项目错误
if doc.BookId != bookId {
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.param_error")
2017-05-25 15:19:17 +08:00
return
2017-05-20 15:27:03 +08:00
}
histories, totalCount, err := models.NewDocumentHistory().FindToPager(docId, pageIndex, conf.PageSize)
2017-05-20 15:27:03 +08:00
if err != nil {
logs.Error("分页查找文档历史失败 ->", err)
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.get_doc_his_failed")
2017-05-25 15:19:17 +08:00
return
2017-05-20 15:27:03 +08:00
}
2017-05-25 15:19:17 +08:00
c.Data["List"] = histories
2017-05-25 15:19:17 +08:00
c.Data["PageHtml"] = ""
c.Data["Document"] = doc
2017-05-20 15:27:03 +08:00
if totalCount > 0 {
2018-03-13 14:14:56 +08:00
pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
2018-01-26 18:07:55 +08:00
c.Data["PageHtml"] = pager.HtmlPages()
2017-05-25 15:19:17 +08:00
}
}
func (c *DocumentController) DeleteHistory() {
c.Prepare()
2017-05-25 15:19:17 +08:00
c.TplName = "document/history.tpl"
identify := c.GetString("identify")
2018-03-23 11:17:52 +08:00
docId, err := c.GetInt("doc_id", 0)
historyId, _ := c.GetInt("history_id", 0)
2017-05-25 15:19:17 +08:00
2018-03-23 11:17:52 +08:00
if historyId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
bookId := 0
// 如果是超级管理员则忽略权限判断
2017-06-05 10:52:14 +08:00
if c.Member.IsAdministrator() {
2017-05-25 15:19:17 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error("查找项目失败 ->", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
bookId = book.BookId
2017-05-25 15:19:17 +08:00
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("查找项目失败 ->", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
bookId = bookResult.BookId
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
if docId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
doc, err := models.NewDocument().Find(docId)
2017-05-25 15:19:17 +08:00
if err != nil {
logs.Error("Delete => ", err)
c.JsonResult(6001, i18n.Tr(c.Lang, "message.get_doc_his_failed"))
2017-05-25 15:19:17 +08:00
}
// 如果文档所属项目错误
2018-03-23 11:17:52 +08:00
if doc.BookId != bookId {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
err = models.NewDocumentHistory().Delete(historyId, docId)
2017-05-25 15:19:17 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.failed"))
2017-05-25 15:19:17 +08:00
}
2017-06-05 10:52:14 +08:00
c.JsonResult(0, "ok")
2017-05-25 15:19:17 +08:00
}
// 通过文档历史恢复文档
2017-06-05 10:52:14 +08:00
func (c *DocumentController) RestoreHistory() {
2017-05-25 15:19:17 +08:00
c.Prepare()
2017-05-25 15:19:17 +08:00
c.TplName = "document/history.tpl"
identify := c.GetString("identify")
2018-03-23 11:17:52 +08:00
docId, err := c.GetInt("doc_id", 0)
historyId, _ := c.GetInt("history_id", 0)
2017-05-25 15:19:17 +08:00
2018-03-23 11:17:52 +08:00
if historyId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
bookId := 0
// 如果是超级管理员则忽略权限判断
2017-06-05 10:52:14 +08:00
if c.Member.IsAdministrator() {
2017-05-25 15:19:17 +08:00
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error("FindByIdentify => ", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
bookId = book.BookId
2017-05-25 15:19:17 +08:00
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("FindByIdentify => ", err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
bookId = bookResult.BookId
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
if docId <= 0 {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-20 15:27:03 +08:00
}
2018-03-23 11:17:52 +08:00
doc, err := models.NewDocument().Find(docId)
2017-05-25 15:19:17 +08:00
if err != nil {
logs.Error("Delete => ", err)
c.JsonResult(6001, i18n.Tr(c.Lang, "message.get_doc_his_failed"))
2017-05-25 15:19:17 +08:00
}
// 如果文档所属项目错误
2018-03-23 11:17:52 +08:00
if doc.BookId != bookId {
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
2017-05-25 15:19:17 +08:00
}
2018-03-23 11:17:52 +08:00
err = models.NewDocumentHistory().Restore(historyId, docId, c.Member.MemberId)
2017-05-25 15:19:17 +08:00
if err != nil {
logs.Error(err)
c.JsonResult(6002, i18n.Tr(c.Lang, "message.failed"))
2017-05-25 15:19:17 +08:00
}
2017-06-05 10:52:14 +08:00
c.JsonResult(0, "ok", doc)
2017-05-20 15:27:03 +08:00
}
func (c *DocumentController) Compare() {
2017-06-09 18:14:55 +08:00
c.Prepare()
2017-06-09 18:14:55 +08:00
c.TplName = "document/compare.tpl"
2018-03-23 11:17:52 +08:00
historyId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
identify := c.Ctx.Input.Param(":key")
2018-03-23 11:17:52 +08:00
bookId := 0
editor := EditorMarkdown
// 如果是超级管理员则忽略权限判断
if c.Member.IsAdministrator() {
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error("DocumentController.Compare => ", err)
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
return
}
2018-03-23 11:17:52 +08:00
bookId = book.BookId
c.Data["Model"] = book
editor = book.Editor
} else {
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
if err != nil || bookResult.RoleId == conf.BookObserver {
logs.Error("FindByIdentify => ", err)
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
return
}
2018-03-23 11:17:52 +08:00
bookId = bookResult.BookId
c.Data["Model"] = bookResult
editor = bookResult.Editor
}
2018-03-23 11:17:52 +08:00
if historyId <= 0 {
c.ShowErrorPage(60002, i18n.Tr(c.Lang, "message.param_error"))
}
2018-03-23 11:17:52 +08:00
history, err := models.NewDocumentHistory().Find(historyId)
if err != nil {
logs.Error("DocumentController.Compare => ", err)
c.ShowErrorPage(60003, err.Error())
}
doc, err := models.NewDocument().Find(history.DocumentId)
if err != nil || doc == nil || doc.BookId != bookId {
c.ShowErrorPage(60002, i18n.Tr(c.Lang, "message.doc_not_exist"))
return
}
2018-03-23 11:17:52 +08:00
c.Data["HistoryId"] = historyId
c.Data["DocumentId"] = doc.DocumentId
if editor == EditorMarkdown || editor == EditorCherryMarkdown {
c.Data["HistoryContent"] = history.Markdown
c.Data["Content"] = doc.Markdown
} else {
c.Data["HistoryContent"] = template.HTML(history.Content)
c.Data["Content"] = template.HTML(doc.Content)
}
2017-06-09 18:14:55 +08:00
}
// 判断用户是否可以阅读文档
2018-11-14 15:57:55 +08:00
func (c *DocumentController) isReadable(identify, token string) *models.BookResult {
book, err := models.NewBook().FindByFieldFirst("identify", identify)
if err != nil {
logs.Error(err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.item_not_exist"))
}
2018-11-13 17:33:13 +08:00
bookResult := models.NewBookResult().ToBookResult(*book)
isOk := false
2018-11-14 15:57:55 +08:00
if c.isUserLoggedIn() {
2018-11-13 17:33:13 +08:00
roleId, err := models.NewBook().FindForRoleId(book.BookId, c.Member.MemberId)
if err == nil {
isOk = true
bookResult.MemberId = c.Member.MemberId
bookResult.RoleId = roleId
}
}
/*
* 访
* 访
* 访
* token
* token访
* token访
* password
* password访
* password访
*
* 1. 访session
* 2. session使sessiontokenpassword使tokenpassword
* 3. tokenpassword访
* 4. 使token访
*/
if book.PrivatelyOwned == 1 {
if c.isUserLoggedIn() && c.Member.IsAdministrator() {
return bookResult
}
if isOk { // Project participant.
return bookResult
}
// Use session in preference.
if tokenOrPassword, ok := c.GetSession(identify).(string); ok {
if strings.EqualFold(book.PrivateToken, tokenOrPassword) || strings.EqualFold(book.BookPassword, tokenOrPassword) {
return bookResult
}
}
// Next: Session not exist or not correct.
if book.PrivateToken != "" && book.PrivateToken == token {
c.SetSession(identify, token)
return bookResult
} else if book.BookPassword != "" {
// Send a page for inputting password.
// For verification, see function DocumentController.CheckPassword
body, err := c.ExecuteViewPathTemplate("document/document_password.tpl",
map[string]string{"Identify": book.Identify, "Lang": c.Lang})
if err != nil {
logs.Error("显示密码页面失败 ->", err)
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
2018-11-14 15:57:55 +08:00
}
c.CustomAbort(200, body)
} else {
// No permission to access this book.
logs.Info("尝试访问文档但权限不足 ->", identify, token)
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
}
}
return bookResult
}
func promptUserToLogIn(c *DocumentController) {
logs.Info("Access " + c.Ctx.Request.URL.RequestURI() + " not permitted.")
logs.Info(" Access will be redirected to login page(SessionId: " + c.CruSession.SessionID(context.TODO()) + ").")
if c.IsAjax() {
c.JsonResult(6000, i18n.Tr(c.Lang, "message.need_relogin"))
} else {
c.Redirect(conf.URLFor("AccountController.Login")+"?url="+url.PathEscape(conf.BaseUrl+c.Ctx.Request.URL.RequestURI()), 302)
}
}