= user()
:description: Returns an ECMUserAttributes object for a single user (mng.GetUserAttributes). Contains login, email, expiry date, and further profile fields.
:keywords: user, mng.GetUserAttributes, ECMUserAttributes, login, email, profile fields
:page-tags: api, security

Returns the detailed attributes of a single user account by username.
Unlike `users()`, this method returns complete account information including
login statistics, password expiry, and MFA configuration.

== Signature

[tabs]
====
Sync::
+
[source,python]
----
ecm.security.user(username: str) -> ECMUserAttributes | None
----

Async::
+
[source,python]
----
await ecm.security.user(username: str) -> ECMUserAttributes | None
----
====

== Parameters

[cols="1,1,3"]
|===
|Parameter |Default |Description

|`username`
|—
|Internal user name (e.g. `"ROOT"`). Not the GUID.
|===

== Return value

`ECMUserAttributes` instance, or `None` if the user was not found.

=== ECMUserAttributes fields

[cols="1,1,3"]
|===
|Field |Type |Description

|`id`
|`int`
|Numeric user ID.

|`username`
|`str`
|Short internal user name.

|`login_name`
|`str`
|Login credential name used for authentication.

|`display_name`
|`str`
|Full display name.

|`email`
|`str`
|E-mail address.

|`guid`
|`str`
|Globally unique identifier of the user account.

|`profile_id`
|`int`
|Profile ID: `-1` = no profile.

|`locked`
|`bool`
|`True` if the account is locked.

|`remark`
|`str`
|Optional remark.

|`account_type`
|`int`
|Account type identifier.

|`flags`
|`int`
|Bit-field of user flags.

|`lang_id`
|`int`
|Language ID of the user. `0` = server default.

|`login_count`
|`int`
|Number of times the user has logged in.

|`login_station`
|`str`
|Name of the station from the last login.

|`login_time`
|`datetime \| None`
|Timestamp of the last login. `None` if the user has never logged in.

|`last_modified`
|`datetime \| None`
|Timestamp of the last account modification.

|`mfa_flag`
|`int`
|Multi-factor authentication flag.

|`never_expire`
|`bool`
|`True` if the account never expires regardless of `valid_to`.

|`change_pwd`
|`bool`
|`True` if the user must change their password at next login.

|`pwd_changed`
|`datetime \| None`
|Timestamp of the last password change. `None` if the password has never been changed.

|`server_id`
|`int`
|ID of the home server for this account.

|`station`
|`str`
|Default station name assigned to the user.

|`supervisor_id`
|`int`
|User ID of the supervisor. `-1` if no supervisor is assigned.

|`valid_from`
|`datetime \| None`
|Account valid-from date.

|`valid_to`
|`datetime \| None`
|Account valid-to date.
|===

== Examples

=== Load a user and inspect attributes

[tabs]
====
Sync::
+
[source,python]
----
user = ecm.security.user("john")
if user:
    print(user.display_name, user.email, user.guid)
    print(f"Last login: {user.login_time}")
    print(f"Login count: {user.login_count}")
    if user.locked:
        print("Account is locked")
----

Async::
+
[source,python]
----
user = await ecm.security.user("john")
if user:
    print(user.display_name, user.email, user.guid)
    print(f"Last login: {user.login_time}")
----
====

=== Resolve GUID for user_groups()

[tabs]
====
Sync::
+
[source,python]
----
user = ecm.security.user("john")
if user:
    groups = ecm.security.user_groups(user.guid)
    print([g.name for g in groups])
----

Async::
+
[source,python]
----
user = await ecm.security.user("john")
if user:
    groups = await ecm.security.user_groups(user.guid)
    print([g.name for g in groups])
----
====

== See also

* xref:api/security/users.adoc[users()] — Retrieve all user accounts
* xref:api/security/roles.adoc[roles()] — System roles of a user
* xref:api/security/user_groups.adoc[user_groups()] — Groups of a user
