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)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ type Scope struct {
|
|||
Runtime *env.Runtime
|
||||
}
|
||||
|
||||
//**************************************************
|
||||
// Page Revisions
|
||||
//**************************************************
|
||||
|
||||
// Add inserts the given page into the page table, adds that page to the queue of pages to index and audits that the page has been added.
|
||||
func (s Scope) Add(ctx domain.RequestContext, model page.NewPage) (err error) {
|
||||
model.Page.OrgID = ctx.OrgID
|
||||
|
@ -54,8 +58,8 @@ func (s Scope) Add(ctx domain.RequestContext, model page.NewPage) (err error) {
|
|||
model.Page.Sequence = maxSeq * 2
|
||||
}
|
||||
|
||||
_, err = ctx.Transaction.Exec("INSERT INTO page (refid, orgid, documentid, userid, contenttype, pagetype, level, title, body, revisions, sequence, blockid, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
model.Page.RefID, model.Page.OrgID, model.Page.DocumentID, model.Page.UserID, model.Page.ContentType, model.Page.PageType, model.Page.Level, model.Page.Title, model.Page.Body, model.Page.Revisions, model.Page.Sequence, model.Page.BlockID, model.Page.Created, model.Page.Revised)
|
||||
_, err = ctx.Transaction.Exec("INSERT INTO page (refid, orgid, documentid, userid, contenttype, pagetype, level, title, body, revisions, sequence, blockid, status, relativeid, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
model.Page.RefID, model.Page.OrgID, model.Page.DocumentID, model.Page.UserID, model.Page.ContentType, model.Page.PageType, model.Page.Level, model.Page.Title, model.Page.Body, model.Page.Revisions, model.Page.Sequence, model.Page.BlockID, model.Page.Status, model.Page.RelativeID, model.Page.Created, model.Page.Revised)
|
||||
|
||||
_, err = ctx.Transaction.Exec("INSERT INTO pagemeta (pageid, orgid, userid, documentid, rawbody, config, externalsource, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
model.Meta.PageID, model.Meta.OrgID, model.Meta.UserID, model.Meta.DocumentID, model.Meta.RawBody, model.Meta.Config, model.Meta.ExternalSource, model.Meta.Created, model.Meta.Revised)
|
||||
|
@ -69,7 +73,7 @@ func (s Scope) Add(ctx domain.RequestContext, model page.NewPage) (err error) {
|
|||
|
||||
// Get returns the pageID page record from the page table.
|
||||
func (s Scope) Get(ctx domain.RequestContext, pageID string) (p page.Page, err error) {
|
||||
err = s.Runtime.Db.Get(&p, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.blockid, a.created, a.revised FROM page a WHERE a.orgid=? AND a.refid=?",
|
||||
err = s.Runtime.Db.Get(&p, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.blockid, a.status, a.relativeid, a.created, a.revised FROM page a WHERE a.orgid=? AND a.refid=?",
|
||||
ctx.OrgID, pageID)
|
||||
|
||||
if err != nil {
|
||||
|
@ -79,9 +83,9 @@ func (s Scope) Get(ctx domain.RequestContext, pageID string) (p page.Page, err e
|
|||
return
|
||||
}
|
||||
|
||||
// GetPages returns a slice containing all the page records for a given documentID, in presentation sequence.
|
||||
// GetPages returns a slice containing all published page records for a given documentID, in presentation sequence.
|
||||
func (s Scope) GetPages(ctx domain.RequestContext, documentID string) (p []page.Page, err error) {
|
||||
err = s.Runtime.Db.Select(&p, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.blockid, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? ORDER BY a.sequence", ctx.OrgID, documentID)
|
||||
err = s.Runtime.Db.Select(&p, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.blockid, a.status, a.relativeid, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? AND (a.status=0 OR ((a.status=4 OR a.status=2) AND a.relativeid='')) ORDER BY a.sequence", ctx.OrgID, documentID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "execute get pages")
|
||||
|
@ -90,10 +94,21 @@ func (s Scope) GetPages(ctx domain.RequestContext, documentID string) (p []page.
|
|||
return
|
||||
}
|
||||
|
||||
// GetUnpublishedPages returns a slice containing all published page records for a given documentID, in presentation sequence.
|
||||
func (s Scope) GetUnpublishedPages(ctx domain.RequestContext, documentID string) (p []page.Page, err error) {
|
||||
err = s.Runtime.Db.Select(&p, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.blockid, a.status, a.relativeid, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? AND a.status!=0 AND a.relativeid!='' ORDER BY a.sequence", ctx.OrgID, documentID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "execute get unpublished pages")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPagesWithoutContent returns a slice containing all the page records for a given documentID, in presentation sequence,
|
||||
// but without the body field (which holds the HTML content).
|
||||
func (s Scope) GetPagesWithoutContent(ctx domain.RequestContext, documentID string) (pages []page.Page, err error) {
|
||||
err = s.Runtime.Db.Select(&pages, "SELECT id, refid, orgid, documentid, userid, contenttype, pagetype, sequence, level, title, revisions, blockid, created, revised FROM page WHERE orgid=? AND documentid=? ORDER BY sequence", ctx.OrgID, documentID)
|
||||
err = s.Runtime.Db.Select(&pages, "SELECT id, refid, orgid, documentid, userid, contenttype, pagetype, sequence, level, title, revisions, blockid, status, relativeid, created, revised FROM page WHERE orgid=? AND documentid=? AND status=0 ORDER BY sequence", ctx.OrgID, documentID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("Unable to execute select pages for org %s and document %s", ctx.OrgID, documentID))
|
||||
|
@ -119,7 +134,7 @@ func (s Scope) Update(ctx domain.RequestContext, page page.Page, refID, userID s
|
|||
}
|
||||
|
||||
// Update page
|
||||
_, err = ctx.Transaction.NamedExec("UPDATE page SET documentid=:documentid, level=:level, title=:title, body=:body, revisions=:revisions, sequence=:sequence, revised=:revised WHERE orgid=:orgid AND refid=:refid",
|
||||
_, err = ctx.Transaction.NamedExec("UPDATE page SET documentid=:documentid, level=:level, title=:title, body=:body, revisions=:revisions, sequence=:sequence, status=:status, relativeid=:relativeid, revised=:revised WHERE orgid=:orgid AND refid=:refid",
|
||||
&page)
|
||||
|
||||
if err != nil {
|
||||
|
@ -139,6 +154,27 @@ func (s Scope) Update(ctx domain.RequestContext, page page.Page, refID, userID s
|
|||
return
|
||||
}
|
||||
|
||||
// Delete deletes the pageID page in the document.
|
||||
// It then propagates that change into the search table, adds a delete the page revisions history, and audits that the page has been removed.
|
||||
func (s Scope) Delete(ctx domain.RequestContext, documentID, pageID string) (rows int64, err error) {
|
||||
b := mysql.BaseQuery{}
|
||||
rows, err = b.DeleteConstrained(ctx.Transaction, "page", ctx.OrgID, pageID)
|
||||
|
||||
if err == nil {
|
||||
_, _ = b.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM pagemeta WHERE orgid='%s' AND pageid='%s'", ctx.OrgID, pageID))
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
_, _ = b.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM useraction WHERE orgid='%s' AND reftypeid='%s' AND reftype='P'", ctx.OrgID, pageID))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//**************************************************
|
||||
// Page Meta
|
||||
//**************************************************
|
||||
|
||||
// UpdateMeta persists meta information associated with a document page.
|
||||
func (s Scope) UpdateMeta(ctx domain.RequestContext, meta page.Meta, updateUserID bool) (err error) {
|
||||
meta.Revised = time.Now().UTC()
|
||||
|
@ -157,43 +193,6 @@ func (s Scope) UpdateMeta(ctx domain.RequestContext, meta page.Meta, updateUserI
|
|||
return
|
||||
}
|
||||
|
||||
// UpdateSequence changes the presentation sequence of the pageID page in the document.
|
||||
// It then propagates that change into the search table and audits that it has occurred.
|
||||
func (s Scope) UpdateSequence(ctx domain.RequestContext, documentID, pageID string, sequence float64) (err error) {
|
||||
_, err = ctx.Transaction.Exec("UPDATE page SET sequence=? WHERE orgid=? AND refid=?", sequence, ctx.OrgID, pageID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "execute page sequence update")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateLevel changes the heading level of the pageID page in the document.
|
||||
// It then propagates that change into the search table and audits that it has occurred.
|
||||
func (s Scope) UpdateLevel(ctx domain.RequestContext, documentID, pageID string, level int) (err error) {
|
||||
_, err = ctx.Transaction.Exec("UPDATE page SET level=? WHERE orgid=? AND refid=?", level, ctx.OrgID, pageID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "execute page level update")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Delete deletes the pageID page in the document.
|
||||
// It then propagates that change into the search table, adds a delete the page revisions history, and audits that the page has been removed.
|
||||
func (s Scope) Delete(ctx domain.RequestContext, documentID, pageID string) (rows int64, err error) {
|
||||
b := mysql.BaseQuery{}
|
||||
rows, err = b.DeleteConstrained(ctx.Transaction, "page", ctx.OrgID, pageID)
|
||||
|
||||
if err == nil {
|
||||
_, _ = b.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM pagemeta WHERE orgid='%s' AND pageid='%s'", ctx.OrgID, pageID))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPageMeta returns the meta information associated with the page.
|
||||
func (s Scope) GetPageMeta(ctx domain.RequestContext, pageID string) (meta page.Meta, err error) {
|
||||
err = s.Runtime.Db.Get(&meta, "SELECT id, pageid, orgid, userid, documentid, rawbody, coalesce(config,JSON_UNQUOTE('{}')) as config, externalsource, created, revised FROM pagemeta WHERE orgid=? AND pageid=?",
|
||||
|
@ -222,9 +221,51 @@ func (s Scope) GetDocumentPageMeta(ctx domain.RequestContext, documentID string,
|
|||
return
|
||||
}
|
||||
|
||||
/********************
|
||||
* Page Revisions
|
||||
********************/
|
||||
//**************************************************
|
||||
// Table of contents
|
||||
//**************************************************
|
||||
|
||||
// UpdateSequence changes the presentation sequence of the pageID page in the document.
|
||||
// It then propagates that change into the search table and audits that it has occurred.
|
||||
func (s Scope) UpdateSequence(ctx domain.RequestContext, documentID, pageID string, sequence float64) (err error) {
|
||||
_, err = ctx.Transaction.Exec("UPDATE page SET sequence=? WHERE orgid=? AND refid=?", sequence, ctx.OrgID, pageID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "execute page sequence update")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateLevel changes the heading level of the pageID page in the document.
|
||||
// It then propagates that change into the search table and audits that it has occurred.
|
||||
func (s Scope) UpdateLevel(ctx domain.RequestContext, documentID, pageID string, level int) (err error) {
|
||||
_, err = ctx.Transaction.Exec("UPDATE page SET level=? WHERE orgid=? AND refid=?", level, ctx.OrgID, pageID)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "execute page level update")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetNextPageSequence returns the next sequence numbner to use for a page in given document.
|
||||
func (s Scope) GetNextPageSequence(ctx domain.RequestContext, documentID string) (maxSeq float64, err error) {
|
||||
row := s.Runtime.Db.QueryRow("SELECT max(sequence) FROM page WHERE orgid=? AND documentid=?", ctx.OrgID, documentID)
|
||||
|
||||
err = row.Scan(&maxSeq)
|
||||
if err != nil {
|
||||
maxSeq = 2048
|
||||
}
|
||||
|
||||
maxSeq = maxSeq * 2
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//**************************************************
|
||||
// Page Revisions
|
||||
//**************************************************
|
||||
|
||||
// GetPageRevision returns the revisionID page revision record.
|
||||
func (s Scope) GetPageRevision(ctx domain.RequestContext, revisionID string) (revision page.Revision, err error) {
|
||||
|
@ -273,17 +314,3 @@ func (s Scope) DeletePageRevisions(ctx domain.RequestContext, pageID string) (ro
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// GetNextPageSequence returns the next sequence numbner to use for a page in given document.
|
||||
func (s Scope) GetNextPageSequence(ctx domain.RequestContext, documentID string) (maxSeq float64, err error) {
|
||||
row := s.Runtime.Db.QueryRow("SELECT max(sequence) FROM page WHERE orgid=? AND documentid=?", ctx.OrgID, documentID)
|
||||
|
||||
err = row.Scan(&maxSeq)
|
||||
if err != nil {
|
||||
maxSeq = 2048
|
||||
}
|
||||
|
||||
maxSeq = maxSeq * 2
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue