PhoenixKit.Users.Roles (phoenix_kit v1.7.71)

Copy Markdown View Source

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{}]

Summary

Functions

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

Checks if user can be deactivated safely.

Counts active users with Owner role.

Counts users with a specific role.

Creates a new role.

Deletes a role safely.

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

Safely assigns Owner role to first user using database transaction.

Gets only custom (non-system) roles.

Gets comprehensive user statistics including activity and confirmation status.

Gets a role by its name.

Gets a single role by its UUID.

Gets role statistics for dashboard display.

Gets all active roles for a user.

Lists all roles.

Promotes a user to admin role.

Removes a role from a user by deleting the assignment.

Safely removes role with Owner protection.

Synchronizes user roles with a given list of role names.

Updates a role.

Checks if a user has a specific role.

Checks if a user has an "Admin" role.

Checks if a user has an "Owner" role.

Gets all users who have a specific role.

Functions

assign_role(user, role_name, assigned_by \\ nil, opts \\ [])

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(opts \\ [])

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?(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(role_name)

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(attrs \\ %{})

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(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(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(user)

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(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(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(user)

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(user, assigned_by \\ nil)

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(user, role_name, opts \\ [])

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(user, role_name)

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(user, role_names)

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(role, attrs)

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?(user, role_name)

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?(user)

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?(user)

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(role_name)

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")
[]