Select your Platform:
Client SDKs
Backend SDKs
Multi-Tenant & Teams
Confused about "Multi-Tenant & Teams"?
Let us know how we can improve our documentation:
Many apps that add chat have customers of their own. If you're building something like Slack, or a SaaS application like Invision you want to make sure that one customer can't read the messages of another customer. Stream Chat can be configured in multi-tenant mode so that users are organized in separated teams that cannot interact with each other.
Teams
Copied!Confused about "Teams"?
Let us know how we can improve our documentation:
Stream Chat has the concept of teams for users and channels. The purpose of teams is to provide a simple way to separate different groups of users and channels within a single application.
If a user belongs to a team, the API will ensure that such user will only be able to connect to channels from the same team. Features such as user search can be configured so that a user can only search for users from the same team.
When enabling multi-tenant mode all user requests will always ensure that the request applies to a team the user belongs to. For instance, if a user from team "blue" tries to delete a message that was created on a channel from team "red" the API will return an error.
Enable Teams for your application
Copied!Confused about "Enable Teams for your application"?
Let us know how we can improve our documentation:
In order to use Teams, your application must have multi-tenant mode enabled. You can ensure your app is in multi-tenant mode by calling the Application Settings endpoint.
1
2
3
4
5
6
const client = new StreamChat('YOUR_API_KEY', 'YOUR_API_SECRET');
// switch your application to v2 permissions
await client.updateAppSettings({
multi_tenant_enabled: true,
});
User teams
Copied!When using teams, users must be created from your back-end and specify which teams they are a member of. (Note this is only allowed server side)
1
2
// creates or updates a user from backend to be part of the "red" and "blue" teams
client.updateUser({id, teams: ["red", "blue"]});
Channel team
Copied!Channels can be associated with a team. Users can create channels client-side but if their user is part of a team, they will have to specify a team or the request will be rejected with an error.
1
2
// Creates the channel red-general for team red
client.channel("messaging", "red-general", {team: "red"}).create()
1
2
3
4
5
6
7
8
9
10
// Creates the red-general channel for the red team
Map<String, Object> extraData = new HashMap<>();
extraData.put("team", "red");
client.createChannel("messaging", "red-general", extraData).enqueue(result -> {
if (result.isSuccess()) {
Channel channel = result.data();
} else {
// Handle result.error()
}
});
1
2
3
4
5
6
7
8
9
10
11
12
// Creates the red-general channel for the red team
client.createChannel(
channelType = "messaging",
channelId = "red-general",
extraData = mapOf("team" to "red")
).enqueue { result ->
if (result.isSuccess) {
val channel = result.data()
} else {
// Handle result.error()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import StreamChat
/// 1: Create a `ChannelId` that represents the channel you want to create.
let channelId = ChannelId(type: .messaging, id: "general")
/// 2: Use the `ChatClient` to create a `ChatChannelController` with the `ChannelId`.
let channelController = try chatClient.channelController(
createChannelWithId: channelId,
name: "Channel Name",
imageURL: nil,
team: "red",
extraData: .defaultValue
)
/// 3: Call `ChatChannelController.synchronize` to create the channel.
channelController.synchronize { error in
if let error = error {
/// 4: Handle possible errors
print(error)
}
}
User Search
Copied!Confused about "User Search "?
Let us know how we can improve our documentation:
By default the user search endpoint allows users to search for any other user, applications in multi-tenant mode are required to specify a team filter when performing user searches client-side.
Because users can belong to multiple teams, you need to use the $contains
operator for this match.
1
2
3
4
5
6
7
// search for users with name Jordan that are part of the red team
client.queryUsers({
$and: [
{ name: { $eq: "Jordan" } },
{ teams: { $contains: "red" } }
],
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import StreamChat
let controller = chatClient.userListController(
query: .init(filter: .in("teams", values: ["blue"]))
)
controller.synchronize { error in
if let error = error {
// handle error
print(error)
} else {
// access users
print(controller.users)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Search for users with the name Jordan that are part of the red team
FilterObject filter = Filters.and(
Filters.eq("name", "Jordan"),
Filters.eq("teams", Filters.contains("red"))
);
int offset = 0;
int limit = 1;
client.queryUsers(new QueryUsersRequest(filter, offset, limit)).enqueue(result -> {
if (result.isSuccess()) {
List<User> users = result.data();
} else {
// Handle result.error()
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
// Search for users with the name Jordan that are part of the red team
val filter = Filters.and(
Filters.eq("name", "Jordan"),
Filters.eq("teams", Filters.contains("red"))
)
client.queryUsers(QueryUsersRequest(filter, offset = 0, limit = 1)).enqueue { result ->
if (result.isSuccess) {
val users: List<User> = result.data()
} else {
// Handle result.error()
}
}
Query Channels
Copied!Confused about "Query Channels "?
Let us know how we can improve our documentation:
When using multi-tenant, the query channels endpoint will only return channels that match the query and are on the same team as the user. This happens automatically on Stream Chat side and cannot be circumvented by users.
Server-side you can use query channels to get channels from any team and you can filter them using the team field as well.
1
2
3
// server-side you can query channels from any team
const otherFilters = {};
client.queryChannels({team: "red-team", ...otherFilters}, sort, options);