Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
Massive refactorings to never ever load all users, all roles, or all …
Browse files Browse the repository at this point in the history
…repositories at once. Necessary for scalability.
  • Loading branch information
cdujeu committed May 26, 2014
1 parent 0f910d3 commit 87e1ddd
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 93 deletions.
46 changes: 11 additions & 35 deletions core/src/core/classes/class.AJXP_XMLWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -515,50 +515,29 @@ public static function sendMessage($logMessage, $errorMessage, $print = true)
}
return AJXP_XMLWriter::write("<message type=\"$messageType\">".$message."</message>", $print);
}
/**
* Writes the user data as XML
* @static
* @param null $userObject
* @param bool $details
* @return void
*/
public static function sendUserData($userObject = null, $details=false)
{
print(AJXP_XMLWriter::getUserXML($userObject, $details));
}

/**
* Extract all the user data and put it in XML
* @static
* @param null $userObject
* @param bool $details
* @param null $userObject * @internal param bool $details
* @return string
*/
public static function getUserXML($userObject = null, $details=false)
public static function getUserXML($userObject = null)
{
$buffer = "";
$loggedUser = AuthService::getLoggedUser();
$confDriver = ConfService::getConfStorageImpl();
if($userObject != null) $loggedUser = $userObject;
if (!AuthService::usersEnabled()) {
$buffer.="<user id=\"shared\">";
if (!$details) {
$buffer.="<active_repo id=\"".ConfService::getCurrentRepositoryId()."\" write=\"1\" read=\"1\"/>";
}
$buffer.= AJXP_XMLWriter::writeRepositoriesData(null, $details);
$buffer.="<active_repo id=\"".ConfService::getCurrentRepositoryId()."\" write=\"1\" read=\"1\"/>";
$buffer.= AJXP_XMLWriter::writeRepositoriesData(null);
$buffer.="</user>";
} else if ($loggedUser != null) {
$lock = $loggedUser->getLock();
$buffer.="<user id=\"".$loggedUser->id."\">";
if (!$details) {
$buffer.="<active_repo id=\"".ConfService::getCurrentRepositoryId()."\" write=\"".($loggedUser->canWrite(ConfService::getCurrentRepositoryId())?"1":"0")."\" read=\"".($loggedUser->canRead(ConfService::getCurrentRepositoryId())?"1":"0")."\"/>";
} else {
$buffer .= "<ajxp_roles>";
foreach ($loggedUser->getRoles() as $roleId => $boolean) {
if($boolean === true) $buffer.= "<role id=\"$roleId\"/>";
}
$buffer .= "</ajxp_roles>";
}
$buffer.= AJXP_XMLWriter::writeRepositoriesData($loggedUser, $details);
$buffer.="<active_repo id=\"".ConfService::getCurrentRepositoryId()."\" write=\"".($loggedUser->canWrite(ConfService::getCurrentRepositoryId())?"1":"0")."\" read=\"".($loggedUser->canRead(ConfService::getCurrentRepositoryId())?"1":"0")."\"/>";
$buffer.= AJXP_XMLWriter::writeRepositoriesData($loggedUser);
$buffer.="<preferences>";
$preferences = $confDriver->getExposedPreferences($loggedUser);
foreach ($preferences as $prefName => $prefData) {
Expand Down Expand Up @@ -589,27 +568,24 @@ public static function getUserXML($userObject = null, $details=false)
}
return $buffer;
}

/**
* Write the repositories access rights in XML format
* @static
* @param AbstractAjxpUser|null $loggedUser
* @param bool $details
* @param AbstractAjxpUser|null $loggedUser * @internal param bool $details
* @return string
*/
public static function writeRepositoriesData($loggedUser, $details=false)
public static function writeRepositoriesData($loggedUser)
{
$st = "<repositories>";
$streams = ConfService::detectRepositoryStreams(false);
foreach (ConfService::getAccessibleRepositories($loggedUser, $details, false) as $repoId => $repoObject) {
foreach (ConfService::getAccessibleRepositories($loggedUser, false, false) as $repoId => $repoObject) {
$toLast = false;
if ($repoObject->getAccessType()=="ajxp_conf") {
if(AuthService::usersEnabled() && !$loggedUser->isAdmin())continue;
$toLast = true;
}
$rightString = "";
if ($details) {
$rightString = " r=\"".($loggedUser->canRead($repoId)?"1":"0")."\" w=\"".($loggedUser->canWrite($repoId)?"1":"0")."\"";
}
$streamString = "";
if (in_array($repoObject->accessType, $streams)) {
$streamString = "allowCrossRepositoryCopy=\"true\"";
Expand Down
8 changes: 8 additions & 0 deletions core/src/core/classes/class.AuthService.php
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,14 @@ public static function listUsers($baseGroup = "/", $regexp = null, $offset = -1,
return $allUsers;
}

public static function findUserPage($userLogin, $usersPerPage){
if(ConfService::getAuthDriverImpl()->supportsUsersPagination()){
return ConfService::getAuthDriverImpl()->findUserPage($userLogin, $usersPerPage);
}else{
return -1;
}
}

public static function authSupportsPagination()
{
$authDriver = ConfService::getAuthDriverImpl();
Expand Down
12 changes: 6 additions & 6 deletions core/src/core/classes/class.ConfService.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,12 @@ private function invalidateLoadedRepositories()
* @param bool $skipShared
* @return Repository[]
*/
public static function getAccessibleRepositories($userObject=null, $details=false, $labelOnly = false, $skipShared = false)
public static function getAccessibleRepositories($userObject=null, $details=false, $labelOnly = false, $includeShared = true)
{
$result = array();
$allReps = ConfService::getRepositoriesList("all");
$allReps = ConfService::getRepositoriesList("user");
foreach ($allReps as $repositoryId => $repositoryObject) {
if (!ConfService::repositoryIsAccessible($repositoryId, $repositoryObject, $userObject, $details, $skipShared)) {
if (!ConfService::repositoryIsAccessible($repositoryId, $repositoryObject, $userObject, $details, $includeShared)) {
continue;
}

Expand All @@ -378,11 +378,11 @@ public static function getAccessibleRepositories($userObject=null, $details=fals
* @param Repository $repositoryObject
* @param AbstractAjxpUser $userObject
* @param bool $details
* @param bool $skipShared
* @param bool $includeShared
*
* @return bool
*/
public static function repositoryIsAccessible($repositoryId, $repositoryObject, $userObject = null, $details=false, $skipShared=false)
public static function repositoryIsAccessible($repositoryId, $repositoryObject, $userObject = null, $details=false, $includeShared=true)
{
if($userObject == null) $userObject = AuthService::getLoggedUser();
if ($userObject == null && AuthService::usersEnabled()) {
Expand Down Expand Up @@ -417,7 +417,7 @@ public static function repositoryIsAccessible($repositoryId, $repositoryObject,
return false;
}
// Do not display shared repositories otherwise.
if ($repositoryObject->hasOwner() && $skipShared && ($userObject == null || $userObject->getParent() != $repositoryObject->getOwner())) {
if ($repositoryObject->hasOwner() && !$includeShared && ($userObject == null || $userObject->getParent() != $repositoryObject->getOwner())) {
return false;
}
if ($userObject != null && $repositoryObject->hasOwner() && !$userObject->hasParent()) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/plugins/access.ajxp_conf/ajxp_confActions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@
var editorData = window.actionArguments[0];
ajaxplorer.openCurrentSelectionInEditor(editorData);
]]></clientCallback>
<serverCallback methodName="switchAction" developerComment="Shortcut for various actions, calling edit with subaction parameter."/>
<serverCallback methodName="switchAction" restParams="/sub_action" developerComment="Shortcut for various actions, calling edit with subaction parameter."/>
</processing>
</action>
<action name="edit_repository_label">
Expand Down
40 changes: 27 additions & 13 deletions core/src/plugins/access.ajxp_conf/class.ajxp_confAccessDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ public function switchAction($action, $httpVars, $fileVars)
if (isSet($httpVars["format"]) && $httpVars["format"] == "json") {
HTMLWriter::charsetHeader("application/json");
$roleData = $role->getDataArray();
$repos = ConfService::getAccessibleRepositories($userObject, true, true, ($userObject == null ? true:false));
$repos = ConfService::getAccessibleRepositories($userObject, true, true, ($userObject == null ? false:true));
// Make sure it's utf8
foreach($repos as $r => $rLabel){
$repos[$r] = SystemTextEncoding::toUTF8($rLabel);
Expand Down Expand Up @@ -1068,10 +1068,12 @@ public function switchAction($action, $httpVars, $fileVars)
case "get_templates_definition":

AJXP_XMLWriter::header("repository_templates");
$repositories = ConfService::getRepositoriesList("all", false);
$repositories = ConfService::getConfStorageImpl()->listRepositoriesWithCriteria(array(
"isTemplate" => '1'
));
foreach ($repositories as $repo) {
if(!$repo->isTemplate) continue;
$repoId = $repo->getId();
$repoId = $repo->getUniqueId();
$repoLabel = SystemTextEncoding::toUTF8($repo->getDisplay());
$repoType = $repo->getAccessType();
print("<template repository_id=\"$repoId\" repository_label=\"$repoLabel\" repository_type=\"$repoType\">");
Expand Down Expand Up @@ -1759,18 +1761,30 @@ public function listUsers($root, $child, $hashValue = null, $returnNodes = false

if ($findNodePosition != null && $hashValue == null) {

// Loop on each page to find the correct page.
$count = AuthService::authCountUsers($baseGroup);
$pages = ceil($count / $USER_PER_PAGE);
for ($i = 0; $i < $pages ; $i ++) {
$position = AuthService::findUserPage($findNodePosition, $USER_PER_PAGE);
if($position != -1){

$tests = $this->listUsers($root, $child, $i+1, true, $findNodePosition);
if (is_array($tests) && isSet($tests["/data/".$root."/".$findNodePosition])) {
return array("/data/".$root."/".$findNodePosition => str_replace("ajxp_mime", "page_position='".($i+1)."' ajxp_mime", $tests["/data/".$root."/".$findNodePosition]));
}
$key = "/data/".$root."/".$findNodePosition;
$data = array($key => AJXP_XMLWriter::renderNode($key, $findNodePosition, true, array(
"page_position" => $position
), true, false));
return $data;

}else{
// Loop on each page to find the correct page.
$count = AuthService::authCountUsers($baseGroup);
$pages = ceil($count / $USER_PER_PAGE);
for ($i = 0; $i < $pages ; $i ++) {

$tests = $this->listUsers($root, $child, $i+1, true, $findNodePosition);
if (is_array($tests) && isSet($tests["/data/".$root."/".$findNodePosition])) {
return array("/data/".$root."/".$findNodePosition => str_replace("ajxp_mime", "page_position='".($i+1)."' ajxp_mime", $tests["/data/".$root."/".$findNodePosition]));
}

}
}


return array();

}
Expand Down Expand Up @@ -1824,7 +1838,6 @@ public function listUsers($root, $child, $hashValue = null, $returnNodes = false

}
$mess = ConfService::getMessages();
$repos = ConfService::getRepositoriesList("all");
$loggedUser = AuthService::getLoggedUser();
$userArray = array();
foreach ($users as $userIndex => $userObject) {
Expand All @@ -1841,6 +1854,7 @@ public function listUsers($root, $child, $hashValue = null, $returnNodes = false
}
ksort($userArray);
foreach ($userArray as $userObject) {
$repos = ConfService::getConfStorageImpl()->listRepositories($userObject);
$isAdmin = $userObject->isAdmin();
$userId = $userObject->getId();
$icon = "user".($userId=="guest"?"_guest":($isAdmin?"_admin":""));
Expand Down Expand Up @@ -1894,12 +1908,12 @@ public function listRoles($root, $child, $hashValue = null, $returnNodes = false
if(!AuthService::usersEnabled()) return ;
$roles = AuthService::getRolesList(array(), !$this->listSpecialRoles);
$mess = ConfService::getMessages();
$repos = ConfService::getRepositoriesList("all");
ksort($roles);
foreach ($roles as $roleId => $roleObject) {
//if(strpos($roleId, "AJXP_GRP_") === 0 && !$this->listSpecialRoles) continue;
$r = array();
if(!AuthService::canAdministrate($roleObject)) continue;
$repos = ConfService::getConfStorageImpl()->listRepositoriesWithCriteria(array("role" => $roleObject));
foreach ($repos as $repoId => $repository) {
if($repository->getAccessType() == "ajxp_shared") continue;
if(!$roleObject->canRead($repoId) && !$roleObject->canWrite($repoId)) continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ public function listUsers()
$loggedUser = AuthService::getLoggedUser();
$users = ConfService::getConfStorageImpl()->getUserChildren($loggedUser->getId()); // AuthService::listUsers();
$mess = ConfService::getMessages();
$repoList = ConfService::getRepositoriesList("all");
$repoList = ConfService::getConfStorageImpl()->listRepositoriesWithCriteria(array(
"owner_user_id" => $loggedUser->getId()
));
$userArray = array();
foreach ($users as $userIndex => $userObject) {
$label = $userObject->getId();
Expand Down Expand Up @@ -335,10 +337,12 @@ public function listUsers()

public function listRepositories()
{
$repos = ConfService::getRepositoriesList("all");
AJXP_XMLWriter::sendFilesListComponentConfig('<columns switchGridMode="filelist"><column messageId="ajxp_conf.8" attributeName="ajxp_label" sortType="String"/><column messageId="user_dash.9" attributeName="parent_label" sortType="String"/><column messageId="user_dash.9" attributeName="repo_accesses" sortType="String"/></columns>');
$repoArray = array();
$loggedUser = AuthService::getLoggedUser();
$repos = ConfService::getConfStorageImpl()->listRepositoriesWithCriteria(array(
"owner_user_id" => $loggedUser->getId()
));

$searchAll = ConfService::getCoreConf("CROSSUSERS_ALLGROUPS", "conf");
$displayAll = ConfService::getCoreConf("CROSSUSERS_ALLGROUPS_DISPLAY", "conf");
Expand Down
8 changes: 8 additions & 0 deletions core/src/plugins/auth.sql/class.sqlAuthDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ public function listUsersPaginated($baseGroup, $regexp, $offset, $limit)
return $pairs;
}

public function findUserPage($userLogin, $usersPerPage){

$res = dibi::query("SELECT COUNT(*) FROM [ajxp_users] WHERE [login] <= %s", $userLogin);
$count = $res->fetchSingle();
return ceil($count / $usersPerPage) - 1;

}

public function getUsersCount($baseGroup = "/", $regexp = "", $filterProperty = null, $filterValue = null)
{
// WITH PARENT
Expand Down
68 changes: 38 additions & 30 deletions core/src/plugins/conf.sql/class.sqlConfDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,23 @@ public function repoToArray($repository)
}


/**
* @param Array $array
* @return Repository[]
*/
protected function initRepoArrayFromDbFetch($array){
$repositories = array();
foreach ($array as $repo_row) {

$res_opts = dibi::query('SELECT * FROM [ajxp_repo_options] WHERE [uuid] = %s', $repo_row['uuid']);
$opts = $res_opts->fetchPairs('name', 'val');
$repo = $this->repoFromDb($repo_row, $opts);

$repositories[$repo->getUniqueId()] = $repo;
}
return $repositories;
}

/**
* Get a list of repositories
*
Expand All @@ -199,43 +216,43 @@ public function repoToArray($repository)
public function listRepositories($user = null)
{
if ($user != null) {
$acls = $user->mergedRole->listAcls();
$limitRepositories = array_keys($acls);
if(!count($limitRepositories)) return array();
// we use (%s) instead of %in to pass int as string ('1' instead of 1)
$res = dibi::query('SELECT * FROM [ajxp_repo] WHERE [uuid] IN (%s) ORDER BY [display] ASC', $limitRepositories);
return $this->listRepositoriesForRole($user->mergedRole);
} else {
$res = dibi::query('SELECT * FROM [ajxp_repo] ORDER BY [display] ASC');
}

$all = $res->fetchAll();
return $this->initRepoArrayFromDbFetch($all);
}

$repositories = Array();

foreach ($all as $repo_row) {

$res_opts = dibi::query('SELECT * FROM [ajxp_repo_options] WHERE [uuid] = %s', $repo_row['uuid']);
$opts = $res_opts->fetchPairs('name', 'val');
$repo = $this->repoFromDb($repo_row, $opts);

$repositories[$repo->getUniqueId()] = $repo;
}

return $repositories;
/**
* @param AJXP_Role $role
* @return Repository[]
*/
public function listRepositoriesForRole($role){
$acls = $role->listAcls();
if(!count($acls)) return array();
$limitRepositories = array_keys($acls);
$res = dibi::query('SELECT * FROM [ajxp_repo] WHERE [uuid] IN (%s) ORDER BY [display] ASC', $limitRepositories);
$all = $res->fetchAll();
return $this->initRepoArrayFromDbFetch($all);
}

/**
* Returns a list of available repositories (dynamic ones only, not the ones defined in the config file).
* @param Array $criteria
* @param int $count possible total count
* @return Array
* @return Repository[]
*/
public function listRepositoriesWithCriteria($criteria, &$count = null){

$wheres = array();
$limit = $groupBy = "";
$order = "ORDER BY display ASC";

if(isSet($criteria["role"]) && is_a($criteria["role"], "AJXP_Role")){
return $this->listRepositoriesForRole($criteria["role"]);
}

$searchableKeys = array("uuid", "parent_uuid", "owner_user_id", "display", "accessType", "isTemplate", "slug", "groupPath");
foreach($criteria as $cName => $cValue){
if(in_array($cName, $searchableKeys)){
Expand All @@ -250,7 +267,7 @@ public function listRepositoriesWithCriteria($criteria, &$count = null){
$wheres[] = array("[$cName] IS NULL");
}else{
$type = "%s";
if($cName == 'isTemplate') $type = "%d";
if($cName == 'isTemplate') $type = "%i";
$wheres[] = array("[$cName] = $type", $cValue);
}
}else if($cName == "CURSOR"){
Expand All @@ -269,16 +286,7 @@ public function listRepositoriesWithCriteria($criteria, &$count = null){

$res = dibi::query("SELECT * FROM [ajxp_repo] WHERE %and $groupBy $order $limit", $wheres);
$all = $res->fetchAll();

$repositories = Array();
foreach ($all as $repo_row) {
$res_opts = dibi::query('SELECT * FROM [ajxp_repo_options] WHERE [uuid] = %s', $repo_row['uuid']);
$opts = $res_opts->fetchPairs('name', 'val');
$repo = $this->repoFromDb($repo_row, $opts);
$repositories[$repo->getUniqueId()] = $repo;
}

return $repositories;
return $this->initRepoArrayFromDbFetch($all);

}

Expand Down
Loading

0 comments on commit 87e1ddd

Please sign in to comment.