# `PhoenixKit.Users.Auth.Scope`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.164/lib/phoenix_kit/users/auth/scope.ex#L1)

Scope module for encapsulating PhoenixKit authentication state.

This module provides a structured way to handle user authentication context
throughout your Phoenix application, similar to Phoenix's built-in authentication
patterns but with PhoenixKit prefixing to avoid conflicts.

## Usage

    # Create scope for authenticated user
    scope = Scope.for_user(user)

    # Create scope for anonymous user
    scope = Scope.for_user(nil)

    # Check authentication status
    Scope.authenticated?(scope)  # true or false

    # Get user information
    Scope.user(scope)        # %User{} or nil
    Scope.user_uuid(scope)   # user.uuid or nil
    Scope.user_email(scope)  # user.email or nil

## Role & State Checks

    Scope.has_role?(scope, "Admin")  # true/false
    Scope.owner?(scope)             # Owner role?
    Scope.admin?(scope)             # Owner, Admin, or custom role with permissions?
    Scope.system_role?(scope)       # Strictly Owner or Admin (not custom roles)?
    Scope.anonymous?(scope)         # Not authenticated?
    Scope.user_roles(scope)         # ["Admin", "User"]
    Scope.user_full_name(scope)     # "John Doe" or nil
    Scope.user_active?(scope)       # true/false
    Scope.to_map(scope)             # Debug-friendly map of all fields

## Module-Level Permissions

Permissions are cached in the scope when it is built via `for_user/1`
(on mount and on PubSub-triggered refresh). Owner gets all 25 keys
automatically. Admin with no explicit permissions gets full access
(backward compat before V53 migration).

    Scope.has_module_access?(scope, "billing")          # Single key check
    Scope.has_any_module_access?(scope, ["billing", "shop"])  # Any of these?
    Scope.has_all_module_access?(scope, ["billing", "shop"])  # All of these?
    Scope.accessible_modules(scope)                     # MapSet of granted keys
    Scope.permission_count(scope)                       # Number of granted keys

## Struct Fields

- `:user` - The current user struct or nil
- `:authenticated?` - Boolean indicating if user is authenticated
- `:cached_roles` - List of role name strings, loaded at scope creation
- `:cached_permissions` - MapSet of granted permission keys, loaded at scope creation

# `t`

```elixir
@type t() :: %PhoenixKit.Users.Auth.Scope{
  authenticated?: boolean(),
  cached_permissions: MapSet.t() | nil,
  cached_roles: [String.t()] | nil,
  multi_session_accounts: list(),
  multi_session_allowed?: boolean(),
  user: PhoenixKit.Users.Auth.User.t() | nil
}
```

# `accessible_modules`

```elixir
@spec accessible_modules(t()) :: MapSet.t()
```

Returns the set of module keys the user can access.

# `admin?`

```elixir
@spec admin?(t()) :: boolean()
```

Checks if the user can access the admin panel.

Returns true when the user holds the Admin or Owner role, OR has been
explicitly granted any module-level permissions (via `RolePermission`).
This allows custom roles (e.g. "Editor", "Support") to access the admin
panel when they've been granted at least one permission.

Per-page access is enforced separately by `has_module_access?/2`.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.admin?(scope)
    true

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.admin?(scope)
    false

# `anonymous?`

```elixir
@spec anonymous?(t()) :: boolean()
```

Checks if the scope represents an anonymous (non-authenticated) user.

## Examples

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.anonymous?(scope)
    true

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.anonymous?(scope)
    false

# `authenticated?`

```elixir
@spec authenticated?(t()) :: boolean()
```

Checks if the scope represents an authenticated user.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.authenticated?(scope)
    true

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.authenticated?(scope)
    false

# `for_user`

```elixir
@spec for_user(PhoenixKit.Users.Auth.User.t() | nil) :: t()
```

Creates a new scope for the given user.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001", email: "user@example.com"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> scope.authenticated?
    true
    iex> scope.user.email
    "user@example.com"

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> scope.authenticated?
    false
    iex> scope.user
    nil

# `has_all_module_access?`

```elixir
@spec has_all_module_access?(t(), [String.t()]) :: boolean()
```

Checks if the user has access to all of the given module keys.

## Examples

    Scope.has_all_module_access?(scope, ["billing", "shop"])

# `has_any_module_access?`

```elixir
@spec has_any_module_access?(t(), [String.t()]) :: boolean()
```

Checks if the user has access to at least one of the given module keys.

## Examples

    Scope.has_any_module_access?(scope, ["billing", "shop"])

# `has_module_access?`

```elixir
@spec has_module_access?(t(), String.t()) :: boolean()
```

Checks if the user has access to a specific admin module/section.

Looks up `module_key` in `cached_permissions`. Owner access works because
`for_user/1` pre-populates all keys for owners; this function itself does
not special-case roles.

# `has_role?`

```elixir
@spec has_role?(t(), String.t()) :: boolean()
```

Checks if the user has a specific role.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.has_role?(scope, "Admin")
    true

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.has_role?(scope, "Admin")
    false

# `owner?`

```elixir
@spec owner?(t()) :: boolean()
```

Checks if the user is an owner.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.owner?(scope)
    true

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.owner?(scope)
    false

# `permission_count`

```elixir
@spec permission_count(t()) :: non_neg_integer()
```

Returns the number of module permissions the user has been granted.

# `system_role?`

```elixir
@spec system_role?(t()) :: boolean()
```

Checks if the user holds the Owner or Admin system role.

Unlike `admin?/1` which also returns true for custom roles with permissions,
this strictly checks for the two built-in system roles.

# `to_map`

```elixir
@spec to_map(t()) :: map()
```

Converts scope to a map for debugging or logging purposes.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001", email: "user@example.com"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.to_map(scope)
    %{
      authenticated?: true,
      user_uuid: "019...",
      user_email: "user@example.com",
      user_roles: ["Admin", "User"],
      owner?: false,
      admin?: true
    }

# `user`

```elixir
@spec user(t()) :: PhoenixKit.Users.Auth.User.t() | nil
```

Gets the user from the scope.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001", email: "user@example.com"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.user(scope)
    %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001", email: "user@example.com"}

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.user(scope)
    nil

# `user_active?`

```elixir
@spec user_active?(t()) :: boolean()
```

Checks if the user is active.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{is_active: true}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.user_active?(scope)
    true

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.user_active?(scope)
    false

# `user_email`

```elixir
@spec user_email(t()) :: String.t() | nil
```

Gets the user email from the scope.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001", email: "user@example.com"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.user_email(scope)
    "user@example.com"

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.user_email(scope)
    nil

# `user_full_name`

```elixir
@spec user_full_name(t()) :: String.t() | nil
```

Gets the user's full name.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{first_name: "John", last_name: "Doe"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.user_full_name(scope)
    "John Doe"

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.user_full_name(scope)
    nil

# `user_roles`

```elixir
@spec user_roles(t()) :: [String.t()]
```

Gets all roles for the user.

## Examples

    iex> user = %PhoenixKit.Users.Auth.User{uuid: "0193a5e4-0000-7000-8000-000000000001"}
    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.user_roles(scope)
    ["Admin", "User"]

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.user_roles(scope)
    []

# `user_uuid`

```elixir
@spec user_uuid(t()) :: String.t() | nil
```

Gets the user ID (UUID) from the scope.

## Examples

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(user)
    iex> PhoenixKit.Users.Auth.Scope.user_uuid(scope)
    "0193a5e4-..."

    iex> scope = PhoenixKit.Users.Auth.Scope.for_user(nil)
    iex> PhoenixKit.Users.Auth.Scope.user_uuid(scope)
    nil

---

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