From 957482bc9b23949923f7ac4a3dbb8b8b54892603 Mon Sep 17 00:00:00 2001 From: Sebastian Bartus-Kunz Date: Fri, 10 Jun 2016 15:06:41 +0200 Subject: [PATCH 001/308] Added change password request. --- restapi/index.php | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/restapi/index.php b/restapi/index.php index a2b17da90..f98ebe8ef 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -929,6 +929,53 @@ function createAccount() { /* {{{ */ return; } /* }}} */ +/** + * Updates the password of an existing Account, the password must be PUT as a md5 string + * + * @param $id The user name or numerical identifier + */ +function changeAccountPassword($id) { /* {{{ */ + global $app, $dms, $userobj; + + checkIfAdmin(); + + if ($app->request()->put('password') == null) + { + $app->response()->header('Content-Type', 'application/json'); + echo json_encode(array('success'=>false, 'message'=>'You must PUT a new password', 'data'=>'')); + return; + } + + $newPassword = $app->request()->put('password'); + + if(is_numeric($id)) + $account = $dms->getUser($id); + else { + $account = $dms->getUserByLogin($id); + } + + /** + * User not found + */ + if (!$account) { + $app->response()->status(404); + return; + } + + $operation = $account->setPwd($newPassword); + + if (!$operation){ + $app->response()->header('Content-Type', 'application/json'); + echo json_encode(array('success'=>false, 'message'=>'', 'data'=>'Could not change password.')); + return; + } + + $app->response()->header('Content-Type', 'application/json'); + echo json_encode(array('success'=>true, 'message'=>'', 'data'=>'')); + + return; +} /* }}} */ + function getAccountById($id) { /* {{{ */ global $app, $dms, $userobj; checkIfAdmin(); @@ -1351,6 +1398,7 @@ $app->get('/account/locked', 'getLockedDocuments'); $app->post('/accounts', 'createAccount'); $app->get('/accounts/:id', 'getAccountById'); $app->put('/accounts/:id/disable', 'setDisabledAccount'); +$app->get('/accounts/:id/password', 'changeAccountPassword'); $app->post('/groups', 'createGroup'); $app->get('/groups/:id', 'getGroup'); $app->put('/groups/:id/addUser', 'addUserToGroup'); From f3490fc6ced1af8d2c96b76c806d47c77553e4f1 Mon Sep 17 00:00:00 2001 From: Sebastian Bartus-Kunz Date: Fri, 10 Jun 2016 15:08:33 +0200 Subject: [PATCH 002/308] Small fix. --- restapi/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/restapi/index.php b/restapi/index.php index f98ebe8ef..99b9460b2 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -1398,7 +1398,7 @@ $app->get('/account/locked', 'getLockedDocuments'); $app->post('/accounts', 'createAccount'); $app->get('/accounts/:id', 'getAccountById'); $app->put('/accounts/:id/disable', 'setDisabledAccount'); -$app->get('/accounts/:id/password', 'changeAccountPassword'); +$app->put('/accounts/:id/password', 'changeAccountPassword'); $app->post('/groups', 'createGroup'); $app->get('/groups/:id', 'getGroup'); $app->put('/groups/:id/addUser', 'addUserToGroup'); From 2c1374bea52a17bf376de09d9176ae0948aff0c8 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Sep 2017 06:20:48 +0200 Subject: [PATCH 003/308] take out echo --- SeedDMS_Core/Core/inc.ClassDocument.php | 1 - 1 file changed, 1 deletion(-) diff --git a/SeedDMS_Core/Core/inc.ClassDocument.php b/SeedDMS_Core/Core/inc.ClassDocument.php index deeae9e6a..b94f43ca9 100644 --- a/SeedDMS_Core/Core/inc.ClassDocument.php +++ b/SeedDMS_Core/Core/inc.ClassDocument.php @@ -3799,7 +3799,6 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ $this->_workflow->setDMS($this->_document->_dms); if($transition) { - echo "Trigger transition"; if(false === $this->triggerWorkflowTransition($user, $transition, $comment)) { $db->rollbackTransaction(); return false; From d5f79f5f7c6bebd46be81406ed24c7b7d7521531 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Sep 2017 18:36:59 +0200 Subject: [PATCH 004/308] various small improvements back ported from 6.0.x --- SeedDMS_Core/Core/inc.ClassDocument.php | 99 +++++++++++++++---------- 1 file changed, 59 insertions(+), 40 deletions(-) diff --git a/SeedDMS_Core/Core/inc.ClassDocument.php b/SeedDMS_Core/Core/inc.ClassDocument.php index ceec06ed5..a2c9f73da 100644 --- a/SeedDMS_Core/Core/inc.ClassDocument.php +++ b/SeedDMS_Core/Core/inc.ClassDocument.php @@ -58,6 +58,41 @@ define("S_OBSOLETE", -2); */ define("S_EXPIRED", -3); +/** + * The different states a workflow log can be in. This is used in + * all tables tblDocumentXXXLog + */ +/* + * workflow is in a neutral status waiting for action of user + */ +define("S_LOG_WAITING", 0); + +/* + * workflow has been successful ended. The document content has been + * approved, reviewed, aknowledged or revised + */ +define("S_LOG_ACCEPTED", 1); + +/* + * workflow has been unsuccessful ended. The document content has been + * rejected + */ +define("S_LOG_REJECTED", -1); + +/* + * user has been removed from workflow. This can be for different reasons + * 1. the user has been actively removed from the workflow, 2. the user has + * been deleted. + */ +define("S_LOG_USER_REMOVED", -2); + +/* + * workflow is sleeping until reactivation. The workflow has been set up + * but not started. This is only valid for the revision workflow, which + * may run over and over again. + */ +define("S_LOG_SLEEPING", -3); + /** * Class to represent a document in the document management system * @@ -150,6 +185,16 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ */ protected $_sequence; + /** + * @var object temp. storage for latestcontent + */ + protected $_latestContent; + + /** + * @var array temp. storage for content + */ + protected $_content; + function __construct($id, $name, $comment, $date, $expires, $ownerID, $folderID, $inheritAccess, $defaultAccess, $locked, $keywords, $sequence) { /* {{{ */ parent::__construct($id); $this->_name = $name; @@ -165,6 +210,8 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ $this->_sequence = $sequence; $this->_categories = array(); $this->_notifyList = array(); + $this->_latestContent = null; + $this->_content = null; } /* }}} */ /** @@ -712,7 +759,7 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ * * @param integer $mode access mode (defaults to M_ANY) * @param integer $op operation (defaults to O_EQ) - * @return array multi dimensional array + * @return array multi dimensional array or false in case of an error */ function getAccessList($mode = M_ANY, $op = O_EQ) { /* {{{ */ $db = $this->_dms->getDB(); @@ -1265,8 +1312,8 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ return false; } - unset($this->_content); - unset($this->_latestContent); + $this->_content = null; + $this->_latestContent = null; $content = $this->getLatestContent($contentID); $docResultSet = new SeedDMS_Core_AddContentResultSet($content); $docResultSet->setDMS($this->_dms); @@ -1438,8 +1485,8 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ return false; } - unset($this->_content); - unset($this->_latestContent); + $this->_content = null; + $this->_latestContent = null; $db->commitTransaction(); return true; @@ -1501,7 +1548,7 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ } /* }}} */ function getLatestContent() { /* {{{ */ - if (!isset($this->_latestContent)) { + if (!$this->_latestContent) { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC LIMIT 1"; $resArr = $db->getResultArray($queryStr); @@ -2991,7 +3038,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ return true; } /* }}} */ - function addIndReviewer($user, $requestUser, $listadmin=false) { /* {{{ */ + function addIndReviewer($user, $requestUser) { /* {{{ */ $db = $this->_document->_dms->getDB(); $userID = $user->getID(); @@ -3000,21 +3047,6 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ if($this->_document->getAccessMode($user) < M_READ) { return -2; } - /* - if (!isset($this->_readAccessList)) { - $this->_readAccessList = $this->_document->getReadAccessList($listadmin); - } - $approved = false; - foreach ($this->_readAccessList["users"] as $appUser) { - if ($userID == $appUser->getID()) { - $approved = true; - break; - } - } - if (!$approved) { - return -2; - } - */ // Check to see if the user has already been added to the review list. $reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version); @@ -3226,7 +3258,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ } } /* }}} */ - function addIndApprover($user, $requestUser, $listadmin=false) { /* {{{ */ + function addIndApprover($user, $requestUser) { /* {{{ */ $db = $this->_document->_dms->getDB(); $userID = $user->getID(); @@ -3235,19 +3267,6 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ if($this->_document->getAccessMode($user) < M_READ) { return -2; } - /* - $readAccessList = $this->_document->getReadAccessList($listadmin); - $approved = false; - foreach ($readAccessList["users"] as $appUser) { - if ($userID == $appUser->getID()) { - $approved = true; - break; - } - } - if (!$approved) { - return -2; - } - */ // Check to see if the user has already been added to the approvers list. $approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version); @@ -3473,7 +3492,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ } $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $indstatus["reviewID"] ."', '-2', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; + "VALUES ('". $indstatus["reviewID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; @@ -3504,7 +3523,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ } $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $reviewStatus[0]["reviewID"] ."', '-2', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; + "VALUES ('". $reviewStatus[0]["reviewID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; @@ -3536,7 +3555,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ } $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $indstatus["approveID"] ."', '-2', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; + "VALUES ('". $indstatus["approveID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; @@ -3567,7 +3586,7 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ } $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $approvalStatus[0]["approveID"] ."', '-2', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; + "VALUES ('". $approvalStatus[0]["approveID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; From 3912cbb5770bc8dc3e54de444e6772cb9926e2f6 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Sep 2017 18:37:37 +0200 Subject: [PATCH 005/308] list all rejected documents --- views/bootstrap/class.MyDocuments.php | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/views/bootstrap/class.MyDocuments.php b/views/bootstrap/class.MyDocuments.php index 6f9e672e1..4f8e3511f 100644 --- a/views/bootstrap/class.MyDocuments.php +++ b/views/bootstrap/class.MyDocuments.php @@ -407,6 +407,84 @@ class SeedDMS_View_MyDocuments extends SeedDMS_Bootstrap_Style { else printMLText("no_docs_to_look_at"); $this->contentContainerEnd(); + + // Get list of documents owned by current user that are pending review or + // pending approval. + $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser`, ". + "`tblDocumentContent`.`version`, `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ". + "`tblDocumentStatusLog`.`comment` AS `statusComment`, `tblDocumentStatusLog`.`date` as `statusDate`, ". + "`tblDocumentStatusLog`.`userID`, `oTbl`.`fullName` AS `ownerName`, `sTbl`.`fullName` AS `statusName` ". + "FROM `tblDocumentContent` ". + "LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentContent`.`document` ". + "LEFT JOIN `tblDocumentStatus` ON `tblDocumentStatus`.`documentID` = `tblDocumentContent`.`document` ". + "LEFT JOIN `tblDocumentStatusLog` ON `tblDocumentStatusLog`.`statusID` = `tblDocumentStatus`.`statusID` ". + "LEFT JOIN `ttstatid` ON `ttstatid`.`maxLogID` = `tblDocumentStatusLog`.`statusLogID` ". + "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentStatus`.`version` AND `ttcontentid`.`document` = `tblDocumentStatus`.`documentID` ". + "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". + "LEFT JOIN `tblUsers` AS `oTbl` on `oTbl`.`id` = `tblDocuments`.`owner` ". + "LEFT JOIN `tblUsers` AS `sTbl` on `sTbl`.`id` = `tblDocumentStatusLog`.`userID` ". + "WHERE `ttstatid`.`maxLogID`=`tblDocumentStatusLog`.`statusLogID` ". + "AND `ttcontentid`.`maxVersion` = `tblDocumentContent`.`version` ". + "AND `tblDocuments`.`owner` = '".$user->getID()."' ". + "AND `tblDocumentStatusLog`.`status` IN (".S_REJECTED.") ". + "ORDER BY `statusDate` DESC"; + + $resArr = $db->getResultArray($queryStr); + if (is_bool($resArr) && !$resArr) { + $this->contentHeading(getMLText("warning")); + $this->contentContainer("Internal error. Unable to complete request. Exiting."); + $this->htmlEndPage(); + exit; + } + + $this->contentHeading(getMLText("documents_user_rejected")); + $this->contentContainerStart(); + if (count($resArr)>0) { + + print ""; + print "\n\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n\n\n"; + + foreach ($resArr as $res) { + $document = $dms->getDocument($res["documentID"]); + $document->verifyLastestContentExpriry(); + + // verify expiry + if ( $res["expires"] && time()>$res["expires"]+24*60*60 ){ + if ( $res["status"]==S_REJECTED ){ + $res["status"]=S_EXPIRED; + } + } + + print "\n"; + $latestContent = $document->getLatestContent(); + $previewer->createPreview($latestContent); + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + print "
".getMLText("name")."".getMLText("status")."".getMLText("version")."".getMLText("last_update")."".getMLText("expires")."
"; + if($previewer->hasPreview($latestContent)) { + print "getID()."&version=".$latestContent->getVersion()."&width=".$previewwidth."\" title=\"".htmlspecialchars($latestContent->getMimeType())."\">"; + } else { + print "getMimeIcon($latestContent->getFileType())."\" title=\"".htmlspecialchars($latestContent->getMimeType())."\">"; + } + print "" . htmlspecialchars($res["name"]) . "".getOverallStatusText($res["status"])."".$res["version"]."".$res["statusDate"]." ".htmlspecialchars($res["statusName"])."".(!$res["expires"] ? "-":getReadableDate($res["expires"]))."
"; + + } + else printMLText("no_docs_to_look_at"); + + $this->contentContainerEnd(); } elseif($workflowmode == 'advanced') { // Get document list for the current user. $workflowStatus = $user->getWorkflowStatus(); From 031887de0a9977cb065c32483d02e9618ee601de Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 28 Sep 2017 07:21:08 +0200 Subject: [PATCH 006/308] add var noReadForStatus and method getLoggedInUser() --- SeedDMS_Core/Core/inc.ClassDMS.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/SeedDMS_Core/Core/inc.ClassDMS.php b/SeedDMS_Core/Core/inc.ClassDMS.php index b982728b0..03b713229 100644 --- a/SeedDMS_Core/Core/inc.ClassDMS.php +++ b/SeedDMS_Core/Core/inc.ClassDMS.php @@ -147,6 +147,13 @@ class SeedDMS_Core_DMS { */ public $viewOnlineFileTypes; + /** + * @var array $noReadForStatus list of status without read right + * online. + * @access public + */ + public $noReadForStatus; + /** * @var string $version version of pear package * @access public @@ -354,6 +361,7 @@ class SeedDMS_Core_DMS { $this->forceRename = false; $this->enableConverting = false; $this->convertFileTypes = array(); + $this->noReadForStatus = array(); $this->classnames = array(); $this->classnames['folder'] = 'SeedDMS_Core_Folder'; $this->classnames['document'] = 'SeedDMS_Core_Document'; @@ -542,6 +550,19 @@ class SeedDMS_Core_DMS { $this->user = $user; } /* }}} */ + /** + * Get the logged in user + * + * If user authentication was done externally, this function can + * be used to tell the dms who is currently logged in. + * + * @return object $user + * + */ + function getLoggedInUser() { /* {{{ */ + return $this->user; + } /* }}} */ + /** * Return a document by its id * From f1f439af8c23590f9178e8bf105949b6ef6e3df2 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 28 Sep 2017 07:23:15 +0200 Subject: [PATCH 007/308] add support for access restrictions on document content --- SeedDMS_Core/Core/inc.ClassDocument.php | 208 ++++++++++++++++++++---- 1 file changed, 178 insertions(+), 30 deletions(-) diff --git a/SeedDMS_Core/Core/inc.ClassDocument.php b/SeedDMS_Core/Core/inc.ClassDocument.php index a2c9f73da..d9c397f8c 100644 --- a/SeedDMS_Core/Core/inc.ClassDocument.php +++ b/SeedDMS_Core/Core/inc.ClassDocument.php @@ -1495,7 +1495,10 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ /** * Return all content elements of a document * - * This functions returns an array of content elements ordered by version + * This functions returns an array of content elements ordered by version. + * Version which are not accessible because of its status, will be filtered + * out. Access rights based on the document status are calculated for the + * currently logged in user. * * @return array list of objects of class SeedDMS_Core_DocumentContent */ @@ -1510,8 +1513,16 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ $this->_content = array(); $classname = $this->_dms->getClassname('documentcontent'); - foreach ($resArr as $row) - array_push($this->_content, new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum'])); + $user = $this->_dms->getLoggedInUser(); + foreach ($resArr as $row) { + $content = new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']); + if($user) { + if($content->getAccessMode($user) >= M_READ) + array_push($this->_content, $content); + } else { + array_push($this->_content, $content); + } + } } return $this->_content; @@ -1520,8 +1531,13 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ /** * Return the content element of a document with a given version number * + * This function will check if the version is accessible and return false + * if not. Access rights based on the document status are calculated for the + * currently logged in user. + * * @param integer $version version number of content element - * @return object object of class SeedDMS_Core_DocumentContent + * @return object/boolean object of class {@link SeedDMS_Core_DocumentContent} + * or false */ function getContentByVersion($version) { /* {{{ */ if (!is_numeric($version)) return false; @@ -1544,10 +1560,19 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ $resArr = $resArr[0]; $classname = $this->_dms->getClassname('documentcontent'); - return new $classname($resArr["id"], $this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"], $resArr['fileSize'], $resArr['checksum']); + if($content = new $classname($resArr["id"], $this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"], $resArr['fileSize'], $resArr['checksum'])) { + $user = $this->_dms->getLoggedInUser(); + /* A user with write access on the document may always see the version */ + if($user && $content->getAccessMode($user) == M_NONE) + return false; + else + return $content; + } else { + return false; + } } /* }}} */ - function getLatestContent() { /* {{{ */ + function __getLatestContent() { /* {{{ */ if (!$this->_latestContent) { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC LIMIT 1"; @@ -1564,6 +1589,49 @@ class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */ return $this->_latestContent; } /* }}} */ + /** + * Get the latest version of document + * + * This function returns the latest accessible version of a document. + * If content access has been restricted by setting + * {@link SeedDMS_Core_DMS::noReadForStatus} the function will go + * backwards in history until an accessible version is found. If none + * is found null will be returned. + * Access rights based on the document status are calculated for the + * currently logged in user. + * + * @return object object of class {@link SeedDMS_Core_DocumentContent} + */ + function getLatestContent() { /* {{{ */ + if (!$this->_latestContent) { + $db = $this->_dms->getDB(); + $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC"; + $resArr = $db->getResultArray($queryStr); + if (is_bool($resArr) && !$res) + return false; + + $classname = $this->_dms->getClassname('documentcontent'); + $user = $this->_dms->getLoggedInUser(); + foreach ($resArr as $row) { + if (!$this->_latestContent) { + $content = new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']); + if($user) { + /* If the user may even write the document, then also allow to see all content. + * This is needed because the user could upload a new version + */ + if($content->getAccessMode($user) >= M_READ) { + $this->_latestContent = $content; + } + } else { + $this->_latestContent = $content; + } + } + } + } + + return $this->_latestContent; + } /* }}} */ + /** * Remove version of document * @@ -2750,36 +2818,117 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ /** * Returns the access mode similar to a document - * There is no real access mode for document content, so this is more - * like a virtual access mode, derived from the status or workflow - * of the document content. The idea is to return an access mode - * M_NONE if the user is still in a workflow or under review/approval. - * In such a case only those user involved in the workflow/review/approval - * process should be allowed to see the document. This method could - * be called by any function that returns the content e.g. getLatestContent() - * It may as well be used by SeedDMS_Core_Document::getAccessMode() to - * prevent access on the whole document if there is just one version. - * The return value is planed to be either M_NONE or M_READ. * - * @param object $user - * @return integer mode + * There is no real access mode for document content, so this is more + * like a virtual access mode, derived from the status of the document + * content. The function checks if {@link SeedDMS_Core_DMS::noReadForStatus} + * contains the status of the version and returns M_NONE if it exists and + * the user is not involved in a workflow or review/approval/revision. + * This method is called by all functions that returns the content e.g. + * {@link SeedDMS_Core_Document::getLatestContent()} + * It is also used by {@link SeedDMS_Core_Document::getAccessMode()} to + * prevent access on the whole document if there is no accessible version. + * + * FIXME: This function only works propperly if $u is the currently logged in + * user, because noReadForStatus will be set for this user. + * FIXED: instead of using $dms->noReadForStatus it is take from the user's role + * + * @param object $u user + * @return integer either M_NONE or M_READ */ function getAccessMode($u) { /* {{{ */ - if(!$this->_workflow) - $this->getWorkflow(); + $dms = $this->_document->_dms; - if($this->_workflow) { - if (!$this->_workflowState) - $this->getWorkflowState(); - $transitions = $this->_workflow->getNextTransitions($this->_workflowState); - foreach($transitions as $transition) { - if($this->triggerWorkflowTransitionIsAllowed($u, $transition)) - return M_READ; - } + if(!$u) return M_NONE; + + /* If read access isn't further restricted by status, than grant read access */ + if(!$dms->noReadForStatus) + return M_READ; + $noReadForStatus = $dms->noReadForStatus; + + if(!$noReadForStatus) + return M_READ; + + /* If the current status is not in list of status without read access, then grant read access */ + if(!in_array($this->getStatus()['status'], $noReadForStatus)) + return M_READ; + + /* Administrators have unrestricted access */ + if ($u->isAdmin()) return M_READ; + + /* The owner of the document has unrestricted access */ + $owner = $this->_document->getOwner(); + if ($u->getID() == $owner->getID()) return M_READ; + + /* Read/Write access on the document will also grant access on the version */ + if($this->_document->getAccessMode($u) >= M_READWRITE) return M_READ; + + /* At this point the current status is in the list of status without read access. + * The only way to still gain read access is, if the user is involved in the + * process, e.g. is a reviewer, approver or an active person in the workflow. + */ + $s = $this->getStatus(); + switch($s['status']) { + case S_DRAFT_REV: + $status = $this->getReviewStatus(); + foreach ($status as $r) { + if($r['status'] != -2) // Check if reviewer was removed + switch ($r["type"]) { + case 0: // Reviewer is an individual. + if($u->getId() == $r["required"]) + return M_READ; + break; + case 1: // Reviewer is a group. + $required = $dms->getGroup($r["required"]); + if (is_object($required) && $required->isMember($u)) + return M_READ; + break; + } + } + break; + case S_DRAFT_APP: + $status = $this->getApprovalStatus(); + foreach ($status as $r) { + if($r['status'] != -2) // Check if approver was removed + switch ($r["type"]) { + case 0: // Reviewer is an individual. + if($u->getId() == $r["required"]) + return M_READ; + break; + case 1: // Reviewer is a group. + $required = $dms->getGroup($r["required"]); + if (is_object($required) && $required->isMember($u)) + return M_READ; + break; + } + } + break; + case S_RELEASED: + break; + case S_IN_WORKFLOW: + if(!$this->_workflow) + $this->getWorkflow(); + + if($this->_workflow) { + if (!$this->_workflowState) + $this->getWorkflowState(); + $transitions = $this->_workflow->getNextTransitions($this->_workflowState); + foreach($transitions as $transition) { + if($this->triggerWorkflowTransitionIsAllowed($u, $transition)) + return M_READ; + } + } + break; + case S_REJECTED: + break; + case S_OBSOLETE: + break; + case S_EXPIRED: + break; } - return M_READ; + return M_NONE; } /* }}} */ /** @@ -3932,7 +4081,6 @@ class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */ $this->_workflow->setDMS($this->_document->_dms); if($transition) { - echo "Trigger transition"; if(false === $this->triggerWorkflowTransition($user, $transition, $comment)) { $db->rollbackTransaction(); return false; From f3d4b86bae1f10e1c2a92e8e6e63913080828870 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 28 Sep 2017 07:27:43 +0200 Subject: [PATCH 008/308] remove unused revisionDate in SeedDMS_Core_DocumentFile --- SeedDMS_Core/Core/inc.ClassDocument.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SeedDMS_Core/Core/inc.ClassDocument.php b/SeedDMS_Core/Core/inc.ClassDocument.php index f4124f587..c70074274 100644 --- a/SeedDMS_Core/Core/inc.ClassDocument.php +++ b/SeedDMS_Core/Core/inc.ClassDocument.php @@ -6008,11 +6008,6 @@ class SeedDMS_Core_DocumentFile { /* {{{ */ */ protected $_mimeType; - /** - * @var string date when revision starts - */ - protected $_revisionDate; - /** * @var string name of the file that was originally uploaded */ From dde468ca9e6d1a9d030125ff83fdde0353d27a38 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 28 Sep 2017 20:48:29 +0200 Subject: [PATCH 009/308] make strict check for selected options in a select menu without strict checking an option with value=0 will be treated as if no option was selected. --- views/bootstrap/class.Settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 1fac139f5..7eba8eff8 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -777,7 +777,7 @@ if(!is_writeable($settings->_configFilePath)) { echo ""; @@ -70,9 +75,8 @@ class SeedDMS_View_BackupTools extends SeedDMS_Bootstrap_Style { // archive creation //////////////////////////////////////////////////////////// $this->contentHeading(getMLText("archive_creation")); - $this->contentContainerStart(); print "

".getMLText("archive_creation_warning")."

\n"; - + $this->contentContainerStart(); print "
"; $this->printFolderChooserHtml("form2",M_READWRITE); print ""; @@ -81,10 +85,10 @@ class SeedDMS_View_BackupTools extends SeedDMS_Bootstrap_Style { // list backup files - $handle = opendir($contentdir); + $handle = opendir($backupdir); $entries = array(); while ($e = readdir($handle)){ - if (is_dir($contentdir.$e)) continue; + if (is_dir($backupdir.$e)) continue; if (strpos($e,".tar.gz")==FALSE) continue; $entries[] = $e; } @@ -113,8 +117,8 @@ class SeedDMS_View_BackupTools extends SeedDMS_Bootstrap_Style { print "".$entry."\n"; if (is_object($folder)) print "".htmlspecialchars($folder->getName())."\n"; else print "".getMLText("unknown_id")."\n"; - print "".getLongReadableDate(filectime($contentdir.$entry))."\n"; - print "".SeedDMS_Core_File::format_filesize(filesize($contentdir.$entry))."\n"; + print "".getLongReadableDate(filectime($backupdir.$entry))."\n"; + print "".SeedDMS_Core_File::format_filesize(filesize($backupdir.$entry))."\n"; print ""; print " ".getMLText("backup_remove").""; print "\n"; @@ -128,18 +132,18 @@ class SeedDMS_View_BackupTools extends SeedDMS_Bootstrap_Style { // dump creation /////////////////////////////////////////////////////////////// $this->contentHeading(getMLText("dump_creation")); - $this->contentContainerStart(); print "

".getMLText("dump_creation_warning")."

\n"; + $this->contentContainerStart(); print ""; print ""; print "
\n"; // list backup files - $handle = opendir($contentdir); + $handle = opendir($backupdir); $entries = array(); while ($e = readdir($handle)){ - if (is_dir($contentdir.$e)) continue; + if (is_dir($backupdir.$e)) continue; if (strpos($e,".sql.gz")==FALSE) continue; $entries[] = $e; } @@ -160,9 +164,11 @@ class SeedDMS_View_BackupTools extends SeedDMS_Bootstrap_Style { foreach ($entries as $entry){ print "\n"; - print "".$entry."\n"; - print "".getLongReadableDate(filectime($contentdir.$entry))."\n"; - print "".SeedDMS_Core_File::format_filesize(filesize($contentdir.$entry))."\n"; + print ""; + print "".$entry.""; + print "\n"; + print "".getLongReadableDate(filectime($backupdir.$entry))."\n"; + print "".SeedDMS_Core_File::format_filesize(filesize($backupdir.$entry))."\n"; print ""; print " ".getMLText("dump_remove").""; print "\n"; diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 7eba8eff8..befb7fc08 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -398,6 +398,10 @@ if(!is_writeable($settings->_configFilePath)) { : showTextField("contentDir", $settings->_contentDir); ?> + "> + : + showTextField("backupDir", $settings->_backupDir); ?> + "> : showTextField("cacheDir", $settings->_cacheDir); ?> From 1d8743fd7fa39967cda60bbe4db6d50153ce5fff Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 21 Nov 2017 17:12:58 +0100 Subject: [PATCH 076/308] handle 'from' propperly, even if it contains a time --- op/op.EditEvent.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/op/op.EditEvent.php b/op/op.EditEvent.php index b287e40ae..55dc8cf84 100644 --- a/op/op.EditEvent.php +++ b/op/op.EditEvent.php @@ -61,7 +61,8 @@ else $comment = $_POST["comment"]; if(isset($_POST["from"])) { - $tmp = explode('-', $_POST["from"]); + $from = explode('T', $_POST["from"]); + $tmp = explode('-', $from[0]); $from = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]); } else { UI::exitError(getMLText("edit_event"),getMLText("error_occured")); From 37a3661698cd639d5023ed3f6ad50c436942dd16 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 21 Nov 2017 17:26:11 +0100 Subject: [PATCH 077/308] fix some indenting of lines --- views/bootstrap/class.Settings.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index e9888e614..8d7eec31a 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -792,14 +792,14 @@ if(!is_writeable($settings->_configFilePath)) { ?> : - showTextField("converters[fulltext][".$mimetype."]", htmlspecialchars($cmd)); ?> + showTextField("converters[fulltext][".$mimetype."]", htmlspecialchars($cmd)); ?> - showTextField("converters[fulltext][newmimetype]", "", '', getMLText('converter_new_mimetype')); ?>: - showTextField("converters[fulltext][newcmd]", "", "", getMLText('converter_new_cmd')); ?> + showTextField("converters[fulltext][newmimetype]", "", '', getMLText('converter_new_mimetype')); ?>: + showTextField("converters[fulltext][newcmd]", "", "", getMLText('converter_new_cmd')); ?> _configFilePath)) { ?> : - showTextField("converters[preview][".$mimetype."]", htmlspecialchars($cmd)); ?> + showTextField("converters[preview][".$mimetype."]", htmlspecialchars($cmd)); ?> _configFilePath)) { contentContainerEnd(); ?> -
+
contentContainerStart(); ?>