1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-19 13:19:43 +02:00

document approvals and protection

This commit is contained in:
Harvey Kandola 2017-12-24 15:51:43 +00:00
parent 58c88e2127
commit f4f32bcfcb
20 changed files with 891 additions and 777 deletions

View file

@ -171,7 +171,7 @@ func setupAccount(rt *env.Runtime, completion onboardRequest, serial string) (er
}
// assign permissions to space
perms := []string{"view", "manage", "own", "doc-add", "doc-edit", "doc-delete", "doc-move", "doc-copy", "doc-template"}
perms := []string{"view", "manage", "own", "doc-add", "doc-edit", "doc-delete", "doc-move", "doc-copy", "doc-template", "doc-approve"}
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)
_, err = runSQL(rt, sql)

View file

@ -1,8 +1,7 @@
## TODO
## PENDING REMOVALS
1. Remove audit table
2. Remove document.layout field ?
NONE
## MYSQL ENCODING

View file

@ -0,0 +1,14 @@
/* enterprise edition */
-- document needs proection and approval columns
ALTER TABLE document ADD COLUMN `protection` INT NOT NULL DEFAULT 0 AFTER `template`;
ALTER TABLE document ADD COLUMN `approval` INT NOT NULL DEFAULT 0 AFTER `protection`;
-- page needs proection and approval columns
ALTER TABLE page ADD COLUMN `protection` INT NOT NULL DEFAULT 0 AFTER `revisions`;
ALTER TABLE page ADD COLUMN `approval` INT NOT NULL DEFAULT 0 AFTER `protection`;
-- data migration clean up from previous releases
DROP TABLE IF EXISTS `audit`;
DROP TABLE IF EXISTS `search_old`;
ALTER TABLE document DROP COLUMN `layout`;

View file

