> ## Documentation Index
> Fetch the complete documentation index at: https://learn.social.plus/llms.txt
> Use this file to discover all available pages before exploring further.

# Roles & Permissions

> Check whether the current user can perform protected actions with social.plus SDK permission APIs.

Use `hasPermission` to decide whether the current user should see or perform protected actions such as deleting messages, editing community posts, or banning users. Permission checks are scope-aware: some checks are global, while others are evaluated for a channel or community.

<Info>
  Permissions are assigned through roles and membership state. The SDK checks the permissions already available for the current user and returns a Boolean-style result.
</Info>

## Parameters

| Operation                  | Required inputs                    | Optional inputs | Platforms                         | Result shape                          |
| -------------------------- | ---------------------------------- | --------------- | --------------------------------- | ------------------------------------- |
| Check global permission    | Permission constant                | None            | TypeScript, iOS, Android, Flutter | Boolean or observable Boolean result. |
| Check channel permission   | Permission constant, `channelId`   | None            | TypeScript, iOS, Android, Flutter | Boolean or observable Boolean result. |
| Check community permission | Permission constant, `communityId` | None            | TypeScript, iOS, Android, Flutter | Boolean or observable Boolean result. |

## Check a permission

Use the scope that matches the action you are gating. For example, message deletion inside a channel should use a channel-scoped permission check, while community post editing should use a community-scoped check.

### Inputs

| Platform   | Method                                                                                                                  | Required inputs                      | Result shape                       |
| ---------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ---------------------------------- |
| TypeScript | `client.hasPermission(permission).currentUser()`, `.channel(channelId)`, or `.community(communityId)`                   | Permission string, optional scope ID | Returns `boolean`.                 |
| iOS        | `client.hasPermission(permission)`, `forChannel:`, or `forCommunity:`                                                   | `AmityPermission`, optional scope ID | Returns `Bool` from an async call. |
| Android    | `AmityCoreClient.hasPermission(permission).atGlobal()`, `.atChannel(channelId)`, or `.atCommunity(communityId).check()` | `AmityPermission`, optional scope ID | Returns `Flowable<Boolean>`.       |
| Flutter    | `AmityCoreClient.hasPermission(permission).atGlobal()`, `.atChannel(channelId)`, or `.atCommunity(communityId).check()` | `AmityPermission`, optional scope ID | Returns `bool`.                    |

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Client } from '@amityco/ts-sdk';

  const client = Client.createClient('your-api-key', 'sg');

  const canEditCommunityPost = client
    .hasPermission('EDIT_COMMUNITY_POST')
    .community('community_123');

  if (canEditCommunityPost) {
    // Enable edit controls.
  }
  ```

  ```swift iOS theme={null}
  Task { @MainActor in
      let canDeleteMessage = await client.hasPermission(
          .deleteMessage,
          forChannel: "channel_123"
      )

      if canDeleteMessage {
          // Enable delete controls.
      }
  }
  ```

  ```kotlin Android theme={null}
  fun checkChannelPermission() {
      AmityCoreClient.hasPermission(AmityPermission.DELETE_MESSAGE)
          .atChannel("channel_123")
          .check()
          .doOnNext { canDeleteMessage: Boolean ->
              if (canDeleteMessage) {
                  // Enable delete controls.
              }
          }
          .subscribe()
  }
  ```

  ```dart Flutter theme={null}
  void checkChannelPermission(String channelId) {
    final canMute = AmityCoreClient
        .hasPermission(AmityPermission.MUTE_USER_INSIDE_CHANNEL)
        .atChannel(channelId)
        .check();

    if (canMute) {
      // Enable mute controls.
    }
  }
  ```
</CodeGroup>

## Platform notes

* TypeScript permission checks are synchronous Boolean checks against current cached user, channel membership, or community membership data.
* iOS permission checks are async and return `Bool`.
* Android permission checks return `Flowable<Boolean>`.
* Flutter permission checks return `bool`.
* Use the permission constant that matches the action and scope. Permission names differ by platform enum casing, but they map to server permission strings such as `DELETE_MESSAGE`, `EDIT_COMMUNITY_POST`, and `BAN_USER`.

## Related topics

<CardGroup cols={2}>
  <Card title="User Identity" href="./user-identity" icon="id-card">
    Understand the stable `userId` used by permission checks.
  </Card>

  <Card title="Flag and Unflag Users" href="./user-operations/flag-unflag-user" icon="flag">
    Add user reporting actions for moderation workflows.
  </Card>
</CardGroup>
