NEW - BETA User Permissions
Confused about "NEW - BETA User Permissions"?
Let us know how we can improve our documentation:
Stream Chat ships with a configurable permission systems that allows you to control with fine grain what users are allowed to do on your chat application.
User permissions are organised as lists of permissions policies. Your chat application and channel types all have their own permission policies that you can adjust.
Application level permissions
Copied!Confused about "Application level permissions"?
Let us know how we can improve our documentation:
These permissions allow you to control access to functionality that is common to all channel types such as: user search and user management. By default Stream chat allows you any user to search users, for users to change their own data and forbids any user from changing the role for any user.
Channel types permissions
Copied!Confused about "Channel types permissions"?
Let us know how we can improve our documentation:
Channel types allow you to support channels with different use cases within a single Chat application. Each channel type can have its own set of features as well as its own set of permissions.
Every time the user performs a request that is channel-specific (ie. send a message) the permission policies for that channel's type will be used.
Permission checking
Copied!Confused about "Permission checking"?
Let us know how we can improve our documentation:
Before we dive into more detail on how a permission policy is structured, let's explain how permission checking works in general.
Retrieve the list of policies for the channel type
Iterate over the list of policies, order is based on priority (highest first)
Check if the policy matches the current request
If there is a match then the policy will decide if the request should continue or be rejected
If there is not match, move to the next in list
Let's also introduce an example of how a list of permissions policies would look like:
Admin users can perform any action
Anonymous users are not allowed
Users can modify their own messages
Users can create channels
Members of a channel can read and send messages
Anything not matching the previous list should not be allowed
Let's now see how this would play out and introduce a couple of users: Tommaso and Thierry. Tommaso is an admin and Thierry a user. Thierry is also a member of the "Sailing" channel.
Thierry posts a message on channel "soccer"
Tommaso edits a message from Thierry
Thierry creates a channel called "founders"
An anonymous user opens the "Sailing" channel
Here's what the outcome of these requests would be:
🙅♂️ Only the last policy matches and it denies this action
👌 Tommaso is an admin, 1st policy is a match
👌 Thierry is a user, 4th policy is a match
🙅♂️ Anonymous users are discarded
Permission Policy
Copied!Confused about "Permission Policy"?
Let us know how we can improve our documentation:
Now that we have a better idea about how the permission system works, let's define more precisely the structure of a permission policy.
Name | Internal Name | Description | Example |
---|---|---|---|
Name | name | The name of the policy, this serves as a human readable placeholder to remember the policy is all about | "Channel Member Permissions" |
Resources | resources | The list of resources this policy applies. This field cannot be empty but you can set it to | ["ReadChannel", "SendMessage"] |
Roles | roles | The list of roles this policy applies. Same as the resources field, this must not be empty and can be set to | ["channel_member"] |
Owner | owner | This is an optional field that you can use to match actions performed on objects that the user owns. Ownership only applies to some resources like messages and channels. When set to true the policy will only match if the user is owner of the resource part for the request (when applicable). | true |
Condition | condition | A condition allows you to express a more complex matching logic. This field can be left blank, in that case it will not have any impact. When present, the expression will be evaluated and must return either true, false or null. More information on this is available later. | - |
Action | action | The action to perform if the policy matches on resource, role and ownership. This field can either be set to 0 or to 1 where 0 stands to Deny and 1 for Allow. | 0 |
Priority | priority | The priority field defined the position of the policy in the list. Permission policies are evaluated in consistent order from the highest priority to the lowest. | 99 |
Example list
Copied!Confused about "Example list"?
Let us know how we can improve our documentation:
Let's now write the example from before into a list of real policies.
Name | Resources | Roles | Owner | action | priority |
---|---|---|---|---|---|
Admin users can perform any action | ["*"] | ["admin"] | - | 1 (Allow) | 600 |
Anonymous users are not allowed | ["*"] | ["anonymous"] | - | 0 (Deny) | 500 |
Users can modify their own messages | ["UpdateMessage"] | ["user"] | true | 1 (Allow) | 400 |
Users can create channels | ["CreateChannel"] | ["user"] | - | 1 (Allow) | 300 |
Members of a channel can read and send messages | ["ReadChannel", "CreateMessage"] | ["channel_member"] | - | 1 (Allow) | 200 |
Anything not matching the previous list should not be allowed | ["*"] | ["*"] | - | 0 (Deny) | 100 |
Permission Policy Conditions
Copied!Confused about "Permission Policy Conditions"?
Let us know how we can improve our documentation:
Conditions allow you to extend the permission logic to support more advanced use-cases such as user groups, teams and more in general, to create permission policies that take into account the objects involved the API call.
Conditions are expressions that you can write using a syntax close to MongoDB's queries; the same syntax is also used to perform channel and user queries so that you don't need to learn yet another DSL.
Conditions are logical expressions that return true or false. If the expression returns true then the policy will be matched (assuming that the rest of policy matches as well) otherwise the policy will be ignored. Variables such as the current user and channel are available in scope and can be used in the condition.
Examples
Copied!Confused about "Examples"?
Let us know how we can improve our documentation:
user.team and channel.team are the same
user is a member or channel.public is true
Scope
Copied!Confused about "Scope"?
Let us know how we can improve our documentation:
This the list of objects that are provided in scope. Any variable that is not defined in scope will be set to a special value called "undefined". An undefined variable is only equal to the undefined
variable and will have any property return undefined, the same applies for any missing property for an object. (ie. user.missingField
is undefined as well as user.missingField.yetAnother
)
This are the variable in scope, any field (custom or not is available as well including nested ones)
$user the user performing the request
$channel the channel that's part of the request
$message the message data
$channelRole the role for the user in the channel
$otherUser the other user involved in the request
$event the event the user is sending
Operators
Copied!Confused about "Operators"?
Let us know how we can improve our documentation:
Expressions can be simple equality checks or chains of multiple checks.
$eq equality check
$neq dis-equality check
$not logical negation
$and logical and operator
$or logical or operator
$in membership check
Errors
Copied!Confused about "Errors"?
Let us know how we can improve our documentation:
Permission policies cannot produce errors, syntax is required to be valid before saving them and because of the way scope is managed (see undefined in the scope section) you can expect conditions will always have a consistent outcome and will never error.
Examples (TODO - not sure about this yet )
Copied!Confused about "Examples (TODO - not sure about this yet )"?
Let us know how we can improve our documentation:
Team / Multi-tenant policy
Copied!Confused about "Team / Multi-tenant policy"?
Let us know how we can improve our documentation:
1
2
3
{
"$user.team":"$channel.team"
}
Match a event type
This is an example on how you can create a policy that applies to events with type set to the custom value "join".
1
2
3
{
"$event.type":"join"
}
Open for members or public
This is a more complex example policy that
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"$or":[
{
"$and":[
{
"$channelRole":"channel_member"
},
{
"$channel.private":true
}
]
},
{
"$in":{
"$channel.private":[
"undefined",
false
]
}
}
]
}