From c9db2ce821af299d8a3a2f9195c0220b04ef27e6 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Fri, 26 Apr 2024 11:04:44 +0200 Subject: [PATCH 1/4] Add multi-tenant guide to video docs --- .../docs/api/basics/multi-tenant.mdx | 189 ++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx diff --git a/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx b/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx new file mode 100644 index 00000000..9ac05bd1 --- /dev/null +++ b/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx @@ -0,0 +1,189 @@ +--- +id: multi-tenant +sidebar_position: 4 +slug: /multi-tenant +title: Multi-Tenant & Teams +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Stream Video can be configured for teams/multi-tenant operation, allowing users to be organized into distinct, isolated teams. This configuration is essential for applications like Zoom or Disqus, where it's crucial that users within one team remain completely separated from others to ensure privacy and security. + +## Teams + +Stream Video has the concept of teams for users and calls. The purpose of teams is to provide a simple way to separate different groups of users and calls 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 calls from the same team. Features such as user search are limited so that a user can only search for users from the same team by default. + +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. If user doesn't have team set, it will only have access to users and channels that don't have team. + +## Enable Teams for your application + +In order to use Teams, your application must have multi-tenant mode enabled. You can enable multi-tenant from the dashboard (Overview screen). + +## User teams + +When multi-tenant is enabled, users can only be created from your back-end. This is necessary to ensure that a user cannot pick its own team/tenant. + + + + +```js +client.upsertUsers({ + users: { + ['']: { + id: '', + name: 'Sara', + teams: ['red', 'blue'], + }, + }, +}); +``` + + + + +```py +client.upsert_users( + UserRequest(id=user_id, teams=["red", "blue"]) +) +``` + + + + +A user can be a member of up to 250 teams, a team name can be up to 100 characters. There is **no limit** to how many teams your application can have. + +## Call team + +Calls can be associated with a team. Users can create calls 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. + + + + +```js +client.call('default', 'red-team-weekly').create({ + data: { team: 'red', created_by_id: '' }, +}); +``` + + + + +```py +call = client.video.call("default", call_id) + +response = call.create( + data=CallRequest( + created_by_id=user_id, + team="blue", + ) +) +``` + + + + +Call teams allow you to ensure proper permission checking for a multi tenant application. Keep in mind that you will still need to enforce that call IDs are unique. +There are two common way to address this: generate random IDs using a random UUID, prefix the team name to the id of the call. + +## User search + +By default client-side user search will only return results from teams that authenticated user is a part of. API injects filter `{team: {$in: []}}` for every request that doesn't already contain filter for teams field. If you want to query users from all teams, you have to provide empty filter like this: `{teams:{}}`. + +For server-side requests, this filter does not apply and you can search as usual and also filter by teams. + + + + +```js +// search for users by name and team +client.queryUsers({ + filter_conditions: { + name: 'Nick', + teams: { $in: ['red', 'blue'] }, + }, +}); + +// search for users that are not part of any team +client.queryUsers({ + filter_conditions: { + name: 'Tom', + teams: null, + }, +}); +``` + + + + +```py +# search for users by name and team +response = client.query_users( + QueryUsersPayload( + filter_conditions={ + "name": {"$eq": "Nick"}, + "teams": {"$in": ["red", "blue"]}, + } + ) +) + +# search for users that are not part of any team +response = client.query_users( + QueryUsersPayload( + filter_conditions={ + "teams": None, + } + ) +) +``` + + + + +## Query Calls + +When using multi-tenant, the client-side query calls endpoint will only return calls that match the query and are on the same team as the authenticated user. The API injects filter `{team: {$in: []}}` for every request that doesn't already contain filter for team field. If you want to query channels from all teams, you have to provide empty filter like this: `{team:{}}`. + +For server-side requests, this filter does not apply and you can search as usual and also filter by teams. + + + + +```js +// All calls +client.video.queryCalls(); + +// Calls without team +client.video.queryCalls({ + filter_conditions: { + team: null, + }, +}); + +// Calls with specific team +client.video.queryCalls({ + filter_conditions: { + team: 'blue', + }, +}); +``` + + + + +```py +# query calls by team field +response = client.video.query_calls( + filter_conditions={"id": call_id, "team": {"$eq": "blue"}} +) + +# retrieve calls without a team +response = client.video.query_calls( + filter_conditions={"id": call_id, "team": {"$eq": "blue"}} +) +``` + + + From 94dbb305bd66e3da4dba1e1cabdd105e124dc6fe Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Fri, 26 Apr 2024 11:10:44 +0200 Subject: [PATCH 2/4] Update upsert user API for Python --- .../video/docusaurus/docs/api/_common_/rtmp.mdx | 4 +--- .../docs/api/basics/authentication.mdx | 17 +++++------------ .../docusaurus/docs/api/basics/get_started.mdx | 7 ++----- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/docusaurus/video/docusaurus/docs/api/_common_/rtmp.mdx b/docusaurus/video/docusaurus/docs/api/_common_/rtmp.mdx index b197b8b6..8fedfda6 100644 --- a/docusaurus/video/docusaurus/docs/api/_common_/rtmp.mdx +++ b/docusaurus/video/docusaurus/docs/api/_common_/rtmp.mdx @@ -31,9 +31,7 @@ resp = call.get() # user ID of an existing user user_id = 'jane' client.upsert_users( - users={ - user_id: {'id': user_id} - } + UserRequest(id=user_id) ) # the token will be valid for 1 hour diff --git a/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx b/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx index 88055054..72355784 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx @@ -40,12 +40,9 @@ await client.upsertUsers({ ```py -users = {} -user = UserRequest( -id='user_id', role="user", custom={"color": "red"}, name="This is a test user",image= "link/to/profile/image", +client.upsert_users(UserRequest( + id='user_id', role="user", custom={"color": "red"}, name="This is a test user",image= "link/to/profile/image",) ) -users[user.id] = user -client.upsert_users(users=users) ``` @@ -95,8 +92,7 @@ client.updateUsersPartial({ ```py -users = {} -user = UserRequest( +client.upsert_users(UserRequest( id= 'userid', role= 'user', custom= { @@ -104,16 +100,13 @@ user = UserRequest( }, name= 'This is a test user', image= 'link/to/profile/image', -) - -users[user.id] = user -client.upsert_users(users=users) +)) # or client.update_users_partial( users= [ { - id: user.id, + id: 'userid', set: { color: 'blue', }, diff --git a/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx b/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx index eaf1a01f..936b2f88 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx @@ -122,12 +122,9 @@ client.createToken(userId, exp); ```py -users = {} -user = UserRequest( -id="john", role="user", custom={"color": "red"}, name="John",image= "link/to/profile/image", +client.upsert_users(UserRequest( + id="john", role="user", custom={"color": "red"}, name="John",image= "link/to/profile/image",) ) -users[user.id] = user -client.upsert_users(users=users) # the token will be valid for 1 hour exp = int(time.time()) + 60 * 60 From a9f50c054bf372cf772da5616da762ea0ade577d Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Fri, 26 Apr 2024 11:38:15 +0200 Subject: [PATCH 3/4] Show how to enable mult-tenant from API --- .../docs/api/basics/multi-tenant.mdx | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx b/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx index 9ac05bd1..4d92e8fb 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx @@ -20,7 +20,28 @@ When enabling multi-tenant mode all user requests will always ensure that the re ## Enable Teams for your application -In order to use Teams, your application must have multi-tenant mode enabled. You can enable multi-tenant from the dashboard (Overview screen). +In order to use Teams, your application must have multi-tenant mode enabled. + +You can enable multi-tenant by API or from the dashboard (Overview screen). + + + + +```js +client.updateAppSettings({ + multi_tenant_enabled: true, +}); +``` + + + + +```py +client.update_app(multi_tenant_enabled=enabled) +``` + + + ## User teams From 3f5a08dcd589a107350e20cd2437358148efc061 Mon Sep 17 00:00:00 2001 From: Zita Szupera Date: Fri, 26 Apr 2024 11:46:26 +0200 Subject: [PATCH 4/4] Update docs --- .../docusaurus/docs/api/basics/multi-tenant.mdx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx b/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx index 4d92e8fb..d8a89310 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/multi-tenant.mdx @@ -20,14 +20,17 @@ When enabling multi-tenant mode all user requests will always ensure that the re ## Enable Teams for your application -In order to use Teams, your application must have multi-tenant mode enabled. - -You can enable multi-tenant by API or from the dashboard (Overview screen). +In order to use Teams, your application must have multi-tenant mode enabled. You can enable multi-tenant from the dashboard (Overview screen) or using the API. ```js +// shows the current status +const appSettings = await client.getAppSettings(); +console.log(appSettings.app.multi_tenant_enabled); + +// enables teams client.updateAppSettings({ multi_tenant_enabled: true, }); @@ -37,12 +40,18 @@ client.updateAppSettings({ ```py -client.update_app(multi_tenant_enabled=enabled) +# shows the current status +print(client.get_app().data.app.multi_tenant_enabled) + +# enables teams +client.update_app(multi_tenant_enabled=True) ``` +Please keep in mind that enabling/disabling multi-tenant changes permission checking for your users. Do not change this on a production app without testing that your integration supports it correctly. + ## User teams When multi-tenant is enabled, users can only be created from your back-end. This is necessary to ensure that a user cannot pick its own team/tenant.