From 16461fef7569d24ff76436b538bd593af56b9276 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 1 Aug 2017 18:09:01 +0200 Subject: [PATCH 1/9] two column layout --- views/bootstrap/class.Help.php | 39 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/views/bootstrap/class.Help.php b/views/bootstrap/class.Help.php index 05d529cd9..4df03d260 100644 --- a/views/bootstrap/class.Help.php +++ b/views/bootstrap/class.Help.php @@ -39,17 +39,46 @@ class SeedDMS_View_Help extends SeedDMS_Bootstrap_Style { $this->htmlStartPage(getMLText("help")); $this->globalNavigation(); $this->contentStart(); - $this->pageNavigation(getMLText("help").": ".getMLText('help_'.strtolower($context), array(), $context), ""); - - $this->contentContainerStart('help'); +// $this->pageNavigation(getMLText("help").": ".getMLText('help_'.strtolower($context), array(), $context), ""); +?> +
+
+ Table of contents +params['session']->getLanguage()."/help"); + echo ""; +?> +
+
+ +params['session']->getLanguage()."/help/".$context.".html"; if(file_exists($helpfile)) readfile($helpfile); - else + else { + $helpfile = "../languages/".$this->params['session']->getLanguage()."/help/".$context.".md"; + if(file_exists($helpfile)) { + require_once('parsedown/Parsedown.php'); + $Parsedown = new Parsedown(); + echo $Parsedown->text(file_get_contents($helpfile)); + } else readfile("../languages/".$this->params['session']->getLanguage()."/help.htm"); + } - $this->contentContainerEnd(); +?> +
+
+contentEnd(); $this->htmlEndPage(); } /* }}} */ From e0dcd86f5a97b9a8e9f030697218f37f8b141ac0 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 06:46:44 +0200 Subject: [PATCH 2/9] add optional version number to mayEditOnline() --- inc/inc.ClassAccessOperation.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/inc/inc.ClassAccessOperation.php b/inc/inc.ClassAccessOperation.php index f93a4f4f1..80840eb5c 100644 --- a/inc/inc.ClassAccessOperation.php +++ b/inc/inc.ClassAccessOperation.php @@ -54,9 +54,12 @@ class SeedDMS_AccessOperation { * document may delete versions. The admin may even delete a version * even if is disallowed in the settings. */ - function mayEditVersion() { /* {{{ */ + function mayEditVersion($vno=0) { /* {{{ */ if(get_class($this->obj) == 'SeedDMS_Core_Document') { - $version = $this->obj->getLatestContent(); + if($vno) + $version = $this->obj->getContentByVersion($vno); + else + $version = $this->obj->getLatestContent(); if (!isset($this->settings->_editOnlineFileTypes) || !is_array($this->settings->_editOnlineFileTypes) || !in_array(strtolower($version->getFileType()), $this->settings->_editOnlineFileTypes)) return false; if ($this->obj->getAccessMode($this->user) == M_ALL || $this->user->isAdmin()) { From 76508cb52b0b5b80cb568c11dee70b36ddf2c827 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 06:47:48 +0200 Subject: [PATCH 3/9] check with SeedDMS_AccessOperation for allowed operation --- out/out.EditAttributes.php | 3 +++ out/out.EditComment.php | 3 +++ out/out.EditOnline.php | 4 ++++ out/out.OverrideContentStatus.php | 10 +++------- out/out.RemoveVersion.php | 3 +++ out/out.SetReviewersApprovers.php | 10 +++------- out/out.SetWorkflow.php | 3 +++ 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/out/out.EditAttributes.php b/out/out.EditAttributes.php index 717768728..b7e72e6c7 100644 --- a/out/out.EditAttributes.php +++ b/out/out.EditAttributes.php @@ -46,6 +46,9 @@ $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); +if(!$accessop->mayEditAttributes()) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("access_denied")); +} $attrdefs = $dms->getAllAttributeDefinitions(array(SeedDMS_Core_AttributeDefinition::objtype_documentcontent, SeedDMS_Core_AttributeDefinition::objtype_all)); diff --git a/out/out.EditComment.php b/out/out.EditComment.php index c39a223b2..d91f130ce 100644 --- a/out/out.EditComment.php +++ b/out/out.EditComment.php @@ -51,6 +51,9 @@ $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); +if(!$accessop->mayEditComment()) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("access_denied")); +} $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.EditOnline.php b/out/out.EditOnline.php index f2433e71d..84f73f155 100644 --- a/out/out.EditOnline.php +++ b/out/out.EditOnline.php @@ -53,6 +53,7 @@ if(isset($_GET["version"])) { $lc = $document->getLatestContent(); } else { + $version = 0; $content = $document->getLatestContent(); $lc = $document->getLatestContent(); } @@ -74,6 +75,9 @@ if (!isset($settings->_editOnlineFileTypes) || !is_array($settings->_editOnlineF /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($dms, $user, $settings); +if(!$accessop->mayEditVersion($version)) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("access_denied")); +} $folder = $document->getFolder(); diff --git a/out/out.OverrideContentStatus.php b/out/out.OverrideContentStatus.php index 6798f6e98..ad4863016 100644 --- a/out/out.OverrideContentStatus.php +++ b/out/out.OverrideContentStatus.php @@ -50,17 +50,13 @@ if (!is_object($content)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -$overallStatus = $content->getStatus(); - -// status change control -if ($overallStatus["status"] == S_REJECTED || $overallStatus["status"] == S_EXPIRED || $overallStatus["status"] == S_DRAFT_REV || $overallStatus["status"] == S_DRAFT_APP ) { - UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("cannot_change_final_states")); -} - $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); +if(!$accessop->mayOverwriteStatus()) { + UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("cannot_change_final_states")); +} $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.RemoveVersion.php b/out/out.RemoveVersion.php index c8958f642..eaa99db3e 100644 --- a/out/out.RemoveVersion.php +++ b/out/out.RemoveVersion.php @@ -60,6 +60,9 @@ $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); +if(!$accessop->mayRemoveVersion()) { + UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("access_denied")); +} $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.SetReviewersApprovers.php b/out/out.SetReviewersApprovers.php index 02c5e09f5..ef3cac583 100644 --- a/out/out.SetReviewersApprovers.php +++ b/out/out.SetReviewersApprovers.php @@ -53,17 +53,13 @@ if(!$settings->_enableVersionModification) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("no_version_modification")); } -// control for document state. Must correspond to check in -// SeedDMS_AccessOperation::maySetReviewersApprovers() -$overallStatus = $content->getStatus(); -if ($overallStatus["status"]!=S_DRAFT_REV && $overallStatus["status"]!=S_DRAFT_APP) { - UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("cannot_assign_invalid_state")); -} - $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); +if(!$accessop->maySetReviewersApprovers()) { + UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("cannot_assign_invalid_state")); +} $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); diff --git a/out/out.SetWorkflow.php b/out/out.SetWorkflow.php index d2473afd0..caee4499d 100644 --- a/out/out.SetWorkflow.php +++ b/out/out.SetWorkflow.php @@ -51,6 +51,9 @@ $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); +if(!$accessop->maySetWorkflow()) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("access_denied")); +} $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); From b974ee0df270c02aff8e09cd023c2e94250dc3b0 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 06:49:01 +0200 Subject: [PATCH 4/9] add entry for 4.3.36 --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 01824e3e0..a322092d9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,6 +8,8 @@ - remove empty lines at end of view/bootstrap/class.*.php files (Closes #329) - make sure contentDir ends with DIRECTORY_SEPARATOR (Closes #323) - minor improvements of installation +- better checking in out/*.php for allowed operation (e.g. EditOnline, + RemoveVersion, SetReviewersApprovers, ...) -------------------------------------------------------------------------------- Changes in version 4.3.35 From 0c3355ed9dc587d7d1492a60bc84763784acc203 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 07:04:46 +0200 Subject: [PATCH 5/9] no extra check enableVersionModificaton is done by maySetReviewersApprovers() --- out/out.SetReviewersApprovers.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/out/out.SetReviewersApprovers.php b/out/out.SetReviewersApprovers.php index ef3cac583..a05d428ca 100644 --- a/out/out.SetReviewersApprovers.php +++ b/out/out.SetReviewersApprovers.php @@ -49,16 +49,12 @@ if (!is_object($content)) { UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("invalid_version")); } -if(!$settings->_enableVersionModification) { - UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("no_version_modification")); -} - $folder = $document->getFolder(); /* Create object for checking access to certain operations */ $accessop = new SeedDMS_AccessOperation($document, $user, $settings); if(!$accessop->maySetReviewersApprovers()) { - UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("cannot_assign_invalid_state")); + UI::exitError(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName()))),getMLText("no_version_modification")); } $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); From ea8a695551820a2ecdfe635ab888d5c42c366bbf Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 10:53:50 +0200 Subject: [PATCH 6/9] maySetReviewersApprovers() checks if review/approval has been done already --- inc/inc.ClassAccessOperation.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/inc/inc.ClassAccessOperation.php b/inc/inc.ClassAccessOperation.php index 80840eb5c..522f1692b 100644 --- a/inc/inc.ClassAccessOperation.php +++ b/inc/inc.ClassAccessOperation.php @@ -114,15 +114,28 @@ class SeedDMS_AccessOperation { * * This check can only be done for documents. Overwriting the document * reviewers/approvers is only allowed if version modification is turned on - * in the settings and the document is in 'draft review' status. The - * admin may even set reviewers/approvers if is disallowed in the + * in the settings and the document has not been reviewed/approved by any + * user/group already. + * The admin may even set reviewers/approvers if is disallowed in the * settings. */ function maySetReviewersApprovers() { /* {{{ */ if(get_class($this->obj) == 'SeedDMS_Core_Document') { $latestContent = $this->obj->getLatestContent(); $status = $latestContent->getStatus(); - if ((($this->settings->_enableVersionModification && ($this->obj->getAccessMode($this->user) == M_ALL)) || $this->user->isAdmin()) && ($status["status"]==S_DRAFT_REV || $status["status"]==S_DRAFT_APP && $this->settings->_workflowMode == 'traditional_only_approval')) { + $reviewstatus = $latestContent->getReviewStatus(); + $hasreview = false; + foreach($reviewstatus as $r) { + if($r['status'] == 1 || $r['status'] == -1) + $hasreview = true; + } + $approvalstatus = $latestContent->getApprovalStatus(); + $hasapproval = false; + foreach($approvalstatus as $r) { + if($r['status'] == 1 || $r['status'] == -1) + $hasapproval = true; + } + if ((($this->settings->_enableVersionModification && ($this->obj->getAccessMode($this->user) == M_ALL)) || $this->user->isAdmin()) && (($status["status"]==S_DRAFT_REV && !$hasreview) || ($status["status"]==S_DRAFT_APP && !$hasreview && !$hasapproval))) { return true; } } From c54faf8f901258edda36dddda23e803bc4b12faa Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 10:54:40 +0200 Subject: [PATCH 7/9] regard mandatory reviewers/approvers the owner of the document may not remove mandatory reviewers/approvers anymore. Only admin may do that, it he/she is not the owner. --- op/op.SetReviewersApprovers.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/op/op.SetReviewersApprovers.php b/op/op.SetReviewersApprovers.php index 4d995a24a..7b0589c59 100644 --- a/op/op.SetReviewersApprovers.php +++ b/op/op.SetReviewersApprovers.php @@ -60,6 +60,7 @@ if ($overallStatus["status"]==S_REJECTED || $overallStatus["status"]==S_OBSOLETE } $folder = $document->getFolder(); +$owner = $document->getOwner(); // Retrieve a list of all users and groups that have review / approve // privileges. @@ -104,6 +105,18 @@ foreach ($approvalStatus as $i=>$rs) { // Get the list of proposed reviewers, stripping out any duplicates. $pIndRev = (isset($_POST["indReviewers"]) ? array_values(array_unique($_POST["indReviewers"])) : array()); $pGrpRev = (isset($_POST["grpReviewers"]) ? array_values(array_unique($_POST["grpReviewers"])) : array()); +if($user->getID() != $owner->getID()) { + $res=$owner->getMandatoryReviewers(); + if($user->isAdmin()) + $res = array(); +} else + $res=$user->getMandatoryReviewers(); +foreach ($res as $r) { + if(!in_array($r['reviewerUserID'], $pIndRev)) + $pIndRev[] = $r['reviewerUserID']; + if(!in_array($r['reviewerGroupID'], $pGrpRev)) + $pGrpRev[] = $r['reviewerGroupID']; +} foreach ($pIndRev as $p) { if (is_numeric($p)) { if (isset($accessIndex["i"][$p])) { @@ -319,6 +332,18 @@ if (count($reviewIndex["g"]) > 0) { // Get the list of proposed approvers, stripping out any duplicates. $pIndApp = (isset($_POST["indApprovers"]) ? array_values(array_unique($_POST["indApprovers"])) : array()); $pGrpApp = (isset($_POST["grpApprovers"]) ? array_values(array_unique($_POST["grpApprovers"])) : array()); +if($user->getID() != $owner->getID()) { + $res=$owner->getMandatoryApprovers(); + if($user->isAdmin()) + $res = array(); +} else + $res=$user->getMandatoryApprovers(); +foreach ($res as $r) { + if(!in_array($r['approverUserID'], $pIndApp)) + $pIndApp[] = $r['approverUserID']; + if(!in_array($r['approverGroupID'], $pGrpApp)) + $pGrpApp[] = $r['approverGroupID']; +} foreach ($pIndApp as $p) { if (is_numeric($p)) { if (isset($accessIndex["i"][$p])) { From 48e1bfa670ed3e0e2353902947b4248846afbad5 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 10:56:28 +0200 Subject: [PATCH 8/9] regard mandatory reviewers/approvers --- .../bootstrap/class.SetReviewersApprovers.php | 103 +++++++++++++++--- 1 file changed, 89 insertions(+), 14 deletions(-) diff --git a/views/bootstrap/class.SetReviewersApprovers.php b/views/bootstrap/class.SetReviewersApprovers.php index b58f73fd4..ffd4f2780 100644 --- a/views/bootstrap/class.SetReviewersApprovers.php +++ b/views/bootstrap/class.SetReviewersApprovers.php @@ -43,6 +43,7 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { $enableselfrevapp = $this->params['enableselfrevapp']; $overallStatus = $content->getStatus(); + $owner = $document->getOwner(); $this->htmlStartPage(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName())))); $this->globalNavigation($folder); @@ -92,7 +93,12 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { "; +// print ""; } elseif (isset($reviewIndex["i"][$usr->getID()])) { @@ -121,8 +127,24 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { } } ?> - - + + 0) { + $u = $dms->getUser($r['reviewerUserID']); + $tmp[] = htmlspecialchars($u->getFullName().' ('.$u->getLogin().')'); + } + } + if($tmp) { + echo '
'.getMLText('mandatory_reviewers').': '; + echo implode(', ', $tmp); + echo "
\n"; + } + } +?>
:
"; +// print ""; } elseif (isset($reviewIndex["g"][$group->getID()])) { @@ -154,8 +176,25 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { } } ?> - - + + 0) { + $u = $dms->getGroup($r['reviewerGroupID']); + $tmp[] = htmlspecialchars($u->getName()); + } + } + if($tmp) { + echo '
'.getMLText('mandatory_reviewergroups').': '; + echo implode(', ', $tmp); + echo "
\n"; + } + } + } +?> contentSubHeading(getMLText("update_approvers"));?> @@ -163,8 +202,12 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { "; +// print ""; } elseif (isset($approvalIndex["i"][$usr->getID()])) { @@ -195,7 +238,23 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { } } ?> - + + 0) { + $u = $dms->getUser($r['approverUserID']); + $tmp[] = htmlspecialchars($u->getFullName().' ('.$u->getLogin().')'); + } + } + if($tmp) { + echo '
'.getMLText('mandatory_approvers').': '; + echo implode(', ', $tmp); + echo "
\n"; + } + } +?>
:
"; +// print ""; } elseif (isset($approvalIndex["g"][$group->getID()])) { @@ -229,8 +288,24 @@ class SeedDMS_View_SetReviewersApprovers extends SeedDMS_Bootstrap_Style { } } ?> - - + + 0) { + $u = $dms->getGroup($r['approverGroupID']); + $tmp[] = htmlspecialchars($u->getName()); + } + } + if($tmp) { + echo '
'.getMLText('mandatory_approvergroups').': '; + echo implode(', ', $tmp); + echo "
\n"; + } + } +?>

From 0dbf05334d6e7c50cff068707a5a45727e80df19 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Aug 2017 10:56:46 +0200 Subject: [PATCH 9/9] add entry for 4.3.36 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a322092d9..965009234 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,9 @@ - minor improvements of installation - better checking in out/*.php for allowed operation (e.g. EditOnline, RemoveVersion, SetReviewersApprovers, ...) +- SetReviewersApprovers checks for mandatory reviewers/approvers +- reviewers/approvers can only be modified by users with unrestricted access + and as long as no reviewer/approver has reviewed/approved the document -------------------------------------------------------------------------------- Changes in version 4.3.35