# `PhoenixKit.Users.Roles`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.87/lib/phoenix_kit/users/roles.ex#L1)

API for managing user roles in PhoenixKit.

This module provides functions for assigning, removing, and querying user roles.
It works with the role system to provide authorization capabilities.

## Role Management

- Assign and remove roles from users
- Query users by role
- Check user permissions
- Bulk role operations

## System Roles

PhoenixKit includes three built-in system roles:

- **Owner**: System owner with full access (assigned automatically to first user)
- **Admin**: Administrator with elevated privileges
- **User**: Standard user with basic access (default for new users)

## Examples

    # Check if user has a role
    iex> user_has_role?(user, "Admin")
    true

    # Get all user roles
    iex> get_user_roles(user)
    ["Admin", "User"]

    # Assign a role to user
    iex> assign_role(user, "Admin")
    {:ok, %RoleAssignment{}}

    # Get all users with a specific role
    iex> users_with_role("Admin")
    [%User{}, %User{}]

# `assign_role`

Assigns a role to a user.

## Security

The Owner role cannot be assigned through this function to maintain system security.
Only one Owner is automatically assigned during initialization.

## Parameters

- `user`: The user to assign the role to
- `role_name`: The name of the role to assign
- `assigned_by` (optional): The user who is assigning the role

## Examples

    iex> assign_role(user, "Admin")
    {:ok, %RoleAssignment{}}

    iex> assign_role(user, "Admin", assigned_by_user)
    {:ok, %RoleAssignment{}}

    iex> assign_role(user, "Owner")
    {:error, :owner_role_protected}

    iex> assign_role(user, "NonexistentRole")
    {:error, :role_not_found}

# `assign_roles_to_existing_users`

Assigns roles to existing users who don't have any PhoenixKit roles.

This is useful for migration scenarios where PhoenixKit is installed
into an existing application with users.

## Parameters

- `opts`: Options for role assignment
  - `:make_first_owner` (default: true) - Make first user without roles an Owner

## Returns

- `{:ok, stats}` with assignment statistics
- `{:error, reason}` on failure

## Examples

    iex> assign_roles_to_existing_users()
    {:ok, %{assigned_owner: 1, assigned_users: 5, total_processed: 6}}

# `can_deactivate_user?`

Checks if user can be deactivated safely.

Prevents deactivation of last active Owner.

## Parameters

- `user`: User to check for deactivation

## Examples

    iex> can_deactivate_user?(last_owner)
    {:error, :cannot_deactivate_last_owner}

    iex> can_deactivate_user?(regular_user)
    :ok

# `count_active_owners`

Counts active users with Owner role.

Critical security function - ensures we never have zero owners.

## Examples

    iex> count_active_owners()
    1

# `count_users_with_role`

Counts users with a specific role.

## Parameters

- `role_name`: The name of the role to count

## Examples

    iex> count_users_with_role("Admin")
    3

# `create_role`

Creates a new role.

## Parameters

- `attrs`: Attributes for the new role

## Examples

    iex> create_role(%{name: "Manager", description: "Department manager"})
    {:ok, %Role{}}

    iex> create_role(%{name: ""})
    {:error, %Ecto.Changeset{}}

# `delete_role`

Deletes a role safely.

Prevents deletion of system roles and roles currently assigned to users.

## Parameters

- `role`: The role to delete

## Examples

    iex> delete_role(custom_role)
    {:ok, %Role{}}

    iex> delete_role(system_role)
    {:error, :system_role_protected}

    iex> delete_role(role_with_users)
    {:error, :role_in_use}

# `demote_to_user`

Safely demotes a user from Admin or Owner role with protection.

Prevents demotion of last Owner to maintain system security.

## Parameters

- `user`: The user to demote

## Examples

    iex> demote_to_user(admin_user)
    {:ok, %RoleAssignment{}}

    iex> demote_to_user(last_owner)
    {:error, :cannot_demote_last_owner}

# `ensure_first_user_is_owner`

Safely assigns Owner role to first user using database transaction.

This function prevents race conditions by using FOR UPDATE lock.

## Parameters

- `user`: The user to potentially make Owner

## Returns

- `{:ok, :owner}` if user became Owner
- `{:ok, :user}` if user became regular User
- `{:error, reason}` on failure

## Examples

    iex> ensure_first_user_is_owner(user)
    {:ok, :owner}

# `get_custom_roles`

Gets only custom (non-system) roles.