@ -34,8 +34,8 @@ func (s Scope) Add(ctx domain.RequestContext, document doc.Document) (err error)
document.Created = time.Now().UTC()
document.Revised = document.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, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
document.RefID, document.OrgID, document.LabelID, document.UserID, document.Job, document.Location, document.Title, document.Excerpt, document.Slug, document.Tags, document.Template, document.Created, document.Revised)
_, err = ctx.Transaction.Exec("INSERT INTO document (refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
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)
if err != nil {
err = errors.Wrap(err, "execuet insert document")
@ -46,7 +46,7 @@ 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.
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, layout, 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, created, revised FROM document WHERE orgid=? and refid=?",
ctx.OrgID, id)
if err != nil {
@ -92,7 +92,7 @@ func (s Scope) DocumentMeta(ctx domain.RequestContext, id string) (meta doc.Docu
// GetAll returns a slice containg all of the the documents for the client's organisation, with the most recient first.
func (s Scope) GetAll() (ctx domain.RequestContext, documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents, "SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, layout, created, revised FROM document WHERE orgid=? AND template=0 ORDER BY revised DESC", ctx.OrgID)
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 ORDER BY revised DESC", ctx.OrgID)
if err != nil {
err = errors.Wrap(err, "select documents")
@ -106,7 +106,7 @@ func (s Scope) GetAll() (ctx domain.RequestContext, documents []doc.Document, er
// by category permissions -- caller must filter as required.
func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents, `
SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, layout, created, revised
SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised
FROM document
WHERE orgid=? AND template=0 AND labelid IN (
SELECT refid FROM label WHERE orgid=? AND refid IN
@ -128,7 +128,7 @@ 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.
func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents,
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, layout, created, revised FROM document WHERE orgid=? AND template=1
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? AND template=1
AND labelid IN
(
SELECT refid FROM label WHERE orgid=?
@ -150,7 +150,7 @@ func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, e
// 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) {
err = s.Runtime.Db.Select(&documents,
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, layout, 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, created, revised FROM document WHERE orgid=? AND labelid=? AND template=1
AND labelid IN
(
SELECT refid FROM label WHERE orgid=?
@ -193,7 +193,7 @@ 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.
func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents,
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, layout, created, revised FROM document WHERE orgid=? AND template=0
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? AND template=0
AND labelid IN
(
SELECT refid FROM label WHERE orgid=?
@ -221,7 +221,7 @@ func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document
func (s Scope) Update(ctx domain.RequestContext, document doc.Document) (err error) {
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, layout=:layout, 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, revised=:revised WHERE orgid=:orgid AND refid=:refid",
&document)
if err != nil {

View file

@ -54,8 +54,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, protected, approval, 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.Protection, model.Page.Approval, 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 +69,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.protection, a.approval, a.created, a.revised FROM page a WHERE a.orgid=? AND a.refid=?",
ctx.OrgID, pageID)
if err != nil {
@ -81,7 +81,7 @@ func (s Scope) Get(ctx domain.RequestContext, pageID string) (p page.Page, err e
// GetPages returns a slice containing all the 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.protection, a.approval, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? ORDER BY a.sequence", ctx.OrgID, documentID)
if err != nil {
err = errors.Wrap(err, "execute get pages")
@ -93,7 +93,7 @@ func (s Scope) GetPages(ctx domain.RequestContext, documentID string) (p []page.
// 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, protection, approval, created, revised FROM page WHERE orgid=? AND documentid=? 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 +119,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, protection=:protection, approval=:approval, revised=:revised WHERE orgid=:orgid AND refid=:refid",
&page)
if err != nil {

File diff suppressed because one or more lines are too long

View file

@ -139,7 +139,7 @@ export default Component.extend({
});
} else {
if (data.authProvider === this.get('appMeta.authProvider')) {
// this.showNotification(response.message);
this.showNotification(response.message);
} else {
this.get('onChange')(data);
}

View file

@ -10,12 +10,10 @@
// https://documize.com
import { setProperties } from '@ember/object';
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import NotifierMixin from '../../mixins/notifier';
export default Component.extend(NotifierMixin, {
export default Component.extend({
folderService: service('folder'),
userService: service('user'),
appMeta: service(),
@ -42,7 +40,8 @@ export default Component.extend(NotifierMixin, {
documentDelete: false,
documentMove: false,
documentCopy: false,
documentTemplate: false
documentTemplate: false,
documentApprove: false,
};
let data = this.get('store').normalize('space-permission', u)
@ -63,8 +62,9 @@ export default Component.extend(NotifierMixin, {
documentDelete: false,
documentMove: false,
documentCopy: false,
documentTemplate: false
};
documentTemplate: false,
documentApprove: false,
};
let data = this.get('store').normalize('space-permission', u)
folderPermissions.pushObject(this.get('store').push(data));
@ -96,7 +96,7 @@ export default Component.extend(NotifierMixin, {
let hasEveryone = _.find(permissions, function (permission) {
return permission.get('userId') === "0" &&
(permission.get('spaceView') || permission.get('documentAdd') || permission.get('documentEdit') || permission.get('documentDelete') ||
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate'));
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate') || permission.get('documentApprove'));
});
// see if more than oen user is granted access to space (excluding everyone)
@ -104,26 +104,22 @@ export default Component.extend(NotifierMixin, {
permissions.forEach((permission) => {
if (permission.get('userId') !== "0" &&
(permission.get('spaceView') || permission.get('documentAdd') || permission.get('documentEdit') || permission.get('documentDelete') ||
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate'))) {
permission.get('documentMove') || permission.get('documentCopy') || permission.get('documentTemplate') || permission.get('documentApprove'))) {
roleCount += 1;
}
});
if (is.not.undefined(hasEveryone)) {
folder.markAsPublic();
this.showNotification('Marked space as public');
} else {
if (roleCount > 1) {
folder.markAsRestricted();
this.showNotification('Marked space as protected');
} else {
folder.markAsPrivate();
this.showNotification('Marked space as private');
}
}
this.get('folderService').savePermissions(folder.get('id'), payload).then(() => {
this.showNotification('Saved permissions');
$('#space-permission-modal').modal('hide');
$('#space-permission-modal').modal('dispose');
});

View file

@ -10,7 +10,6 @@
// https://documize.com
import { run } from '@ember/runloop';
import Component from '@ember/component';
import miscUtil from '../utils/misc';

View file

@ -25,7 +25,8 @@ export default Model.extend({
userId: attr('string'),
tags: attr('string'),
template: attr('boolean'),
layout: attr('string'),
protection: attr('number', { defaultValue: 0 }),
approval: attr('number', { defaultValue: 0 }),
// client-side property
selected: attr('boolean', { defaultValue: false }),

View file

@ -28,6 +28,8 @@ export default Model.extend({
body: attr('string'),
rawBody: attr('string'),
meta: attr(),
protection: attr('number', { defaultValue: 0 }),
approval: attr('number', { defaultValue: 0 }),
tagName: computed('level', function () {
return "h2";

View file

@ -27,5 +27,6 @@ export default Model.extend({
documentDelete: attr('boolean'),
documentMove: attr('boolean'),
documentCopy: attr('boolean'),
documentTemplate: attr('boolean')
documentTemplate: attr('boolean'),
documentApprove: attr('boolean')
});

View file

@ -10,7 +10,6 @@
// https://documize.com
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import NotifierMixin from '../../../mixins/notifier';
@ -24,8 +23,6 @@ export default Controller.extend(NotifierMixin, {
actions: {
onAddSpace(payload) {
let self = this;
this.showNotification("Added");
this.get('folderService').add(payload).then(function (newFolder) {
self.get('folderService').setCurrentFolder(newFolder);
self.transitionToRoute('folder', newFolder.get('id'), newFolder.get('slug'));
@ -34,7 +31,6 @@ export default Controller.extend(NotifierMixin, {
onDeleteSpace(id) {
this.get('folderService').delete(id).then(() => { /* jshint ignore:line */
this.showNotification("Deleted");
this.get('localStorage').clearSessionItem('folder');
this.transitionToRoute('folders');
});

View file

@ -10,7 +10,7 @@
<tr>
<th></th>
<th colspan="3">Spaces</th>
<th colspan="6" class="text-info">Documents</th>
<th colspan="7" class="text-info">Documents</th>
</tr>
<tr>
<th></th>
@ -23,6 +23,7 @@
<th class="text-info">Move</th>
<th class="text-info">Copy</th>
<th class="text-info">Templates</th>
<th class="text-info">Approval</th>
</tr>
</thead>
<tbody>
@ -56,6 +57,9 @@
<td>
{{input type="checkbox" id=(concat 'doc-role-template-' permission.userId) checked=permission.documentTemplate}}
</td>
<td>
{{input type="checkbox" id=(concat 'doc-role-approve-' permission.userId) checked=permission.documentApprove}}
</td>
</tr>
{{/each}}
</tbody>

View file

@ -39,5 +39,18 @@ export default {
PublishedTemplate: 8,
PublishedBlock: 9,
Feedback: 10
},
ProtectionType: {
None: 0,
Lock: 1,
Review: 2
},
ApprovalType: {
None: 0,
Anybody: 1,
Majority: 2,
Unanimous: 3
}
};

View file

@ -10,9 +10,7 @@
// https://documize.com
import { htmlSafe } from '@ember/string';
import EmberObject, { computed } from '@ember/object';
import Ember from 'ember';
import stringUtil from '../utils/string';
import constants from '../utils/constants';
@ -98,6 +96,8 @@ let DocumentModel = BaseModel.extend({
userId: "",
tags: "",
template: "",
protection: constants.ProtectionType.None,
approval: constants.ApprovalType.None,
slug: computed('name', function () {
return stringUtil.makeSlug(this.get('name'));
@ -164,6 +164,8 @@ let PageModel = BaseModel.extend({
title: "",
body: "",
rawBody: "",
protection: constants.ProtectionType.None,
approval: constants.ApprovalType.None,
meta: {},
tagName: computed('level', function () {
@ -202,7 +204,6 @@ let SectionModel = BaseModel.extend({
});
export default {
TemplateModel,
AttachmentModel,
DocumentModel,
FolderModel,
@ -210,6 +211,7 @@ export default {
PageModel,
PageMetaModel,
ProtectedFolderParticipant,
UserModel,
SectionModel
SectionModel,
TemplateModel,
UserModel
};

View file

@ -16,22 +16,24 @@ import (
"time"
"github.com/documize/community/model"
"github.com/documize/community/model/workflow"
)
// Document represents the purpose of Documize.
type Document struct {
model.BaseEntity
OrgID string `json:"orgId"`
LabelID string `json:"folderId"`
UserID string `json:"userId"`
Job string `json:"job"`
Location string `json:"location"`
Title string `json:"name"`
Excerpt string `json:"excerpt"`
Slug string `json:"-"`
Tags string `json:"tags"`
Template bool `json:"template"`
Layout string `json:"layout"`
OrgID string `json:"orgId"`
LabelID string `json:"folderId"`
UserID string `json:"userId"`
Job string `json:"job"`
Location string `json:"location"`
Title string `json:"name"`
Excerpt string `json:"excerpt"`
Slug string `json:"-"`
Tags string `json:"tags"`
Template bool `json:"template"`
Protection workflow.Protection `json:"protection"`
Approval workflow.Approval `json:"approval"`
}
// SetDefaults ensures on blanks and cleans.

View file

@ -16,23 +16,26 @@ import (
"time"
"github.com/documize/community/model"
"github.com/documize/community/model/workflow"
)
// Page represents a section within a document.
type Page struct {
model.BaseEntity
OrgID string `json:"orgId"`
DocumentID string `json:"documentId"`
UserID string `json:"userId"`
ContentType string `json:"contentType"`
PageType string `json:"pageType"`
BlockID string `json:"blockId"`
Level uint64 `json:"level"`
Sequence float64 `json:"sequence"`
Numbering string `json:"numbering"`
Title string `json:"title"`
Body string `json:"body"`
Revisions uint64 `json:"revisions"`
OrgID string `json:"orgId"`
DocumentID string `json:"documentId"`
UserID string `json:"userId"`
ContentType string `json:"contentType"`
PageType string `json:"pageType"`
BlockID string `json:"blockId"`
Level uint64 `json:"level"`
Sequence float64 `json:"sequence"`
Numbering string `json:"numbering"`
Title string `json:"title"`
Body string `json:"body"`
Revisions uint64 `json:"revisions"`
Protection workflow.Protection `json:"protection"`
Approval workflow.Approval `json:"approval"`
}
// SetDefaults ensures no blank values.

View file

@ -32,24 +32,34 @@ type Action string
const (
// SpaceView action means you can view a space and documents therein
SpaceView Action = "view"
// SpaceManage action means you can add, remove users, set permissions, but not delete that space
SpaceManage Action = "manage"
// SpaceOwner action means you can delete a space and do all SpaceManage functions
SpaceOwner Action = "own"
// DocumentAdd action means you can create/upload documents to a space
DocumentAdd Action = "doc-add"
// DocumentEdit action means you can edit documents in a space
DocumentEdit Action = "doc-edit"
// DocumentDelete means you can delete documents in a space
DocumentDelete Action = "doc-delete"
// DocumentMove means you can move documents between spaces
DocumentMove Action = "doc-move"
// DocumentCopy means you can copy documents within and between spaces
DocumentCopy Action = "doc-copy"
// DocumentTemplate means you can create, edit and delete document templates and content blocks
DocumentTemplate Action = "doc-template"
// DocumentApprove means you can approve a change to a document
DocumentApprove Action = "doc-approve"
// CategoryView action means you can view a category and documents therein
CategoryView Action = "view"
)
@ -70,6 +80,7 @@ type Record struct {
DocumentMove bool `json:"documentMove"`
DocumentCopy bool `json:"documentCopy"`
DocumentTemplate bool `json:"documentTemplate"`
DocumentApprove bool `json:"documentApprove"`
}
// DecodeUserPermissions returns a flat, usable permission summary record
@ -104,6 +115,8 @@ func DecodeUserPermissions(perm []Permission) (r Record) {
r.DocumentCopy = true
case DocumentTemplate:
r.DocumentTemplate = true
case DocumentApprove:
r.DocumentApprove = true
}
}
@ -158,6 +171,9 @@ func EncodeUserPermissions(r Record) (perm []Permission) {
if r.DocumentTemplate {
perm = append(perm, EncodeRecord(r, DocumentTemplate))
}
if r.DocumentApprove {
perm = append(perm, EncodeRecord(r, DocumentApprove))
}
return
}
@ -165,7 +181,7 @@ func EncodeUserPermissions(r Record) (perm []Permission) {
// HasAnyPermission returns true if user has at least one permission.
func HasAnyPermission(p Record) bool {
return p.SpaceView || p.SpaceManage || p.SpaceOwner || p.DocumentAdd || p.DocumentEdit ||
p.DocumentDelete || p.DocumentMove || p.DocumentCopy || p.DocumentTemplate
p.DocumentDelete || p.DocumentMove || p.DocumentCopy || p.DocumentTemplate || p.DocumentApprove
}
// EncodeRecord creates standard permission record representing user permissions for a space.

View file

@ -0,0 +1,43 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
package workflow
// Protection tell us how to handle data item changes
type Protection int
const (
// NoProtection means no protection so data item changes are permitted
NoProtection Protection = 0
// Lock means no data itme changes
Lock Protection = 1
// Review means changes must be reviewed and approved
Review Protection = 2
)
// Approval tells us how some data item change is to be approved
type Approval int
const (
// NoApproval means no approval necessary
NoApproval Approval = 0
// Anybody can approve data item change
Anybody Approval = 1
// Majority must approve data item change
Majority Approval = 2
// Unanimous approval must be given for data item change
Unanimous Approval = 3
)