# Manipulation des comptes utilisateur

Ce chapitre a pour but de montrer, par l'utilisation des méthodes et fonctions les plus courantes, la manipulation des utilisateurs "interne".

# Création d'un utilisateur

La création d'un utilisateur peut être fait à l'aide de la Smart Structure IUSER.
Les comptes utilisateurs sont gérés par la classe Account. La Smart Structure IUSER permet de faire le lien entre le compte "système" (classe Account) et le Smart Element (Smart Structure IUSER).
Un utilisateur est identifié par un numéro unique. Ce numéro est renseigné par le Smart Field us_whatid du Smart Element IUSER. Il correspond au Smart Field "id" de la classe Account.
Code minimaliste pour créer un utilisateur via les Smart Elements.

use Anakeen\SmartElementManager;

$account = SmartElementManager::createDocument("IUSER");
if ($account) {
  $account->setValue("us_login", "léo.tes");
  $account->setValue("us_lname", "tes");
  $account->setValue("us_fname", "léo");
  $account->setValue("us_passwd1", "secret");
  $account->setValue("us_passwd2", "secret"); // nécessaire à doubler à causde des contraintes
  $err = $account->store();
  if (!$err) {
    print "nouvel utilisateur n°" . $account->getRawValue("us_whatid"); //affichage de l'identifiant système
  } else {
    print "\nerreur:" . $err;
  }
}

# Correspondance entre compte User et Smart Element IUSER

Pour récupérer le compte système à partir du Smart Element IUSER:

use Anakeen\SmartElementManager;
use Anakeen\Core\AccountManager;

$userDoc = AccountManager::getAccount("zoo.user4");
$doc = SmartElementManager::getDocument(98430);
if ($doc->getRawValue("us_whatid") != $userDoc->id) {
  //ce n'est pas normal
}

Si vous ne disposez que de l'identifiant du Smart Element, vous pouvez aussi utiliser la méthode setFid de la classe Account:

use Anakeen\Core\Account;

$user = new Account();
$user->setFid(98430);
if ($user->isAffected()) {
  print $user->login . " is affected";
}

A l'inverse pour récupérer l'objet Smart Element à partir du compte système, vous pouvez utiliser le Smart Field fid.

use Anakeen\Core\Account;
use Anakeen\SmartElement;

$user = new Account();
$user->setLoginName("john.doe");
if ($user->isAffected()) {
  $doc = new SmartElement($user->fid);
}

Smart Field de correspondance: Compte User <=> Smart Element IUSER

Compte User Smart Element IUSER
id us_whatid
login us_login
mail us_mail
firstname us_fname
lastname us_lname
fid id

Exemple de création d'utilisateur via la classe Account

use Anakeen\Core\Account;

$user = new Account();
$user->login = "jean.dupond";
$user->firstname = "Jean";
$user->lastname = "Dupond";
$user->password_new = "secret";
$err = $user->add();
if ($err) {
  error_log($err);
} else {
  print "Nouvel utilisateur n°" . $user->id;
}

# Groupe d'utilisateurs

La Smart Structure IGROUP permet de rajouter des utilisateurs dans des groupes.
La Smart Structure IGROUP comme la Smart Structure IUSER utilise la classe Account pour identifier les groupes système.
Comme la Smart Structure IUSER, la Smart Structure IGROUP dispose de la méthode IGROUP::getAccount() pour récupérer l'objet Account correspondant.

# Correspondance Compte Groupe <=> Smart Element IGROUP

Compte Groupe Smart Element IGROUP
id us_whatid
login us_login
lastname grp_name
fid id

Le compte Account d'un groupe a toujours son Smart Field accounttype à G.

# Ajout d'un utilisateur à un groupe

Utilisation de Anakeen\SmartStructures\Igroup::insertDocument(). Ajout de l'utilisateur n° dans le groupe GDEFAULT:

use Anakeen\Core\SEManager;

$group = SEManager::getDocument("GDEFAULT");
$user = SEManager::getDocument(98430);
printf(
  "ajout de l'utilisateur %s [%d] au groupe %s [%d]\n",
  $user->getTitle(),
  $user->id,
  $group->getTitle(),
  $group->id
);
printf("Liste des groupes avant ajout\n");
print $user->getRawValue("us_idgroup");

$err = $group->insertDocument($user->getRawValue("initid"));
if ($err) {
  print "Error:$err\n";
} else {
  printf("Liste des groupes après ajout \n");
  print_r($user->getRawValue("us_idgroup"));
}

# Suppression d'utilisateur dans un groupe

Utilisation de Anakeen\SmartStructures\Igroup::removeDocument().

use Anakeen\Core\SEManager;

$group = SEManager::getDocument("GDEFAULT");
$user = SEManager::getDocument(98430);
printf(
  "suppression de l'utilisateur %s [%d] du groupe %s [%d]\n",
  $user->getTitle(),
  $user->id,
  $group->getTitle(),
  $group->id
);
printf("Liste des groupes avant suppression\n");
print $user->getRawValue("us_idgroup");

$err = $group->removeDocument($user->getRawValue("initid"));
if ($err) {
  print "Error:$err\n";
} else {
  printf("Liste des groupes après suppression\n");
  print_r($user->getRawValue("us_idgroup"));
}

# Récupération des membres d'un groupe

À partir de l'objet Account d'un groupe Account::getAllMembers().

Exemple:

use Anakeen\Core\SEManager;

$elgroup = SEManager::getDocument("GDEFAULT");
$group = $elgroup->getAccount();
$members = $group->getAllMembers();
$userElIdList = array();
foreach ($members as $user) {
  printf("%s %s \n", $user["id"], $user["login"]);
  $userElIdList[] = $user["fid"];
}
print "-----------\n";
$elementList = new \ElementList();
$elementList->addElementIdentifiers($userElIdList);
foreach ($elementList as $docid => $docIUser) {
  printf("%s %s \n", $docIUser->id, $docIUser->getTitle());
}

# Rôles

La Smart Structure ROLE permet d'associer des rôles à des utilisateurs ou à des groupes.
La Smart Structure ROLE comme la Smart Structure IUSER utilisa la class Account pour identifier les groupes système.
Comme la Smart Structure IUSER, la Smart Structure ROLE dispose de la méthode ROLE::getAccount() pour récupérer l'objet Account correspondant.

# Correspondance Compte Rôle <=> Smart Element ROLE

Compte Rôle Smart Element ROLE
id us_whatid
login role_login
lastname role_name
fid id

# Récupération des utilisateurs associés à un rôle

Comme pour les groupes, à partir de l'objet Account d'un rôle : Account::getAllMembers().

Exemple:

use Anakeen\Core\SEManager;

$elRole = SEManager::getDocument(945); // identifiant ou nom logique du rôle (ici : identifiant du rôle "hub admin")
$members = $elRole->getAccount()->getAllMembers();
$userElIdList = array();
foreach ($members as $user) {
  printf("%s %s \n", $user["id"], $user["login"]);
  $userElIdList[] = $user["fid"];
}
print "-----------\n";
$elementList = new \ElementList();
$elementList->addElementIdentifiers($userElIdList);
foreach ($elementList as $docid => $docIUser) {
  printf("%s %s \n", $docIUser->id, $docIUser->getTitle());
}

# Récupération des rôles d'un utilisateur

À partir de l'objet Account, méthode Account::getAllRoles().

Exemple:

use Anakeen\Core\Account;

$user = new Account();
$user->setLoginName("john.doe");
if ($user->isAffected()) {
  $roles = $user->getAllRoles();
  foreach ($roles as $aRole) {
    printf("%d %s \n", $aRole["id"], $aRole["login"]);
  }
}

# Suppléants et titulaires

Affectation d'un suppléant à un utilisateur et récupérations des titulaires

use Anakeen\Core\Account;

$user = new Account();
$user->setLoginName("john.doe");
if ($user->isAffected()) {
  $err = $user->setSubstitute("spock");
}
$user->setLoginName("spock");
$incumbents = $user->getIncumbents();
foreach ($incumbents as $key => $aIncumbent) {
  printf("%d %s \n", $key, Account::getDisplayName($aIncumbent));
}

# Recherche de comptes

Il est possible de rechercher les comptes suivant leurs critères d'appartenance à des rôles ou des groupes. La classe SearchAccount permet de réaliser facilement la recherche de compte. Le résultat de cette recherche peut retourner des utilisateurs, des groupes ou des rôles.

# Recherche des utilisateurs par rôle

Pour indiquer le filtre d'un rôle, il faut utiliser la méthode addRoleFilter(). Cette méthode prend en argument la référence du rôle. La référence correspond au Smart Field role_login du Smart Element ou au Smart Field login de l'objet Account. Il ne correspond pas au nom logique du Smart Element.

use Anakeen\Accounts\SearchAccounts;

$searchAccount = new SearchAccounts();
$searchAccount->addRoleFilter("hub-admin-role");
$searchAccount->setObjectReturn($searchAccount::returnAccount);

$accountList = $searchAccount->search();
foreach ($accountList as $account) {
  $login = $account->login;
  print "$login\n";
}

La méthode SearchAccounts::setObjetReturn permet d'indiquer le type de résultat obtenu par la méthode SearchAccounts::search(). Par défaut, cela retourne un objet AccountList qui est un itérateur sur des objets Account. Il est possible d'indiquer SearchAccounts::returnDocument, pour que la recherche retourne un objet ElementList qui donnera les Smart Elements correspondants.

use Anakeen\Accounts\SearchAccounts;

$searchAccount = new SearchAccounts();
$searchAccount->addRoleFilter("hub-admin-role");
$searchAccount->setObjectReturn($searchAccount::returnDocument);

$elementList = $searchAccount->search();
foreach ($elementList as $element) {
  $login = $element->getRawValue("us_login");
  print "$login\n";
}

Si on précise plusieurs rôles séparés par un espace, cela indiquera une disjonction (OU).

$searchAccount->addRoleFilter("hub-admin-role hub-user-role");

Cette écriture est équivalente à :

$searchAccount->addRoleFilter("hub-admin-role");
$searchAccount->addRoleFilter("hub-user-role");

# Recherche des utilisateurs par groupe

La méthode addGroupFilter() est équivalent à addRoleFilter(). Elle permet de rechercher parmi les comptes qui appartiennent à différents groupes. Si cette méthode est combinée à la méthode addRoleFilter() cela indique tous les comptes qui appartiennent à un des groupes cités ou à un des rôles cités.

$searchAccounts->addGroupFilter("all"); // tous les utilisateurs du groupe `all`

La recherche par groupe recherche aussi les comptes dans les sous-groupes. Ce filtre peut retourner des groupes ou des utilisateurs.

# Recherche sur des critères de compte

La méthode addFilter() permet d'ajouter des filtres sur les caractéristiques des comptes:

  • login,
  • firstname,
  • lastname,
  • mail,
  • accounttype,
  • status.
use Anakeen\Accounts\SearchAccounts;

$mailExpre = "test";
$searchAccount = new SearchAccounts();
$searchAccount->addfilter("mail ~ '%s'", $mailExpre); // files les mails qui contiennent test
$accountList = $searchAccount->search();
foreach ($accountList as $account) {
  printf("%s => %s\n", $account->login, $account->mail);
}

La méthode SearchAccounts::addFilter() ajoute une condition supplémentaire sur le filtre. Le premier argument est la partie statique du filtre et les suivants sont les arguments du filtre comme pour sprintf.
Au contraire de SearchAccounts::addGroupFilter() ou SearchAccount::addRoleFilter() les filtres sont autant de critères ajoutés à la condition finale.
La méthode SearchAccount::setTypeReturn() permet de préciser le type de compte à retourner: Utilisateur, Groupe ou Rôle.

$searchAccount->setTypeFilter($searchAccount::userType); // limité aux utilisateurs.
$searchAccount->setTypeFilter($searchAccount::userType | $searchAccount::groupType); // limité aux utilisateurs et aux groupes.
$searchAccount->setTypeFilter($searchAccount::roleType); // limité aux rôles.

# Spécialisation des Smart Elements utilisateurs

Les Smart Elements système utilisateur (Smart Structure IUSER) peuvent être dérivés pour ajouter des informations fonctionnelles ou pour ajouter des informations techniques dans le cas d'un backend d'authentification spécifique.
La Smart Structure IUSER n'impose pas de contrainte de syntaxe sur le login. La seule contrainte est que ce login doit être unique parmi tous les comptes (utilisateurs, groupes et rôles). Si vous voulez ajouter une contrainte de syntaxe sur votre Smart Structure utilisateur dérivé de IUSER, vous devez surcharger la méthode IUSER::contraintLogin() qui est une méthode contrainte.

Exemple:

// constraint to limit login to 6 characters
public function constraintLogin($login)
{
    //only six alpha numeric
    $err = '';
    if (!preg_match("/^[a-z0-9]{6}$/i", $login)) {
        $err = _("the login must have six characters at most");
    }
    // must verify unicity
    if (!$err) return parent::constraintLogin($login);
    return $err;
}

Attention

Lorsque la Smart Structure IUSER est dérivée, il faut reprendre et adapter le paramétrage en terme de sécurité (profil, contrôle de vue) en fonction de vos besoins.