## Examples

    iex> get_custom_roles()
    [%Role{name: "Manager"}, %Role{name: "Editor"}]

# `get_extended_stats`

Gets comprehensive user statistics including activity and confirmation status.

## Examples

    iex> get_extended_stats()
    %{
      total_users: 10,
      owner_count: 1,
      admin_count: 2,
      user_count: 7,
      active_users: 8,
      inactive_users: 2,
      confirmed_users: 9,
      pending_users: 1
    }

# `get_role_by_name`

Gets a role by its name.

## Parameters

- `name`: The name of the role

## Examples

    iex> get_role_by_name("Admin")
    %Role{name: "Admin"}

    iex> get_role_by_name("NonexistentRole")
    nil

# `get_role_by_uuid`

Gets a single role by its UUID.

Returns `nil` if no role is found.

## Parameters

- `uuid`: The UUID of the role to find

## Examples

    iex> get_role_by_uuid("01234567-89ab-cdef-0123-456789abcdef")
    %Role{uuid: "01234567-89ab-cdef-0123-456789abcdef", name: "Editor"}

    iex> get_role_by_uuid("nonexistent-uuid")
    nil

# `get_role_stats`

Gets role statistics for dashboard display.

## Examples

    iex> get_role_stats()
    %{
      total_users: 10,
      owner_count: 1,
      admin_count: 2,
      user_count: 7
    }

# `get_user_roles`

Gets all active roles for a user.

## Parameters

- `user`: The user to get roles for

## Examples

    iex> get_user_roles(user)
    ["Admin", "User"]

    iex> get_user_roles(user_with_no_roles)
    []

# `list_roles`

Lists all roles.

## Examples

    iex> list_roles()
    [%Role{}, %Role{}, %Role{}]

# `promote_to_admin`

Promotes a user to admin role.

## Parameters

- `user`: The user to promote
- `assigned_by` (optional): The user who is doing the promotion

## Examples

    iex> promote_to_admin(user)
    {:ok, %RoleAssignment{}}

# `remove_role`

Removes a role from a user by deleting the assignment.

## Parameters

- `user`: The user to remove the role from
- `role_name`: The name of the role to remove

## Examples

    iex> remove_role(user, "Admin")
    {:ok, %RoleAssignment{}}

    iex> remove_role(user, "NonexistentRole")
    {:error, :assignment_not_found}

# `safely_remove_role`

Safely removes role with Owner protection.

Prevents removal of Owner role if it would leave system without owners.

## Parameters

- `user`: User to remove role from
- `role_name`: Name of role to remove

## Examples

    iex> safely_remove_role(owner_user, "Owner")
    {:error, :cannot_remove_last_owner}

    iex> safely_remove_role(admin_user, "Admin")
    {:ok, %RoleAssignment{}}

# `sync_user_roles`

Synchronizes user roles with a given list of role names.

This function ensures the user has exactly the specified roles.

## Parameters

- `user`: The user to synchronize roles for
- `role_names`: List of role names the user should have

## Examples

    iex> sync_user_roles(user, ["Admin", "Manager"])
    {:ok, [%RoleAssignment{}, %RoleAssignment{}]}

# `update_role`

Updates a role.

## Parameters

- `role`: The role to update
- `attrs`: Attributes to update

## Examples

    iex> update_role(role, %{description: "Updated description"})
    {:ok, %Role{}}

    iex> update_role(system_role, %{name: "NewName"})
    {:error, %Ecto.Changeset{}}

# `user_has_role?`

Checks if a user has a specific role.

## Parameters

- `user`: The user to check
- `role_name`: The name of the role to check for

## Examples

    iex> user_has_role?(user, "Admin")
    true

    iex> user_has_role?(user, "Owner")
    false

# `user_has_role_admin?`

Checks if a user has an "Admin" role.

## Parameters

- `user`: The user to check

## Examples

    iex> user_has_role_admin?(user)
    true

# `user_has_role_owner?`

Checks if a user has an "Owner" role.

## Parameters

- `user`: The user to check

## Examples

    iex> user_has_role_owner?(user)
    true

# `users_with_role`

Gets all users who have a specific role.

## Parameters

- `role_name`: The name of the role to search for

## Examples

    iex> users_with_role("Admin")
    [%User{}, %User{}]

    iex> users_with_role("NonexistentRole")
    []

---

*Consult [api-reference.md](api-reference.md) for complete listing*
