mirror of
https://github.com/documize/community.git
synced 2025-08-02 20:15:26 +02:00
improve level code
This commit is contained in:
parent
049b83e0b9
commit
5f59e95495
25 changed files with 1104 additions and 461 deletions
|
@ -31,8 +31,9 @@ import (
|
|||
"github.com/documize/community/domain/section/provider"
|
||||
"github.com/documize/community/model/activity"
|
||||
"github.com/documize/community/model/audit"
|
||||
"github.com/documize/community/model/doc"
|
||||
"github.com/documize/community/model/page"
|
||||
pm "github.com/documize/community/model/permission"
|
||||
"github.com/documize/community/model/workflow"
|
||||
htmldiff "github.com/documize/html-diff"
|
||||
)
|
||||
|
||||
|
@ -53,17 +54,14 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// check param
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
// read payload
|
||||
defer streamutil.Close(r.Body)
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
|
@ -90,6 +88,38 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Check protection and approval process
|
||||
document, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, err.Error())
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Protect locked
|
||||
if document.Protection == workflow.ProtectionLock {
|
||||
response.WriteForbiddenError(w)
|
||||
h.Runtime.Log.Info("attempted write to locked document")
|
||||
return
|
||||
}
|
||||
|
||||
// Check edit permission
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
// if document review process then we must mark page as pending
|
||||
if document.Protection == workflow.ProtectionReview {
|
||||
if model.Page.RelativeID == "" {
|
||||
model.Page.Status = workflow.ChangePendingNew
|
||||
} else {
|
||||
model.Page.Status = workflow.ChangePending
|
||||
}
|
||||
} else {
|
||||
model.Page.Status = workflow.ChangePublished
|
||||
}
|
||||
|
||||
pageID := uniqueid.Generate()
|
||||
model.Page.RefID = pageID
|
||||
model.Meta.PageID = pageID
|
||||
|
@ -97,7 +127,6 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
model.Meta.UserID = ctx.UserID // required for Render call below
|
||||
model.Page.SetDefaults()
|
||||
model.Meta.SetDefaults()
|
||||
// page.Title = template.HTMLEscapeString(page.Title)
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
|
@ -229,16 +258,11 @@ func (h *Handler) GetPages(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteJSON(w, pages)
|
||||
}
|
||||
|
||||
// Delete deletes a page.
|
||||
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.delete"
|
||||
// GetMeta gets page meta data for specified document page.
|
||||
func (h *Handler) GetMeta(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.meta"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
if !h.Runtime.Product.License.IsValid() {
|
||||
response.WriteBadLicense(w)
|
||||
return
|
||||
}
|
||||
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
|
@ -251,156 +275,31 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
if !permission.CanViewDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
meta, err := h.Store.Page.GetPageMeta(ctx, pageID)
|
||||
if err == sql.ErrNoRows {
|
||||
response.WriteNotFoundError(w, method, pageID)
|
||||
h.Runtime.Log.Info(method + " no record")
|
||||
meta = page.Meta{}
|
||||
response.WriteJSON(w, meta)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
if meta.DocumentID != documentID {
|
||||
response.WriteBadRequestError(w, method, "documentID mismatch")
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
page, err := h.Store.Page.Get(ctx, pageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(page.BlockID) > 0 {
|
||||
h.Store.Block.DecrementUsage(ctx, page.BlockID)
|
||||
}
|
||||
|
||||
_, err = h.Store.Page.Delete(ctx, documentID, pageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
|
||||
LabelID: doc.LabelID,
|
||||
SourceID: documentID,
|
||||
SourceType: activity.SourceTypeDocument,
|
||||
ActivityType: activity.TypeDeleted})
|
||||
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeSectionDelete)
|
||||
|
||||
go h.Indexer.DeleteContent(ctx, pageID)
|
||||
|
||||
h.Store.Link.DeleteSourcePageLinks(ctx, pageID)
|
||||
|
||||
h.Store.Link.MarkOrphanPageLink(ctx, pageID)
|
||||
|
||||
h.Store.Page.DeletePageRevisions(ctx, pageID)
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
response.WriteEmpty(w)
|
||||
}
|
||||
|
||||
// DeletePages batch deletes pages.
|
||||
func (h *Handler) DeletePages(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.delete.pages"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
if !h.Runtime.Product.License.IsValid() {
|
||||
response.WriteBadLicense(w)
|
||||
return
|
||||
}
|
||||
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
defer streamutil.Close(r.Body)
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, "Bad body")
|
||||
return
|
||||
}
|
||||
|
||||
model := new([]page.LevelRequest)
|
||||
err = json.Unmarshal(body, &model)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, "JSON marshal")
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, page := range *model {
|
||||
pageData, err := h.Store.Page.Get(ctx, page.PageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(pageData.BlockID) > 0 {
|
||||
h.Store.Block.DecrementUsage(ctx, pageData.BlockID)
|
||||
}
|
||||
|
||||
_, err = h.Store.Page.Delete(ctx, documentID, page.PageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
go h.Indexer.DeleteContent(ctx, page.PageID)
|
||||
|
||||
h.Store.Link.DeleteSourcePageLinks(ctx, page.PageID)
|
||||
|
||||
h.Store.Link.MarkOrphanPageLink(ctx, page.PageID)
|
||||
|
||||
h.Store.Page.DeletePageRevisions(ctx, page.PageID)
|
||||
}
|
||||
|
||||
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
|
||||
LabelID: doc.LabelID,
|
||||
SourceID: documentID,
|
||||
SourceType: activity.SourceTypeDocument,
|
||||
ActivityType: activity.TypeDeleted})
|
||||
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeSectionDelete)
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
response.WriteEmpty(w)
|
||||
response.WriteJSON(w, meta)
|
||||
}
|
||||
|
||||
// Update will persist changed page and note the fact
|
||||
|
@ -415,11 +314,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// if !ctx.Editor {
|
||||
// response.WriteForbiddenError(w)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Check params
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
|
@ -432,11 +327,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
// Read payload
|
||||
defer streamutil.Close(r.Body)
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
|
@ -458,13 +349,26 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Check protection and approval process
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
response.WriteBadRequestError(w, method, err.Error())
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if doc.Protection == workflow.ProtectionLock {
|
||||
response.WriteForbiddenError(w)
|
||||
h.Runtime.Log.Info("attempted write to locked document")
|
||||
return
|
||||
}
|
||||
|
||||
// Check edit permission
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -492,6 +396,11 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
skipRevision := false
|
||||
skipRevision, err = strconv.ParseBool(request.Query(r, "r"))
|
||||
|
||||
// We don't track revisions for non-published pages
|
||||
if model.Page.Status != workflow.ChangePublished {
|
||||
skipRevision = true
|
||||
}
|
||||
|
||||
err = h.Store.Page.Update(ctx, model.Page, refID, ctx.UserID, skipRevision)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -562,6 +471,258 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteJSON(w, updatedPage)
|
||||
}
|
||||
|
||||
// Delete deletes a page.
|
||||
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.delete"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
if !h.Runtime.Product.License.IsValid() {
|
||||
response.WriteBadLicense(w)
|
||||
return
|
||||
}
|
||||
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
pageID := request.Param(r, "pageID")
|
||||
if len(pageID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "pageID")
|
||||
return
|
||||
}
|
||||
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Protect locked
|
||||
if doc.Protection == workflow.ProtectionLock {
|
||||
response.WriteForbiddenError(w)
|
||||
h.Runtime.Log.Info("attempted delete section on locked document")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := h.Store.Page.Get(ctx, pageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(p.BlockID) > 0 {
|
||||
h.Store.Block.DecrementUsage(ctx, p.BlockID)
|
||||
}
|
||||
|
||||
_, err = h.Store.Page.Delete(ctx, documentID, pageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
|
||||
LabelID: doc.LabelID,
|
||||
SourceID: documentID,
|
||||
SourceType: activity.SourceTypeDocument,
|
||||
ActivityType: activity.TypeDeleted})
|
||||
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeSectionDelete)
|
||||
|
||||
go h.Indexer.DeleteContent(ctx, pageID)
|
||||
|
||||
h.Store.Link.DeleteSourcePageLinks(ctx, pageID)
|
||||
|
||||
h.Store.Link.MarkOrphanPageLink(ctx, pageID)
|
||||
|
||||
h.Store.Page.DeletePageRevisions(ctx, pageID)
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
// Re-level all pages in document
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
p2, err := h.Store.Page.GetPages(ctx, documentID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
page.Levelize(p2)
|
||||
|
||||
for _, i := range p2 {
|
||||
err = h.Store.Page.UpdateLevel(ctx, documentID, i.RefID, int(i.Level))
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
response.WriteEmpty(w)
|
||||
}
|
||||
|
||||
// DeletePages batch deletes pages.
|
||||
func (h *Handler) DeletePages(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.delete.pages"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
if !h.Runtime.Product.License.IsValid() {
|
||||
response.WriteBadLicense(w)
|
||||
return
|
||||
}
|
||||
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
if !permission.CanChangeDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
defer streamutil.Close(r.Body)
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, "Bad body")
|
||||
return
|
||||
}
|
||||
|
||||
model := new([]page.LevelRequest)
|
||||
err = json.Unmarshal(body, &model)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, "JSON marshal")
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Protect locked
|
||||
if doc.Protection == workflow.ProtectionLock {
|
||||
response.WriteForbiddenError(w)
|
||||
h.Runtime.Log.Info("attempted delete sections on locked document")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, page := range *model {
|
||||
pageData, err := h.Store.Page.Get(ctx, page.PageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(pageData.BlockID) > 0 {
|
||||
h.Store.Block.DecrementUsage(ctx, pageData.BlockID)
|
||||
}
|
||||
|
||||
_, err = h.Store.Page.Delete(ctx, documentID, page.PageID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
go h.Indexer.DeleteContent(ctx, page.PageID)
|
||||
|
||||
h.Store.Link.DeleteSourcePageLinks(ctx, page.PageID)
|
||||
|
||||
h.Store.Link.MarkOrphanPageLink(ctx, page.PageID)
|
||||
|
||||
h.Store.Page.DeletePageRevisions(ctx, page.PageID)
|
||||
}
|
||||
|
||||
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
|
||||
LabelID: doc.LabelID,
|
||||
SourceID: documentID,
|
||||
SourceType: activity.SourceTypeDocument,
|
||||
ActivityType: activity.TypeDeleted})
|
||||
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeSectionDelete)
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
// Re-level all pages in document
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
p2, err := h.Store.Page.GetPages(ctx, documentID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
page.Levelize(p2)
|
||||
|
||||
for _, i := range p2 {
|
||||
err = h.Store.Page.UpdateLevel(ctx, documentID, i.RefID, int(i.Level))
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
response.WriteEmpty(w)
|
||||
}
|
||||
|
||||
//**************************************************
|
||||
// Table of Contents
|
||||
//**************************************************
|
||||
|
||||
// ChangePageSequence will swap page sequence for a given number of pages.
|
||||
func (h *Handler) ChangePageSequence(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.sequence"
|
||||
|
@ -684,75 +845,10 @@ func (h *Handler) ChangePageLevel(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteEmpty(w)
|
||||
}
|
||||
|
||||
// GetMeta gets page meta data for specified document page.
|
||||
func (h *Handler) GetMeta(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.meta"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
pageID := request.Param(r, "pageID")
|
||||
if len(pageID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "pageID")
|
||||
return
|
||||
}
|
||||
|
||||
if !permission.CanViewDocument(ctx, *h.Store, documentID) {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
meta, err := h.Store.Page.GetPageMeta(ctx, pageID)
|
||||
if err == sql.ErrNoRows {
|
||||
response.WriteNotFoundError(w, method, pageID)
|
||||
h.Runtime.Log.Info(method + " no record")
|
||||
meta = page.Meta{}
|
||||
response.WriteJSON(w, meta)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
if meta.DocumentID != documentID {
|
||||
response.WriteBadRequestError(w, method, "documentID mismatch")
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteJSON(w, meta)
|
||||
}
|
||||
|
||||
//**************************************************
|
||||
// Copy Move Page
|
||||
//**************************************************
|
||||
|
||||
// GetMoveCopyTargets returns available documents for page copy/move axction.
|
||||
func (h *Handler) GetMoveCopyTargets(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.targets"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
var d []doc.Document
|
||||
var err error
|
||||
|
||||
d, err = h.Store.Document.DocumentList(ctx)
|
||||
if len(d) == 0 {
|
||||
d = []doc.Document{}
|
||||
}
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteJSON(w, d)
|
||||
}
|
||||
|
||||
// Copy copies page to either same or different document.
|
||||
func (h *Handler) Copy(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.targets"
|
||||
|
@ -790,6 +886,12 @@ func (h *Handler) Copy(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// workflow check
|
||||
if doc.Protection == workflow.ProtectionLock || doc.Protection == workflow.ProtectionReview {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := h.Store.Page.Get(ctx, pageID)
|
||||
if err == sql.ErrNoRows {
|
||||
response.WriteNotFoundError(w, method, documentID)
|
||||
|
@ -1101,3 +1203,176 @@ func (h *Handler) Rollback(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
response.WriteJSON(w, p)
|
||||
}
|
||||
|
||||
//**************************************************
|
||||
// Bulk data fetching (reduce network traffic)
|
||||
//**************************************************
|
||||
|
||||
// FetchPages returns all page data for given document: page, meta data, pending changes.
|
||||
func (h *Handler) FetchPages(w http.ResponseWriter, r *http.Request) {
|
||||
method := "page.FetchPages"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
model := []page.BulkRequest{}
|
||||
|
||||
// check params
|
||||
documentID := request.Param(r, "documentID")
|
||||
if len(documentID) == 0 {
|
||||
response.WriteMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// published pages and new pages awaiting approval
|
||||
pages, err := h.Store.Page.GetPages(ctx, documentID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
if len(pages) == 0 {
|
||||
pages = []page.Page{}
|
||||
}
|
||||
|
||||
// unpublished pages
|
||||
unpublished, err := h.Store.Page.GetUnpublishedPages(ctx, documentID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
if len(unpublished) == 0 {
|
||||
unpublished = []page.Page{}
|
||||
}
|
||||
|
||||
// meta for all pages
|
||||
meta, err := h.Store.Page.GetDocumentPageMeta(ctx, documentID, false)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
if len(meta) == 0 {
|
||||
meta = []page.Meta{}
|
||||
}
|
||||
|
||||
// permissions
|
||||
perms, err := h.Store.Permission.GetUserSpacePermissions(ctx, doc.LabelID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
return
|
||||
}
|
||||
if len(perms) == 0 {
|
||||
perms = []pm.Permission{}
|
||||
}
|
||||
permissions := pm.DecodeUserPermissions(perms)
|
||||
|
||||
roles, err := h.Store.Permission.GetUserDocumentPermissions(ctx, doc.RefID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
response.WriteServerError(w, method, err)
|
||||
return
|
||||
}
|
||||
if len(roles) == 0 {
|
||||
roles = []pm.Permission{}
|
||||
}
|
||||
docRoles := pm.DecodeUserDocumentPermissions(roles)
|
||||
|
||||
// check document view permissions
|
||||
if !permissions.SpaceView && !permissions.SpaceManage && !permissions.SpaceOwner {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
// process published pages
|
||||
for _, p := range pages {
|
||||
// only send back pages that user can see
|
||||
process := false
|
||||
forcePending := false
|
||||
|
||||
if process == false && p.Status == workflow.ChangePublished {
|
||||
process = true
|
||||
}
|
||||
if process == false && p.Status == workflow.ChangePendingNew && p.RelativeID == "" && p.UserID == ctx.UserID {
|
||||
process = true
|
||||
forcePending = true // user has newly created page which should be treated as pending
|
||||
}
|
||||
if process == false && p.Status == workflow.ChangeUnderReview && p.RelativeID == "" && p.UserID == ctx.UserID {
|
||||
process = true
|
||||
forcePending = true // user has newly created page which should be treated as pending
|
||||
}
|
||||
if process == false && p.Status == workflow.ChangeUnderReview && p.RelativeID == "" && (permissions.DocumentApprove || docRoles.DocumentRoleApprove) {
|
||||
process = true
|
||||
forcePending = true // user has newly created page which should be treated as pending
|
||||
}
|
||||
|
||||
if process {
|
||||
d := page.BulkRequest{}
|
||||
d.Page = p
|
||||
|
||||
for _, m := range meta {
|
||||
if p.RefID == m.PageID {
|
||||
d.Meta = m
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d.Pending = []page.PendingPage{}
|
||||
|
||||
// process pending pages
|
||||
for _, up := range unpublished {
|
||||
if up.RelativeID == p.RefID {
|
||||
ud := page.PendingPage{}
|
||||
ud.Page = up
|
||||
|
||||
for _, m := range meta {
|
||||
if up.RefID == m.PageID {
|
||||
ud.Meta = m
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
owner, err := h.Store.User.Get(ctx, up.UserID)
|
||||
if err == nil {
|
||||
ud.Owner = owner.Fullname()
|
||||
}
|
||||
|
||||
d.Pending = append(d.Pending, ud)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle situation where we need approval, and user has created new page
|
||||
if forcePending && len(d.Pending) == 0 && doc.Protection == workflow.ProtectionReview {
|
||||
ud := page.PendingPage{}
|
||||
ud.Page = d.Page
|
||||
ud.Meta = d.Meta
|
||||
|
||||
owner, err := h.Store.User.Get(ctx, d.Page.UserID)
|
||||
if err == nil {
|
||||
ud.Owner = owner.Fullname()
|
||||
}
|
||||
|
||||
d.Pending = append(d.Pending, ud)
|
||||
}
|
||||
|
||||
model = append(model, d)
|
||||
}
|
||||
}
|
||||
|
||||
// Attach numbers to pages, 1.1, 2.1.1 etc.
|
||||
t := []page.Page{}
|
||||
for _, i := range model {
|
||||
t = append(t, i.Page)
|
||||
}
|
||||
page.Numberize(t)
|
||||
for i, j := range t {
|
||||
model[i].Page = j
|
||||
}
|
||||
|
||||
// deliver payload
|
||||
response.WriteJSON(w, model)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue