17.2.1.19. Users

These are the library functions for user functions. It depends on the lib.resolver and lib.realm.

There are and must be no dependencies to the token functions (lib.token) or to webservices!

This code is tested in tests/test_lib_user.py

class privacyidea.lib.user.User(login='', realm='', resolver='', uid=None)[source]

The user has the attributes login, realm and resolver.

Usually a user can be found via “login@realm”.

A user object with an empty login and realm should not exist, whereas a user object could have an empty resolver.

property attributes: dict

returns the custom attributes of a user :return: a dictionary of attributes with keys and values

property available_info_keys: list[str]

returns the possible keys for user information for this user

Returns:

a list of possible keys for user information

Return type:

list

check_password(password: str) → str[source]

The password of the user is checked against the user source

Parameters:

password – The clear text password

Returns:

the username of the authenticated user. If unsuccessful, returns None

delete() → bool[source]

This deletes the user in the user store. I.e. the user in the SQL database or the LDAP gets deleted.

Returns True in case of success

delete_attribute(attribute_key: str = None) → int[source]

Delete the given key as custom user attribute. If no key is given, then all attributes are deleted

Parameters:

attribute_key – The key to delete

Returns:

The number of deleted rows

delete_internal_attribute(key: str | None = None) → int[source]

Delete an internal attribute. If key is None, all internal attributes for this user are deleted.

exist() → bool[source]

Check if the user object exists in the user store :return: True or False

get_search_fields() → dict[source]

Return the valid search fields of a user. The search fields are defined in the UserIdResolver class.

Returns:

searchFields with name (key) and type (value)

Return type:

dict

get_specific_info(attributes: list[str] = None) → dict[source]

returns the specified attributes for the user or all if attributes is None

Returns:

a dict with the specified user information

get_user_identifiers() → tuple[str, str, str][source]

This returns the UserId information from the resolver object and the resolvertype and the resolvername (former: getUserId) (former: getUserResolverId)

Returns:

The userid, the resolver type and the resolver name like (1000, “passwdresolver”, “resolver1”)

Return type:

tuple

get_user_phone(phone_type: str = 'phone', index: int = None) → str[source]

Returns the phone number or a list of phone numbers of a user.

Parameters:
  • phone_type (string) – The type of the phone, i.e. either mobile or phone (land line)

  • index – The index of the selected phone number of list of the phones of the user. If the index is given, this phone number as string is returned. If the index is omitted, all phone numbers are returned.

Returns:

list with phone numbers of this user object

get_user_realms() → list[str][source]

Returns a list of the realms, a user belongs to. Usually this will only be one realm. But if the user object has no realm but only a resolver, than all realms, containing this resolver are returned. This function is used for the policy module

Returns:

realms of the user

Return type:

list

property info: dict

return the detailed information for the user

Returns:

a dict with all the userinformation

Return type:

dict

property internal_attributes: dict

Returns all internal user attributes for this user as a dict. Internal attributes are written by privacyIDEA itself (e.g. cached FIDO2 user IDs, last-used token per client) and are NOT meant to be used in policy conditions. Use attributes() for admin-facing data.

For an unresolved user (empty uid) this returns {} rather than raising — callers like preferred_client_mode run for every auth response, including serial-only flows that legitimately have no user.

is_empty() → bool[source]
login = ''
realm = ''
resolver = ''
set_attribute(attribute_key: str, attribute_value: str, attribute_type: str = None) → int[source]

Set a custom attribute for a user

Parameters:
  • attribute_key – The key of the attribute

  • attribute_value – The value of the attribute

Returns:

The id of the attribute setting

set_internal_attribute(key: str, value: Any) → int[source]

Set an internal attribute for this user. value may be any JSON-serializable Python object.

The model’s node column is reserved for future node-local state and is intentionally not exposed here: it is part of neither the lookup nor the unique constraint yet, so writing it would create inconsistent rows. When node-awareness is implemented, node must be added to the unique constraint and to the SELECT below before it can be written here.

Not safe against concurrent writes on the same key for the same user: two callers can both miss the SELECT and race on the INSERT, with one hitting the UNIQUE constraint. Acceptable for the current callers (hint-style values, low contention).

update_user_info(attributes: dict, password: str = None) → bool[source]

This updates the given attributes of a user. The attributes can be “username”, “surname”, “givenname”, “email”, “mobile”, “phone”, “password”

Parameters:
  • attributes – A dictionary of the attributes to be updated

  • password – The password of the user

Returns:

True in case of success

user_export_dict() → dict[source]

Returns a dictionary with the user identifiers, which can be used to assign a token to the same user after import.

Returns:

A dictionary with the user identifiers

privacyidea.lib.user.count_users(param: dict | None = None, failures: list[str] | None = None, allowed_resolvers: dict[str, list[str]] | None = None, user_filter: Callable[[str, str, str | None], bool] | None = None) → dict[str, int][source]

Count the users get_user_list() lists for param, and how many of them own a token.

Both numbers come from one listing, deduplicated the same way the user list is, so the users without a token are their difference and each number matches the length of the user list with the corresponding has_tokens filter. A has_tokens entry in param is ignored.

Parameters:
  • param – search parameters, as for get_user_list()

  • failures – optional list, receives the resolvers that could not be queried, as for get_user_list()

  • allowed_resolvers – optional, the resolvers that may be counted in each realm, as for get_user_list()

  • user_filter – optional, which users may be counted, as for get_user_list()

Returns:

{"count": <number of users>, "with_tokens": <number of those that own a token>}

privacyidea.lib.user.create_user(resolvername: str, attributes: dict, password: str = None) → int[source]

This creates a new user in the given resolver. The resolver must be editable to do so.

The attributes is a dictionary containing the keys “username”, “email”, “phone”, “mobile”, “surname”, “givenname”, “password”.

We return the UID and not the user object, since the user could be located in several realms!

Parameters:
  • resolvername (basestring) – The name of the resolver, in which the user should be created

  • attributes (dict) – Attributes of the user

  • password – The password of the user

Returns:

The uid of the user object

privacyidea.lib.user.delete_orphaned_custom_attributes(orphans: list[tuple[str, str, int | None]]) → int[source]

Delete every customuserattribute row belonging to one of orphans. See _delete_orphaned_attributes().

privacyidea.lib.user.delete_orphaned_internal_attributes(orphans: list[tuple[str, str, int | None]]) → int[source]

Delete every internaluserattribute row belonging to one of orphans. See _delete_orphaned_attributes().

privacyidea.lib.user.find_orphaned_custom_attributes(orphaned_on_error: bool = False) → list[tuple[str, str, int | None]][source]

Return the (user_id, resolver, realm_id) tuples in customuserattribute whose user is no longer in the resolver. See _find_orphaned_attributes().

privacyidea.lib.user.find_orphaned_internal_attributes(orphaned_on_error: bool = False) → list[tuple[str, str, int | None]][source]

Return the (user_id, resolver, realm_id) tuples in internaluserattribute whose user is no longer in the resolver. See _find_orphaned_attributes().

privacyidea.lib.user.get_attributes(uid: str, resolver: str, realm_id: int, requested_attributes: list[str] = None) → dict[source]

Returns the attributes for the given user.

Parameters:
  • uid – The UID of the user

  • resolver – The name of the resolver

  • realm_id – The realm_id

  • requested_attributes – A list of attributes to return. If None, all attributes are returned.

Returns:

A dictionary of key/values

privacyidea.lib.user.get_internal_attributes(uid: str, resolver: str, realm_id: int) → dict[source]

Returns all internal attributes for the given user as a single dict.

privacyidea.lib.user.get_user_from_param(param: dict, optional_or_required: bool = True) → User[source]

Find the parameter user, realm and resolver and create a user object from these parameters.

An exception is raised, if a user in a realm is found in more than one resolver.

Parameters:
  • param – The dictionary of request parameters

  • optional_or_required – True (default) if the user param is optional, False if it is required (raises ParameterError when absent).

Returns:

User as found in the parameters

privacyidea.lib.user.get_user_list(param: dict | None = None, user: User | None = None, include_custom_attributes: bool = False, requested_attributes: list[str] | None = None, failures: list[str] | None = None, allowed_resolvers: dict[str, list[str]] | None = None, user_filter: Callable[[str, str, str | None], bool] | None = None) → list[dict][source]

This function returns a list of user dictionaries. The user dict contains the resolver and custom user attributes, if requested.

The realm parameter may be a single realm name, a comma-separated string of realm names, or a list of realm names (surrounding whitespace is ignored). Scoping by realm / resolver in param:

  • realm only: query every resolver in each given realm.

  • resolver only: query only that resolver, in every realm that contains it.

  • realm and resolver: query only that resolver, and only within each given realm. If the resolver is not part of a realm, that realm contributes no results.

  • neither: query every resolver in every realm.

An empty realm or resolver value is treated as if it were not supplied and therefore does not restrict the scope. When a user object is passed as well, its resolver narrows only the user’s own realm, not a separately requested realm.

The realm, resolver and editable keys are added on the lib layer and are only included in the returned user dictionaries when requested_attributes is None/empty or explicitly lists them.

A has_tokens entry in param keeps only the users that own a token, or only those that do not; an empty value does not filter. A revoked token does not count, as it can never be used again; a disabled one does. A token counts for the realm its owner was assigned in, not for the realms the token itself belongs to, so a user of a resolver shared by several realms can own a token in one of them and none in another. It is applied after the resolvers answered, because token ownership is privacyIDEA’s own record and no resolver knows about it. The filter needs the user id; it is added to requested_attributes when missing and stripped again afterwards, so it works independently of requested_attributes. A resolver whose user listing reports no user id - an advanced HTTP resolver whose attribute mapping does not map userid - leaves its users looking like they own no token, as there is nothing to match the token owners against.

Parameters:
  • param – search parameters

  • user – a specific user object to return

  • include_custom_attributes – Set to True, if you want to receive custom attributes of external users.

  • requested_attributes – A list of attributes to return for each user. If None or empty, all attributes are returned.

  • failures – optional list. When provided, the name of every resolver that could not be queried is appended once (deduplicated). This covers resolvers that raised ResolverError or ParameterError as well as resolvers that are assigned to a realm in scope but pinned to a different node and could therefore not be queried here. Callers that want to surface partial failures can pass an empty list and inspect it after the call.

  • allowed_resolvers – optional, the resolvers that may be listed in each realm, by realm name. A realm that is missing lists no user. The resolvers left out are not queried at all, so a user of one of them does not hide a user of the same login name in a resolver of lower priority, and they are not reported in failures either. None lists every resolver.

  • user_filter – optional, called with the realm, the resolver and the login name of each user a resolver returned, before the users are deduplicated. A user it returns False for is left out. None keeps every user.

Returns:

list of user info as dictionaries

privacyidea.lib.user.get_username(user_id: str, resolvername: str) → str[source]

Determine the username for a given id and a resolvername.

Parameters:
  • user_id (string) – The id of the user in a resolver

  • resolvername – The name of the resolver

Returns:

the username or “” if it does not exist

Return type:

string

privacyidea.lib.user.is_attribute_at_all() → bool[source]

Check if there are custom user attributes at all

privacyidea.lib.user.log_used_user(user: User, other_text: str = '') → str[source]

This creates a log message combined of a user and another text. The user information is only added, if user.login != user.used_login

Parameters:
  • user (User object) – A user to log

  • other_text – Some additional text

Returns:

str

privacyidea.lib.user.split_user(username: str) → tuple[str, str][source]

Split the username of the form user@realm into the username and the realm splitting myemail@emailprovider.com@realm is also possible and will return (myemail@emailprovider.com, realm).

If for a user@domain the “domain” does not exist as realm, the name is not split, since it might be the user@domain in the default realm

If the Split@Sign configuration is disabled, the username won’t be split and the username and an empty realm will be returned.

We can also split realmuser to (user, realm)

Parameters:

username (string) – the username to split

Returns:

username and realm

Return type:

tuple