mirror of
https://github.com/documize/community.git
synced 2025-07-19 05:09:42 +02:00
Provider foundation for doc lifecycle and versions
This commit is contained in:
parent
4e32bffebe
commit
958f4d30b9
19 changed files with 918 additions and 782 deletions
|
@ -52,7 +52,7 @@ Space view.
|
||||||
|
|
||||||
## Latest version
|
## Latest version
|
||||||
|
|
||||||
Community edition: v1.58.0
|
Community edition: v1.59.0
|
||||||
|
|
||||||
## OS support
|
## OS support
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,7 @@ func setupAccount(rt *env.Runtime, completion onboardRequest, serial string) (er
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign permissions to space
|
// assign permissions to space
|
||||||
perms := []string{"view", "manage", "own", "doc-add", "doc-edit", "doc-delete", "doc-move", "doc-copy", "doc-template", "doc-approve"}
|
perms := []string{"view", "manage", "own", "doc-add", "doc-edit", "doc-delete", "doc-move", "doc-copy", "doc-template", "doc-approve", "doc-version", "doc-lifecycle"}
|
||||||
for _, p := range perms {
|
for _, p := range perms {
|
||||||
sql = fmt.Sprintf("insert into permission (orgid, who, whoid, action, scope, location, refid) values (\"%s\", 'user', \"%s\", \"%s\", 'object', 'space', \"%s\")", orgID, userID, p, labelID)
|
sql = fmt.Sprintf("insert into permission (orgid, who, whoid, action, scope, location, refid) values (\"%s\", 'user', \"%s\", \"%s\", 'object', 'space', \"%s\")", orgID, userID, p, labelID)
|
||||||
_, err = runSQL(rt, sql)
|
_, err = runSQL(rt, sql)
|
||||||
|
|
22
core/database/scripts/autobuild/db_00019.sql
Normal file
22
core/database/scripts/autobuild/db_00019.sql
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* enterprise edition */
|
||||||
|
|
||||||
|
-- document lifecycle and versions
|
||||||
|
ALTER TABLE document ADD COLUMN `lifecycle` INT NOT NULL DEFAULT 1 AFTER `approval`;
|
||||||
|
ALTER TABLE document ADD COLUMN `versioned` INT NOT NULL DEFAULT 0 AFTER `lifecycle`;
|
||||||
|
ALTER TABLE document ADD COLUMN `versionid` VARCHAR(100) DEFAULT '' NOT NULL AFTER `versioned`;
|
||||||
|
ALTER TABLE document ADD COLUMN `versionorder` INT NOT NULL DEFAULT 0 AFTER `versionid`;
|
||||||
|
ALTER TABLE document ADD COLUMN `groupid` CHAR(16) NOT NULL COLLATE utf8_bin AFTER `versionorder`;
|
||||||
|
|
||||||
|
-- grant doc-lifecycle permission
|
||||||
|
INSERT INTO permission(orgid, who, whoid, action, scope, location, refid, created)
|
||||||
|
SELECT orgid, who, whoid, 'doc-lifecycle' AS action, scope, location, refid, created
|
||||||
|
FROM permission
|
||||||
|
WHERE action = 'doc-edit' OR action = 'doc-approve';
|
||||||
|
|
||||||
|
-- grant doc-versions permission
|
||||||
|
INSERT INTO permission(orgid, who, whoid, action, scope, location, refid, created)
|
||||||
|
SELECT orgid, who, whoid, 'doc-version' AS action, scope, location, refid, created
|
||||||
|
FROM permission
|
||||||
|
WHERE action = 'doc-edit' OR action = 'doc-approve';
|
||||||
|
|
||||||
|
-- deprecations
|
|
@ -30,6 +30,7 @@ import (
|
||||||
indexer "github.com/documize/community/domain/search"
|
indexer "github.com/documize/community/domain/search"
|
||||||
"github.com/documize/community/model/attachment"
|
"github.com/documize/community/model/attachment"
|
||||||
"github.com/documize/community/model/audit"
|
"github.com/documize/community/model/audit"
|
||||||
|
"github.com/documize/community/model/workflow"
|
||||||
uuid "github.com/nu7hatch/gouuid"
|
uuid "github.com/nu7hatch/gouuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -161,7 +162,12 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
||||||
d, _ := h.Store.Document.Get(ctx, documentID)
|
d, _ := h.Store.Document.Get(ctx, documentID)
|
||||||
|
|
||||||
|
if d.Lifecycle == workflow.LifecycleLive {
|
||||||
go h.Indexer.IndexDocument(ctx, d, a)
|
go h.Indexer.IndexDocument(ctx, d, a)
|
||||||
|
} else {
|
||||||
|
go h.Indexer.DeleteDocument(ctx, d.RefID)
|
||||||
|
}
|
||||||
|
|
||||||
response.WriteEmpty(w)
|
response.WriteEmpty(w)
|
||||||
}
|
}
|
||||||
|
@ -236,7 +242,12 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
all, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
all, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
||||||
d, _ := h.Store.Document.Get(ctx, documentID)
|
d, _ := h.Store.Document.Get(ctx, documentID)
|
||||||
|
|
||||||
|
if d.Lifecycle == workflow.LifecycleLive {
|
||||||
go h.Indexer.IndexDocument(ctx, d, all)
|
go h.Indexer.IndexDocument(ctx, d, all)
|
||||||
|
} else {
|
||||||
|
go h.Indexer.DeleteDocument(ctx, d.RefID)
|
||||||
|
}
|
||||||
|
|
||||||
response.WriteEmpty(w)
|
response.WriteEmpty(w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,7 +249,12 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||||
h.Store.Audit.Record(ctx, audit.EventTypeDocumentUpdate)
|
h.Store.Audit.Record(ctx, audit.EventTypeDocumentUpdate)
|
||||||
|
|
||||||
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
||||||
|
|
||||||
|
if d.Lifecycle == workflow.LifecycleLive {
|
||||||
go h.Indexer.IndexDocument(ctx, d, a)
|
go h.Indexer.IndexDocument(ctx, d, a)
|
||||||
|
} else {
|
||||||
|
go h.Indexer.DeleteDocument(ctx, d.RefID)
|
||||||
|
}
|
||||||
|
|
||||||
response.WriteEmpty(w)
|
response.WriteEmpty(w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,16 @@ type Scope struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add inserts the given document record into the document table and audits that it has been done.
|
// Add inserts the given document record into the document table and audits that it has been done.
|
||||||
func (s Scope) Add(ctx domain.RequestContext, document doc.Document) (err error) {
|
func (s Scope) Add(ctx domain.RequestContext, d doc.Document) (err error) {
|
||||||
document.OrgID = ctx.OrgID
|
d.OrgID = ctx.OrgID
|
||||||
document.Created = time.Now().UTC()
|
d.Created = time.Now().UTC()
|
||||||
document.Revised = document.Created // put same time in both fields
|
d.Revised = d.Created // put same time in both fields
|
||||||
|
|
||||||
_, err = ctx.Transaction.Exec("INSERT INTO document (refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
_, err = ctx.Transaction.Exec(`
|
||||||
document.RefID, document.OrgID, document.LabelID, document.UserID, document.Job, document.Location, document.Title, document.Excerpt, document.Slug, document.Tags, document.Template, document.Protection, document.Approval, document.Created, document.Revised)
|
INSERT INTO document (refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
|
d.RefID, d.OrgID, d.LabelID, d.UserID, d.Job, d.Location, d.Title, d.Excerpt, d.Slug, d.Tags,
|
||||||
|
d.Template, d.Protection, d.Approval, d.Lifecycle, d.Versioned, d.VersionID, d.VersionOrder, d.GroupID, d.Created, d.Revised)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "execuet insert document")
|
err = errors.Wrap(err, "execuet insert document")
|
||||||
|
@ -46,7 +49,11 @@ func (s Scope) Add(ctx domain.RequestContext, document doc.Document) (err error)
|
||||||
|
|
||||||
// Get fetches the document record with the given id fromt the document table and audits that it has been got.
|
// Get fetches the document record with the given id fromt the document table and audits that it has been got.
|
||||||
func (s Scope) Get(ctx domain.RequestContext, id string) (document doc.Document, err error) {
|
func (s Scope) Get(ctx domain.RequestContext, id string) (document doc.Document, err error) {
|
||||||
err = s.Runtime.Db.Get(&document, "SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? and refid=?",
|
err = s.Runtime.Db.Get(&document, `
|
||||||
|
SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
|
||||||
|
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
|
||||||
|
FROM document
|
||||||
|
WHERE orgid=? and refid=?`,
|
||||||
ctx.OrgID, id)
|
ctx.OrgID, id)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -106,7 +113,8 @@ func (s Scope) GetAll() (ctx domain.RequestContext, documents []doc.Document, er
|
||||||
// by category permissions -- caller must filter as required.
|
// by category permissions -- caller must filter as required.
|
||||||
func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
|
func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
|
||||||
err = s.Runtime.Db.Select(&documents, `
|
err = s.Runtime.Db.Select(&documents, `
|
||||||
SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised
|
SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
|
||||||
|
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
|
||||||
FROM document
|
FROM document
|
||||||
WHERE orgid=? AND template=0 AND labelid IN (
|
WHERE orgid=? AND template=0 AND labelid IN (
|
||||||
SELECT refid FROM label WHERE orgid=? AND refid IN
|
SELECT refid FROM label WHERE orgid=? AND refid IN
|
||||||
|
@ -119,8 +127,9 @@ func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents
|
||||||
)
|
)
|
||||||
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, spaceID, ctx.OrgID, ctx.UserID, ctx.OrgID, spaceID, ctx.UserID)
|
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, spaceID, ctx.OrgID, ctx.UserID, ctx.OrgID, spaceID, ctx.UserID)
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows || len(documents) == 0 {
|
||||||
err = nil
|
err = nil
|
||||||
|
documents = []doc.Document{}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "select documents by space")
|
err = errors.Wrap(err, "select documents by space")
|
||||||
|
@ -132,7 +141,10 @@ func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents
|
||||||
// Templates returns a slice containing the documents available as templates to the client's organisation, in title order.
|
// Templates returns a slice containing the documents available as templates to the client's organisation, in title order.
|
||||||
func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, err error) {
|
func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, err error) {
|
||||||
err = s.Runtime.Db.Select(&documents,
|
err = s.Runtime.Db.Select(&documents,
|
||||||
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? AND template=1
|
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
|
||||||
|
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
|
||||||
|
FROM document
|
||||||
|
WHERE orgid=? AND template=1 AND lifecycle=1
|
||||||
AND labelid IN
|
AND labelid IN
|
||||||
(
|
(
|
||||||
SELECT refid FROM label WHERE orgid=?
|
SELECT refid FROM label WHERE orgid=?
|
||||||
|
@ -144,6 +156,10 @@ func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, e
|
||||||
)
|
)
|
||||||
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.UserID, ctx.OrgID, ctx.UserID)
|
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.UserID, ctx.OrgID, ctx.UserID)
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows || len(documents) == 0 {
|
||||||
|
err = nil
|
||||||
|
documents = []doc.Document{}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "select document templates")
|
err = errors.Wrap(err, "select document templates")
|
||||||
}
|
}
|
||||||
|
@ -154,7 +170,10 @@ func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, e
|
||||||
// TemplatesBySpace returns a slice containing the documents available as templates for given space.
|
// TemplatesBySpace returns a slice containing the documents available as templates for given space.
|
||||||
func (s Scope) TemplatesBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
|
func (s Scope) TemplatesBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
|
||||||
err = s.Runtime.Db.Select(&documents,
|
err = s.Runtime.Db.Select(&documents,
|
||||||
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? AND labelid=? AND template=1
|
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
|
||||||
|
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
|
||||||
|
FROM document
|
||||||
|
WHERE orgid=? AND labelid=? AND template=1 ANd lifecycle=1
|
||||||
AND labelid IN
|
AND labelid IN
|
||||||
(
|
(
|
||||||
SELECT refid FROM label WHERE orgid=?
|
SELECT refid FROM label WHERE orgid=?
|
||||||
|
@ -170,7 +189,6 @@ func (s Scope) TemplatesBySpace(ctx domain.RequestContext, spaceID string) (docu
|
||||||
err = nil
|
err = nil
|
||||||
documents = []doc.Document{}
|
documents = []doc.Document{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "select space document templates")
|
err = errors.Wrap(err, "select space document templates")
|
||||||
}
|
}
|
||||||
|
@ -185,8 +203,13 @@ func (s Scope) PublicDocuments(ctx domain.RequestContext, orgID string) (documen
|
||||||
FROM document d LEFT JOIN label l ON l.refid=d.labelid
|
FROM document d LEFT JOIN label l ON l.refid=d.labelid
|
||||||
WHERE d.orgid=?
|
WHERE d.orgid=?
|
||||||
AND l.type=1
|
AND l.type=1
|
||||||
|
AND d.lifecycle=1
|
||||||
AND d.template=0`, orgID)
|
AND d.template=0`, orgID)
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
err = nil
|
||||||
|
documents = []doc.SitemapDocument{}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, fmt.Sprintf("execute GetPublicDocuments for org %s%s", orgID))
|
err = errors.Wrap(err, fmt.Sprintf("execute GetPublicDocuments for org %s%s", orgID))
|
||||||
}
|
}
|
||||||
|
@ -197,7 +220,10 @@ func (s Scope) PublicDocuments(ctx domain.RequestContext, orgID string) (documen
|
||||||
// DocumentList returns a slice containing the documents available as templates to the client's organisation, in title order.
|
// DocumentList returns a slice containing the documents available as templates to the client's organisation, in title order.
|
||||||
func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document, err error) {
|
func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document, err error) {
|
||||||
err = s.Runtime.Db.Select(&documents,
|
err = s.Runtime.Db.Select(&documents,
|
||||||
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? AND template=0
|
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
|
||||||
|
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
|
||||||
|
FROM document
|
||||||
|
WHERE orgid=? AND template=0 AND lifecycle=1
|
||||||
AND labelid IN
|
AND labelid IN
|
||||||
(
|
(
|
||||||
SELECT refid FROM label WHERE orgid=?
|
SELECT refid FROM label WHERE orgid=?
|
||||||
|
@ -213,7 +239,6 @@ func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document
|
||||||
err = nil
|
err = nil
|
||||||
documents = []doc.Document{}
|
documents = []doc.Document{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "select documents list")
|
err = errors.Wrap(err, "select documents list")
|
||||||
}
|
}
|
||||||
|
@ -225,7 +250,12 @@ func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document
|
||||||
func (s Scope) Update(ctx domain.RequestContext, document doc.Document) (err error) {
|
func (s Scope) Update(ctx domain.RequestContext, document doc.Document) (err error) {
|
||||||
document.Revised = time.Now().UTC()
|
document.Revised = time.Now().UTC()
|
||||||
|
|
||||||
_, err = ctx.Transaction.NamedExec("UPDATE document SET labelid=:labelid, userid=:userid, job=:job, location=:location, title=:title, excerpt=:excerpt, slug=:slug, tags=:tags, template=:template, protection=:protection, approval=:approval, revised=:revised WHERE orgid=:orgid AND refid=:refid",
|
_, err = ctx.Transaction.NamedExec(`
|
||||||
|
UPDATE document
|
||||||
|
SET
|
||||||
|
labelid=:labelid, userid=:userid, job=:job, location=:location, title=:title, excerpt=:excerpt, slug=:slug, tags=:tags, template=:template,
|
||||||
|
protection=:protection, approval=:approval, lifecycle=:lifecycle, versioned=:versioned, versionid=:versionid, versionorder=:versionorder, groupid=:groupid, revised=:revised
|
||||||
|
WHERE orgid=:orgid AND refid=:refid`,
|
||||||
&document)
|
&document)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -176,7 +176,12 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
h.Store.Audit.Record(ctx, audit.EventTypeSectionAdd)
|
h.Store.Audit.Record(ctx, audit.EventTypeSectionAdd)
|
||||||
|
|
||||||
np, _ := h.Store.Page.Get(ctx, pageID)
|
np, _ := h.Store.Page.Get(ctx, pageID)
|
||||||
|
|
||||||
|
if doc.Lifecycle == workflow.LifecycleLive {
|
||||||
go h.Indexer.IndexContent(ctx, np)
|
go h.Indexer.IndexContent(ctx, np)
|
||||||
|
} else {
|
||||||
|
go h.Indexer.DeleteDocument(ctx, doc.RefID)
|
||||||
|
}
|
||||||
|
|
||||||
response.WriteJSON(w, np)
|
response.WriteJSON(w, np)
|
||||||
}
|
}
|
||||||
|
@ -309,6 +314,7 @@ func (h *Handler) GetMeta(w http.ResponseWriter, r *http.Request) {
|
||||||
// Update will persist changed page and note the fact
|
// Update will persist changed page and note the fact
|
||||||
// that this is a new revision. If the page is the first in a document
|
// that this is a new revision. If the page is the first in a document
|
||||||
// then the corresponding document title will also be changed.
|
// then the corresponding document title will also be changed.
|
||||||
|
// Draft documents do not get revision entry.
|
||||||
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.update"
|
method := "page.update"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
@ -406,6 +412,11 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||||
skipRevision = true
|
skipRevision = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We only track revisions for live documents
|
||||||
|
if doc.Lifecycle != workflow.LifecycleLive {
|
||||||
|
skipRevision = true
|
||||||
|
}
|
||||||
|
|
||||||
err = h.Store.Page.Update(ctx, model.Page, refID, ctx.UserID, skipRevision)
|
err = h.Store.Page.Update(ctx, model.Page, refID, ctx.UserID, skipRevision)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Transaction.Rollback()
|
ctx.Transaction.Rollback()
|
||||||
|
@ -470,7 +481,11 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
ctx.Transaction.Commit()
|
ctx.Transaction.Commit()
|
||||||
|
|
||||||
|
if doc.Lifecycle == workflow.LifecycleLive {
|
||||||
go h.Indexer.IndexContent(ctx, model.Page)
|
go h.Indexer.IndexContent(ctx, model.Page)
|
||||||
|
} else {
|
||||||
|
go h.Indexer.DeleteDocument(ctx, doc.RefID)
|
||||||
|
}
|
||||||
|
|
||||||
updatedPage, err := h.Store.Page.Get(ctx, pageID)
|
updatedPage, err := h.Store.Page.Get(ctx, pageID)
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"github.com/documize/community/model/page"
|
"github.com/documize/community/model/page"
|
||||||
pm "github.com/documize/community/model/permission"
|
pm "github.com/documize/community/model/permission"
|
||||||
"github.com/documize/community/model/template"
|
"github.com/documize/community/model/template"
|
||||||
|
"github.com/documize/community/model/workflow"
|
||||||
uuid "github.com/nu7hatch/gouuid"
|
uuid "github.com/nu7hatch/gouuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -377,7 +378,12 @@ func (h *Handler) Use(w http.ResponseWriter, r *http.Request) {
|
||||||
event.Handler().Publish(string(event.TypeAddDocument), nd.Title)
|
event.Handler().Publish(string(event.TypeAddDocument), nd.Title)
|
||||||
|
|
||||||
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
|
||||||
|
|
||||||
|
if nd.Lifecycle == workflow.LifecycleLive {
|
||||||
go h.Indexer.IndexDocument(ctx, nd, a)
|
go h.Indexer.IndexDocument(ctx, nd, a)
|
||||||
|
} else {
|
||||||
|
go h.Indexer.DeleteDocument(ctx, d.RefID)
|
||||||
|
}
|
||||||
|
|
||||||
response.WriteJSON(w, nd)
|
response.WriteJSON(w, nd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func main() {
|
||||||
// product details
|
// product details
|
||||||
rt.Product = env.ProdInfo{}
|
rt.Product = env.ProdInfo{}
|
||||||
rt.Product.Major = "1"
|
rt.Product.Major = "1"
|
||||||
rt.Product.Minor = "58"
|
rt.Product.Minor = "59"
|
||||||
rt.Product.Patch = "0"
|
rt.Product.Patch = "0"
|
||||||
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
||||||
rt.Product.Edition = "Community"
|
rt.Product.Edition = "Community"
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -93,6 +93,8 @@ export default Component.extend(ModalMixin, {
|
||||||
documentCopy: false,
|
documentCopy: false,
|
||||||
documentTemplate: false,
|
documentTemplate: false,
|
||||||
documentApprove: false,
|
documentApprove: false,
|
||||||
|
documentLifecycle: false,
|
||||||
|
documentVersion: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let rec = this.get('store').normalize('space-permission', raw);
|
let rec = this.get('store').normalize('space-permission', raw);
|
||||||
|
@ -132,7 +134,8 @@ export default Component.extend(ModalMixin, {
|
||||||
let hasEveryone = _.find(permissions, (permission) => {
|
let hasEveryone = _.find(permissions, (permission) => {
|
||||||
return permission.get('whoId') === constants.EveryoneUserId &&
|
return permission.get('whoId') === constants.EveryoneUserId &&
|
||||||
(permission.get('spaceView') || permission.get('documentAdd') || permission.get('documentEdit') || permission.get('documentDelete') ||
|
(permission.get('spaceView') || permission.get('documentAdd') || permission.get('documentEdit') || permission.get('documentDelete') ||
|
||||||
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate') || permission.get('documentApprove'));
|
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate') ||
|
||||||
|
permission.get('documentApprove') || permission.get('documentLifecycle') || permission.get('documentVersion'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// see if more than oen user is granted access to space (excluding everyone)
|
// see if more than oen user is granted access to space (excluding everyone)
|
||||||
|
@ -140,7 +143,8 @@ export default Component.extend(ModalMixin, {
|
||||||
permissions.forEach((permission) => {
|
permissions.forEach((permission) => {
|
||||||
if (permission.get('whoId') !== constants.EveryoneUserId &&
|
if (permission.get('whoId') !== constants.EveryoneUserId &&
|
||||||
(permission.get('spaceView') || permission.get('documentAdd') || permission.get('documentEdit') || permission.get('documentDelete') ||
|
(permission.get('spaceView') || permission.get('documentAdd') || permission.get('documentEdit') || permission.get('documentDelete') ||
|
||||||
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate') || permission.get('documentApprove'))) {
|
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate') ||
|
||||||
|
permission.get('documentApprove') || permission.get('documentLifecycle') || permission.get('documentVersion'))) {
|
||||||
roleCount += 1;
|
roleCount += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -161,7 +165,7 @@ export default Component.extend(ModalMixin, {
|
||||||
},
|
},
|
||||||
|
|
||||||
onSearch() {
|
onSearch() {
|
||||||
debounce(this, function() {
|
debounce(this, function () {
|
||||||
let searchText = this.get('searchText').trim();
|
let searchText = this.get('searchText').trim();
|
||||||
|
|
||||||
if (searchText.length === 0) {
|
if (searchText.length === 0) {
|
||||||
|
@ -181,7 +185,6 @@ export default Component.extend(ModalMixin, {
|
||||||
if (is.undefined(exists)) {
|
if (is.undefined(exists)) {
|
||||||
spacePermissions.pushObject(this.permissionRecord(constants.WhoType.User, user.get('id'), user.get('fullname')));
|
spacePermissions.pushObject(this.permissionRecord(constants.WhoType.User, user.get('id'), user.get('fullname')));
|
||||||
this.set('spacePermissions', spacePermissions);
|
this.set('spacePermissions', spacePermissions);
|
||||||
// this.set('spacePermissions', spacePermissions.sortBy('who', 'name'));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ export default Model.extend({
|
||||||
documentCopy: attr('boolean'),
|
documentCopy: attr('boolean'),
|
||||||
documentTemplate: attr('boolean'),
|
documentTemplate: attr('boolean'),
|
||||||
documentApprove: attr('boolean'),
|
documentApprove: attr('boolean'),
|
||||||
|
documentLifecycle: attr('boolean'),
|
||||||
|
documentVersion: attr('boolean'),
|
||||||
name: attr('string'), // read-only
|
name: attr('string'), // read-only
|
||||||
members: attr('number') // read-only
|
members: attr('number') // read-only
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
<th class="text-info">Copy</th>
|
<th class="text-info">Copy</th>
|
||||||
<th class="text-info">Templates</th>
|
<th class="text-info">Templates</th>
|
||||||
<th class="text-info">Approval</th>
|
<th class="text-info">Approval</th>
|
||||||
|
<th class="text-info">Lifecycle</th>
|
||||||
|
<th class="text-info">Versions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -55,36 +57,18 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>{{input type="checkbox" id=(concat 'space-role-view-' permission.whoId) checked=permission.spaceView}}</td>
|
||||||
{{input type="checkbox" id=(concat 'space-role-view-' permission.whoId) checked=permission.spaceView}}
|
<td>{{input type="checkbox" id=(concat 'space-role-manage-' permission.whoId) checked=permission.spaceManage}}</td>
|
||||||
</td>
|
<td>{{input type="checkbox" id=(concat 'space-role-owner-' permission.whoId) checked=permission.spaceOwner}}</td>
|
||||||
<td>
|
<td>{{input type="checkbox" id=(concat 'doc-role-add-' permission.whoId) checked=permission.documentAdd}}</td>
|
||||||
{{input type="checkbox" id=(concat 'space-role-manage-' permission.whoId) checked=permission.spaceManage}}
|
<td>{{input type="checkbox" id=(concat 'doc-role-edit-' permission.whoId) checked=permission.documentEdit}}</td>
|
||||||
</td>
|
<td>{{input type="checkbox" id=(concat 'doc-role-delete-' permission.whoId) checked=permission.documentDelete}}</td>
|
||||||
<td>
|
<td>{{input type="checkbox" id=(concat 'doc-role-move-' permission.whoId) checked=permission.documentMove}}</td>
|
||||||
{{input type="checkbox" id=(concat 'space-role-owner-' permission.whoId) checked=permission.spaceOwner}}
|
<td>{{input type="checkbox" id=(concat 'doc-role-copy-' permission.whoId) checked=permission.documentCopy}}</td>
|
||||||
</td>
|
<td>{{input type="checkbox" id=(concat 'doc-role-template-' permission.whoId) checked=permission.documentTemplate}}</td>
|
||||||
<td>
|
<td>{{input type="checkbox" id=(concat 'doc-role-approve-' permission.whoId) checked=permission.documentApprove}}</td>
|
||||||
{{input type="checkbox" id=(concat 'doc-role-add-' permission.whoId) checked=permission.documentAdd}}
|
<td>{{input type="checkbox" id=(concat 'doc-role-lifecycle-' permission.whoId) checked=permission.documentLifecycle}}</td>
|
||||||
</td>
|
<td>{{input type="checkbox" id=(concat 'doc-role-version-' permission.whoId) checked=permission.documentVersion}}</td>
|
||||||
<td>
|
|
||||||
{{input type="checkbox" id=(concat 'doc-role-edit-' permission.whoId) checked=permission.documentEdit}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input type="checkbox" id=(concat 'doc-role-delete-' permission.whoId) checked=permission.documentDelete}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input type="checkbox" id=(concat 'doc-role-move-' permission.whoId) checked=permission.documentMove}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input type="checkbox" id=(concat 'doc-role-copy-' permission.whoId) checked=permission.documentCopy}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input type="checkbox" id=(concat 'doc-role-template-' permission.whoId) checked=permission.documentTemplate}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input type="checkbox" id=(concat 'doc-role-approve-' permission.whoId) checked=permission.documentApprove}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -113,7 +97,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="button" class="btn btn-success" onclick={{action 'setPermissions'}}>Save</button>
|
<button type="button" class="btn btn-success" onclick= {{action 'setPermissions'}}>Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "documize",
|
"name": "documize",
|
||||||
"version": "1.58.0",
|
"version": "1.59.0",
|
||||||
"description": "The Document IDE",
|
"description": "The Document IDE",
|
||||||
"private": true,
|
"private": true,
|
||||||
"repository": "",
|
"repository": "",
|
||||||
|
|
14
meta.json
14
meta.json
|
@ -1,16 +1,14 @@
|
||||||
{
|
{
|
||||||
"community":
|
"community": {
|
||||||
{
|
"version": "1.59.0",
|
||||||
"version": "1.58.0",
|
|
||||||
"major": 1,
|
"major": 1,
|
||||||
"minor": 58,
|
"minor": 59,
|
||||||
"patch": 0
|
"patch": 0
|
||||||
},
|
},
|
||||||
"enterprise":
|
"enterprise": {
|
||||||
{
|
"version": "1.61.0",
|
||||||
"version": "1.60.0",
|
|
||||||
"major": 1,
|
"major": 1,
|
||||||
"minor": 60,
|
"minor": 61,
|
||||||
"patch": 0
|
"patch": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,6 +34,11 @@ type Document struct {
|
||||||
Template bool `json:"template"`
|
Template bool `json:"template"`
|
||||||
Protection workflow.Protection `json:"protection"`
|
Protection workflow.Protection `json:"protection"`
|
||||||
Approval workflow.Approval `json:"approval"`
|
Approval workflow.Approval `json:"approval"`
|
||||||
|
Lifecycle workflow.Lifecycle `json:"lifecycle"`
|
||||||
|
Versioned bool `json:"versioned"`
|
||||||
|
VersionID string `json:"versionId"`
|
||||||
|
VersionOrder int `json:"versionOrder"`
|
||||||
|
GroupID string `json:"groupId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults ensures on blanks and cleans.
|
// SetDefaults ensures on blanks and cleans.
|
||||||
|
|
|
@ -93,6 +93,12 @@ const (
|
||||||
// DocumentApprove means you can approve a change to a document
|
// DocumentApprove means you can approve a change to a document
|
||||||
DocumentApprove Action = "doc-approve"
|
DocumentApprove Action = "doc-approve"
|
||||||
|
|
||||||
|
// DocumentLifecycle means you can move a document between DRAFT/LIVE/ARCHIVE states
|
||||||
|
DocumentLifecycle Action = "doc-lifecycle"
|
||||||
|
|
||||||
|
// DocumentVersion means you can manage document versions
|
||||||
|
DocumentVersion Action = "doc-version"
|
||||||
|
|
||||||
// CategoryView action means you can view a category and documents therein
|
// CategoryView action means you can view a category and documents therein
|
||||||
CategoryView Action = "view"
|
CategoryView Action = "view"
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,6 +29,8 @@ type Record struct {
|
||||||
DocumentCopy bool `json:"documentCopy"`
|
DocumentCopy bool `json:"documentCopy"`
|
||||||
DocumentTemplate bool `json:"documentTemplate"`
|
DocumentTemplate bool `json:"documentTemplate"`
|
||||||
DocumentApprove bool `json:"documentApprove"`
|
DocumentApprove bool `json:"documentApprove"`
|
||||||
|
DocumentLifecycle bool `json:"documentLifecycle"`
|
||||||
|
DocumentVersion bool `json:"documentVersion"`
|
||||||
Name string `json:"name"` // read-only, user or group name
|
Name string `json:"name"` // read-only, user or group name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +69,10 @@ func DecodeUserPermissions(perm []Permission) (r Record) {
|
||||||
r.DocumentTemplate = true
|
r.DocumentTemplate = true
|
||||||
case DocumentApprove:
|
case DocumentApprove:
|
||||||
r.DocumentApprove = true
|
r.DocumentApprove = true
|
||||||
|
case DocumentLifecycle:
|
||||||
|
r.DocumentLifecycle = true
|
||||||
|
case DocumentVersion:
|
||||||
|
r.DocumentVersion = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +113,12 @@ func EncodeUserPermissions(r Record) (perm []Permission) {
|
||||||
if r.DocumentApprove {
|
if r.DocumentApprove {
|
||||||
perm = append(perm, EncodeRecord(r, DocumentApprove))
|
perm = append(perm, EncodeRecord(r, DocumentApprove))
|
||||||
}
|
}
|
||||||
|
if r.DocumentVersion {
|
||||||
|
perm = append(perm, EncodeRecord(r, DocumentVersion))
|
||||||
|
}
|
||||||
|
if r.DocumentLifecycle {
|
||||||
|
perm = append(perm, EncodeRecord(r, DocumentLifecycle))
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -114,7 +126,8 @@ func EncodeUserPermissions(r Record) (perm []Permission) {
|
||||||
// HasAnyPermission returns true if user has at least one permission.
|
// HasAnyPermission returns true if user has at least one permission.
|
||||||
func HasAnyPermission(p Record) bool {
|
func HasAnyPermission(p Record) bool {
|
||||||
return p.SpaceView || p.SpaceManage || p.SpaceOwner || p.DocumentAdd || p.DocumentEdit ||
|
return p.SpaceView || p.SpaceManage || p.SpaceOwner || p.DocumentAdd || p.DocumentEdit ||
|
||||||
p.DocumentDelete || p.DocumentMove || p.DocumentCopy || p.DocumentTemplate || p.DocumentApprove
|
p.DocumentDelete || p.DocumentMove || p.DocumentCopy || p.DocumentTemplate || p.DocumentApprove ||
|
||||||
|
p.DocumentLifecycle || p.DocumentVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeRecord creates standard permission record representing user permissions for a space.
|
// EncodeRecord creates standard permission record representing user permissions for a space.
|
||||||
|
@ -138,7 +151,6 @@ type CategoryViewRequestModel struct {
|
||||||
CategoryID string `json:"categoryID"`
|
CategoryID string `json:"categoryID"`
|
||||||
WhoID string `json:"whoId"`
|
WhoID string `json:"whoId"`
|
||||||
Who WhoType `json:"who"`
|
Who WhoType `json:"who"`
|
||||||
// UserID string `json:"userId"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SpaceRequestModel details which users have what permissions on a given space.
|
// SpaceRequestModel details which users have what permissions on a given space.
|
||||||
|
|
|
@ -63,3 +63,17 @@ const (
|
||||||
// ChangePendingNew means a new section to a document is pending review
|
// ChangePendingNew means a new section to a document is pending review
|
||||||
ChangePendingNew ChangeStatus = 4
|
ChangePendingNew ChangeStatus = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Lifecycle tells us if document is in Draft, Live, Archived
|
||||||
|
type Lifecycle int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LifecycleDraft means document is in draft mode with restricted viewing
|
||||||
|
LifecycleDraft Lifecycle = 0
|
||||||
|
|
||||||
|
// LifecycleLive means document can be seen by all
|
||||||
|
LifecycleLive Lifecycle = 1
|
||||||
|
|
||||||
|
// LifecycleArchived means document has been archived
|
||||||
|
LifecycleArchived Lifecycle = 2
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue