Преглед на файлове

New field on the User class to enable/disable user accounts.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@4230 a333f486-631f-4898-b8df-5754b55c2be0
dflaven преди 9 години
родител
ревизия
5a63878541

+ 85 - 81
application/loginwebpage.class.inc.php

@@ -478,97 +478,101 @@ EOF
 		{
 			//echo "User: ".$_SESSION['auth_user']."\n";
 			// Already authentified
-			UserRights::Login($_SESSION['auth_user']); // Login & set the user's language
-			return self::EXIT_CODE_OK;
+			$bRet = UserRights::Login($_SESSION['auth_user']); // Login & set the user's language
+			if ($bRet)
+			{
+				return self::EXIT_CODE_OK;
+			}
+			// The user account is no longer valid/enabled
+			 static::ResetSession();
 		}
-		else
+		
+		$index = 0;
+		$sLoginMode = '';
+		$sAuthentication = 'internal';
+		while(($sLoginMode == '') && ($index < count($aAllowedLoginTypes)))
 		{
-			$index = 0;
-			$sLoginMode = '';
-			$sAuthentication = 'internal';
-			while(($sLoginMode == '') && ($index < count($aAllowedLoginTypes)))
+			$sLoginType = $aAllowedLoginTypes[$index];
+			switch($sLoginType)
 			{
-				$sLoginType = $aAllowedLoginTypes[$index];
-				switch($sLoginType)
+				case 'cas':
+				utils::InitCASClient();					
+				// check CAS authentication
+				if (phpCAS::isAuthenticated())
 				{
-					case 'cas':
-					utils::InitCASClient();					
-					// check CAS authentication
-					if (phpCAS::isAuthenticated())
-					{
-						$sAuthUser = phpCAS::getUser();
-						$sAuthPwd = '';
-						$sLoginMode = 'cas';
-						$sAuthentication = 'external';
-					}
-					break;
-					
-					case 'form':
-					// iTop standard mode: form based authentication
-					$sAuthUser = utils::ReadPostedParam('auth_user', '', false, 'raw_data');
-					$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, false, 'raw_data');
-					if (($sAuthUser != '') && ($sAuthPwd !== null))
-					{
-						$sLoginMode = 'form';
-					}
-					break;
-					
-					case 'basic':
-					// Standard PHP authentication method, works with Apache...
-					// Case 1) Apache running in CGI mode + rewrite rules in .htaccess
-					if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
-					{
-						list($sAuthUser, $sAuthPwd) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
-						$sLoginMode = 'basic';
-					}
-					else if (isset($_SERVER['PHP_AUTH_USER']))
+					$sAuthUser = phpCAS::getUser();
+					$sAuthPwd = '';
+					$sLoginMode = 'cas';
+					$sAuthentication = 'external';
+				}
+				break;
+				
+				case 'form':
+				// iTop standard mode: form based authentication
+				$sAuthUser = utils::ReadPostedParam('auth_user', '', false, 'raw_data');
+				$sAuthPwd = utils::ReadPostedParam('auth_pwd', null, false, 'raw_data');
+				if (($sAuthUser != '') && ($sAuthPwd !== null))
+				{
+					$sLoginMode = 'form';
+				}
+				break;
+				
+				case 'basic':
+				// Standard PHP authentication method, works with Apache...
+				// Case 1) Apache running in CGI mode + rewrite rules in .htaccess
+				if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION']))
+				{
+					list($sAuthUser, $sAuthPwd) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
+					$sLoginMode = 'basic';
+				}
+				else if (isset($_SERVER['PHP_AUTH_USER']))
+				{
+					$sAuthUser = $_SERVER['PHP_AUTH_USER'];
+					// Unfortunately, the RFC is not clear about the encoding...
+					// IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8
+					// So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base
+					if (!self::LooksLikeUTF8($sAuthUser))
 					{
-						$sAuthUser = $_SERVER['PHP_AUTH_USER'];
-						// Unfortunately, the RFC is not clear about the encoding...
-						// IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8
-						// So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base
-						if (!self::LooksLikeUTF8($sAuthUser))
-						{
-							// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
-							// Supposed to be harmless in case of a plain ASCII string...
-							$sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser);
-						}
-						$sAuthPwd = $_SERVER['PHP_AUTH_PW'];
-						if (!self::LooksLikeUTF8($sAuthPwd))
-						{
-							// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
-							// Supposed to be harmless in case of a plain ASCII string...
-							$sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd);
-						}
-						$sLoginMode = 'basic';
+						// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
+						// Supposed to be harmless in case of a plain ASCII string...
+						$sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser);
 					}
-					break;
-
-					case 'external':
-					// Web server supplied authentication
-					$bExternalAuth = false;
-					$sExtAuthVar = MetaModel::GetConfig()->GetExternalAuthenticationVariable(); // In which variable is the info passed ?
-					eval('$sAuthUser = isset('.$sExtAuthVar.') ? '.$sExtAuthVar.' : false;'); // Retrieve the value
-					if ($sAuthUser && (strlen($sAuthUser) > 0))
+					$sAuthPwd = $_SERVER['PHP_AUTH_PW'];
+					if (!self::LooksLikeUTF8($sAuthPwd))
 					{
-						$sAuthPwd = ''; // No password in this case the web server already authentified the user...
-						$sLoginMode = 'external';
-						$sAuthentication = 'external';
+						// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
+						// Supposed to be harmless in case of a plain ASCII string...
+						$sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd);
 					}
-					break;
-
-					case 'url':
-					// Credentials passed directly in the url
-					$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
-					$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
-					if (($sAuthUser != '') && ($sAuthPwd !== null))
-					{
-						$sLoginMode = 'url';
-					}		
-					break;	
+					$sLoginMode = 'basic';
 				}
-				$index++;
+				break;
+
+				case 'external':
+				// Web server supplied authentication
+				$bExternalAuth = false;
+				$sExtAuthVar = MetaModel::GetConfig()->GetExternalAuthenticationVariable(); // In which variable is the info passed ?
+				eval('$sAuthUser = isset('.$sExtAuthVar.') ? '.$sExtAuthVar.' : false;'); // Retrieve the value
+				if ($sAuthUser && (strlen($sAuthUser) > 0))
+				{
+					$sAuthPwd = ''; // No password in this case the web server already authentified the user...
+					$sLoginMode = 'external';
+					$sAuthentication = 'external';
+				}
+				break;
+
+				case 'url':
+				// Credentials passed directly in the url
+				$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
+				$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
+				if (($sAuthUser != '') && ($sAuthPwd !== null))
+				{
+					$sLoginMode = 'url';
+				}		
+				break;	
 			}
+			$index++;
+			
 			//echo "\nsLoginMode: $sLoginMode (user: $sAuthUser / pwd: $sAuthPwd\n)";
 			if ($sLoginMode == '')
 			{

+ 25 - 9
core/userrights.class.inc.php

@@ -188,15 +188,16 @@ abstract class User extends cmdbAbstractObject
 		MetaModel::Init_AddAttribute(new AttributeString("login", array("allowed_values"=>null, "sql"=>"login", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
 
 		MetaModel::Init_AddAttribute(new AttributeApplicationLanguage("language", array("sql"=>"language", "default_value"=>"EN US", "is_null_allowed"=>false, "depends_on"=>array())));
-
+		MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values" => new ValueSetEnum('enabled,disabled'), "sql"=>"status", "default_value"=>"enabled", "is_null_allowed"=>false, "depends_on"=>array())));
+		
 		MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("profile_list", array("linked_class"=>"URP_UserProfile", "ext_key_to_me"=>"userid", "ext_key_to_remote"=>"profileid", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
 		MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("allowed_org_list", array("linked_class"=>"URP_UserOrg", "ext_key_to_me"=>"userid", "ext_key_to_remote"=>"allowed_org_id", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 
@@ -432,10 +433,10 @@ abstract class UserInternal extends User
 		MetaModel::Init_AddAttribute(new AttributeOneWayPassword("reset_pwd_token", array("allowed_values"=>null, "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'status', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 
@@ -591,7 +592,17 @@ class UserRights
 		$oUser = self::FindUser($sName, $sAuthentication);
 		if (is_null($oUser))
 		{
-			return self::CheckCredentialsAndCreateUser($sName, $sPassword, $sLoginMode, $sAuthentication);
+			// Check if the user does not exist at all or if it is just disabled
+			if (self::FindUser($sName, $sAuthentication, true) == null)
+			{
+				// User does not exist at all
+				return self::CheckCredentialsAndCreateUser($sName, $sPassword, $sLoginMode, $sAuthentication);
+			}
+			else
+			{
+				// User is actually disabled
+				return  false;
+			}
 		}
 
 		if (!$oUser->CheckCredentials($sPassword))
@@ -1084,9 +1095,10 @@ class UserRights
 	 * Find a user based on its login and its type of authentication
 	 * @param string $sLogin Login/identifier of the user
 	 * @param string $sAuthentication Type of authentication used: internal|external|any
+	 * @param bool $bAllowDisabledUsers Whether or not to retrieve disabled users (status != enabled)
 	 * @return User The found user or null
 	 */
-	protected static function FindUser($sLogin, $sAuthentication = 'any')
+	protected static function FindUser($sLogin, $sAuthentication = 'any', $bAllowDisabledUsers = false)
 	{
 		if ($sAuthentication == 'any')
 		{
@@ -1120,6 +1132,10 @@ class UserRights
 					assert(false); // should never happen
 				}
 				$oSearch = DBObjectSearch::FromOQL("SELECT $sBaseClass WHERE login = :login");
+				if (!$bAllowDisabledUsers)
+				{
+					$oSearch->AddCondition('status', 'enabled');
+				}
 				$oSet = new DBObjectSet($oSearch, array(), array('login' => $sLogin));
 				$oUser = $oSet->fetch();
 				self::$m_aCacheUsers[$sAuthentication][$sLogin] = $oUser;

+ 3 - 3
datamodels/1.x/authent-external/model.authent-external.php

@@ -51,10 +51,10 @@ class UserExternal extends User
 		MetaModel::Init_InheritAttributes();
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 

+ 3 - 3
datamodels/1.x/authent-ldap/model.authent-ldap.php

@@ -46,10 +46,10 @@ class UserLDAP extends UserInternal
 		MetaModel::Init_InheritAttributes();
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 

+ 3 - 3
datamodels/1.x/authent-local/model.authent-local.php

@@ -48,10 +48,10 @@ class UserLocal extends UserInternal
 		MetaModel::Init_AddAttribute(new AttributeOneWayPassword("password", array("allowed_values"=>null, "sql"=>"pwd", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'password', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'password', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 

+ 3 - 3
datamodels/2.x/authent-external/model.authent-external.php

@@ -51,10 +51,10 @@ class UserExternal extends User
 		MetaModel::Init_InheritAttributes();
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 

+ 3 - 3
datamodels/2.x/authent-ldap/model.authent-ldap.php

@@ -46,10 +46,10 @@ class UserLDAP extends UserInternal
 		MetaModel::Init_InheritAttributes();
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login', 'status')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 

+ 2 - 2
datamodels/2.x/authent-local/model.authent-local.php

@@ -48,10 +48,10 @@ class UserLocal extends UserInternal
 		MetaModel::Init_AddAttribute(new AttributeOneWayPassword("password", array("allowed_values"=>null, "sql"=>"pwd", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
 
 		// Display lists
-		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'password', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
+		MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'password', 'language', 'status', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
 		MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
 		// Search criteria
-		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
+		MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid', 'status')); // Criteria of the std search form
 		MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
 	}
 

+ 4 - 0
dictionaries/de.dictionary.itop.ui.php

@@ -108,6 +108,10 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
 	'Class:User/Attribute:language/Value:EN US+' => 'English (U.S.)',
 	'Class:User/Attribute:language/Value:FR FR' => 'French',
 	'Class:User/Attribute:language/Value:FR FR+' => 'French (France)',
+	'Class:User/Attribute:status' => 'Status',
+	'Class:User/Attribute:status+' => 'Ist das Benutzer aktiviert oder deaktiviert ?',
+	'Class:User/Attribute:status/Value:enabled' => 'Akitv',
+	'Class:User/Attribute:status/Value:disabled' => 'Inaktiv',
 	'Class:User/Attribute:profile_list' => 'Profile',
 	'Class:User/Attribute:profile_list+' => 'Rollen, Rechtemanagement für diese Person',
 	'Class:User/Attribute:allowed_org_list' => 'Erlaubte Organisationen',

+ 5 - 1
dictionaries/dictionary.itop.ui.php

@@ -131,7 +131,11 @@ Dict::Add('EN US', 'English', 'English', array(
 	'Class:User/Attribute:profile_list+' => 'Roles, granting rights for that person',
 	'Class:User/Attribute:allowed_org_list' => 'Allowed Organizations',
 	'Class:User/Attribute:allowed_org_list+' => 'The end user is allowed to see data belonging to the following organizations. If no organization is specified, there is no restriction.',
-
+	'Class:User/Attribute:status' => 'Status',
+	'Class:User/Attribute:status+' => 'Whether the user account is enabled or disabled.',
+	'Class:User/Attribute:status/Value:enabled' => 'Enabled',
+	'Class:User/Attribute:status/Value:disabled' => 'Disabled',
+		
 	'Class:User/Error:LoginMustBeUnique' => 'Login must be unique - "%1s" is already being used.',
 	'Class:User/Error:AtLeastOneProfileIsNeeded' => 'At least one profile must be assigned to this user.',
 

+ 5 - 0
dictionaries/fr.dictionary.itop.ui.php

@@ -156,6 +156,11 @@ Dict::Add('FR FR', 'French', 'Français', array(
 	'Class:User/Attribute:profile_list+' => 'Rôles, ouvrants les droits d\'accès',
 	'Class:User/Attribute:allowed_org_list' => 'Organisations permises',
 	'Class:User/Attribute:allowed_org_list+' => 'L\'utilisateur a le droit de voir les données des organisations listées ici. Si aucune organisation n\'est spécifiée, alors aucune restriction ne s\'applique.',
+	'Class:User/Attribute:status' => 'Etat',
+	'Class:User/Attribute:status+' => 'Est-ce que ce compte utilisateur est actif, ou non?',
+	'Class:User/Attribute:status/Value:enabled' => 'Actif',
+	'Class:User/Attribute:status/Value:disabled' => 'Désactivé',
+	'Class:User/Attribute:status' => 'Etat',
 	'Class:User/Error:LoginMustBeUnique' => 'Le login doit être unique - "%1s" est déjà utilisé.',
 	'Class:User/Error:AtLeastOneProfileIsNeeded' => 'L\'utilisateur doit avoir au moins un profil.',
 	'Class:UserInternal' => 'Utilisateur interne',