diff --git a/lib/livebook/hubs/team.ex b/lib/livebook/hubs/team.ex
index 83e5be63e..60df74655 100644
--- a/lib/livebook/hubs/team.ex
+++ b/lib/livebook/hubs/team.ex
@@ -41,6 +41,7 @@ defmodule Livebook.Hubs.Team do
field :session_token, :string, redact: true
field :hub_name, :string
field :hub_emoji, :string
+ field :disabled, :boolean, default: false
embeds_one :offline, Offline
end
diff --git a/lib/livebook/hubs/team_client.ex b/lib/livebook/hubs/team_client.ex
index 14a3e34a7..c7cc44eb2 100644
--- a/lib/livebook/hubs/team_client.ex
+++ b/lib/livebook/hubs/team_client.ex
@@ -641,6 +641,7 @@ defmodule Livebook.Hubs.TeamClient do
defp handle_event(:user_connected, user_connected, state) do
state
+ |> update_hub(user_connected)
|> dispatch_secrets(user_connected)
|> dispatch_file_systems(user_connected)
|> dispatch_deployment_groups(user_connected)
@@ -728,6 +729,10 @@ defmodule Livebook.Hubs.TeamClient do
state
end
+ defp handle_event(:org_updated, org_updated, state) do
+ update_hub(state, org_updated)
+ end
+
defp dispatch_secrets(state, %{secrets: secrets}) do
decrypted_secrets = Enum.map(secrets, &build_secret(state, &1))
@@ -796,14 +801,26 @@ defmodule Livebook.Hubs.TeamClient do
state
end
- defp update_hub(state, %{public_key: org_public_key}) do
- hub = %{state.hub | org_public_key: org_public_key}
+ defp update_hub(state, %LivebookProto.UserConnected{org_disabled: disabled}) do
+ update_hub(state, &put_in(&1.disabled, disabled))
+ end
- if Livebook.Hubs.hub_exists?(hub.id) do
+ defp update_hub(state, %LivebookProto.OrgUpdated{disabled: disabled}) do
+ update_hub(state, &put_in(&1.disabled, disabled))
+ end
+
+ defp update_hub(state, %LivebookProto.AgentConnected{public_key: org_public_key}) do
+ update_hub(state, &put_in(&1.org_public_key, org_public_key))
+ end
+
+ defp update_hub(state, fun) when is_function(fun, 1) do
+ hub = fun.(state.hub)
+
+ if Hubs.hub_exists?(hub.id) do
Hubs.save_hub(hub)
end
- %{state | hub: hub}
+ put_in(state.hub, hub)
end
defp diff(old_list, new_list, fun, deleted_fun \\ nil, updated_fun \\ nil) do
diff --git a/lib/livebook_web/live/hub/edit/personal_component.ex b/lib/livebook_web/live/hub/edit/personal_component.ex
index dde1164e9..5c1fabcee 100644
--- a/lib/livebook_web/live/hub/edit/personal_component.ex
+++ b/lib/livebook_web/live/hub/edit/personal_component.ex
@@ -123,6 +123,7 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
id="hub-file-systems-list"
hub_id={@hub.id}
file_systems={@file_systems}
+ disabled={false}
/>
@@ -195,6 +196,7 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
hub={@hub}
secret_name={@secret_name}
secret_value={@secret_value}
+ disabled={false}
return_to={~p"/hub/#{@hub.id}"}
/>
@@ -210,6 +212,7 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
module={LivebookWeb.Hub.FileSystemFormComponent}
id="file-systems"
hub={@hub}
+ disabled={false}
file_system={@file_system}
file_system_id={@file_system_id}
return_to={~p"/hub/#{@hub.id}"}
diff --git a/lib/livebook_web/live/hub/edit/team_component.ex b/lib/livebook_web/live/hub/edit/team_component.ex
index 2e4fc3863..fac6260dc 100644
--- a/lib/livebook_web/live/hub/edit/team_component.ex
+++ b/lib/livebook_web/live/hub/edit/team_component.ex
@@ -63,6 +63,15 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
{Provider.connection_status(@hub)}
+
+
+ Workspace disabled: your organization doesn't have an active subscription. Please contact your <.link
+ href={org_url(@hub, "/users")}
+ class="underline"
+ >org's admin.
+
+
+
@@ -176,10 +185,15 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
secrets={@secrets}
edit_path={"hub/#{@hub.id}/secrets/edit"}
return_to={~p"/hub/#{@hub.id}"}
+ disabled={@hub.disabled}
/>
- <.button patch={~p"/hub/#{@hub.id}/secrets/new"} id="add-secret">
+ <.button
+ patch={~p"/hub/#{@hub.id}/secrets/new"}
+ id="add-secret"
+ disabled={@hub.disabled}
+ >
Add secret
@@ -200,6 +214,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
hub_id={@hub.id}
file_systems={@file_systems}
target={@myself}
+ disabled={@hub.disabled}
/>
@@ -233,7 +248,11 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
- <.button patch={~p"/hub/#{@hub.id}/groups/new"} id="add-deployment-group">
+ <.button
+ patch={~p"/hub/#{@hub.id}/groups/new"}
+ id="add-deployment-group"
+ disabled={@hub.disabled}
+ >
Add deployment group
@@ -289,6 +308,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
secret_name={@secret_name}
secret_value={@secret_value}
return_to={~p"/hub/#{@hub.id}"}
+ disabled={@hub.disabled}
/>
@@ -303,6 +323,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
module={LivebookWeb.Hub.FileSystemFormComponent}
id="file-systems"
hub={@hub}
+ disabled={@hub.disabled}
file_system={@file_system}
file_system_id={@file_system_id}
return_to={~p"/hub/#{@hub.id}"}
diff --git a/lib/livebook_web/live/hub/edit_live.ex b/lib/livebook_web/live/hub/edit_live.ex
index fc99e48ce..6768f2161 100644
--- a/lib/livebook_web/live/hub/edit_live.ex
+++ b/lib/livebook_web/live/hub/edit_live.ex
@@ -11,6 +11,7 @@ defmodule LivebookWeb.Hub.EditLive do
def mount(_params, _session, socket) do
if connected?(socket) do
Hubs.Broadcasts.subscribe([:connection])
+
Livebook.Teams.Broadcasts.subscribe([:deployment_groups, :app_deployments, :agents])
end
@@ -111,6 +112,10 @@ defmodule LivebookWeb.Hub.EditLive do
{:noreply, load_hub(socket, id)}
end
+ def handle_info({:hub_changed, id}, %{assigns: %{hub: %{id: id}}} = socket) do
+ {:noreply, load_hub(socket, id)}
+ end
+
def handle_info(_message, socket) do
{:noreply, socket}
end
diff --git a/lib/livebook_web/live/hub/file_system_form_component.ex b/lib/livebook_web/live/hub/file_system_form_component.ex
index 47693f5e1..f5c6105e4 100644
--- a/lib/livebook_web/live/hub/file_system_form_component.ex
+++ b/lib/livebook_web/live/hub/file_system_form_component.ex
@@ -88,7 +88,7 @@ defmodule LivebookWeb.Hub.FileSystemFormComponent do
<% end %>
- <.button type="submit" disabled={not @changeset.valid?}>
+ <.button type="submit" disabled={@disabled or not @changeset.valid?}>
<.remix_icon icon={@button.icon} />
{@button.label}
diff --git a/lib/livebook_web/live/hub/file_system_list_component.ex b/lib/livebook_web/live/hub/file_system_list_component.ex
index e732e81be..5f278878f 100644
--- a/lib/livebook_web/live/hub/file_system_list_component.ex
+++ b/lib/livebook_web/live/hub/file_system_list_component.ex
@@ -60,7 +60,11 @@ defmodule LivebookWeb.Hub.FileSystemListComponent do
- <.button patch={~p"/hub/#{@hub_id}/file-systems/new"} id="add-file-system">
+ <.button
+ patch={~p"/hub/#{@hub_id}/file-systems/new"}
+ id="add-file-system"
+ disabled={@disabled}
+ >
Add file storage
diff --git a/lib/livebook_web/live/hub/secret_form_component.ex b/lib/livebook_web/live/hub/secret_form_component.ex
index dd99f34f6..ff1280017 100644
--- a/lib/livebook_web/live/hub/secret_form_component.ex
+++ b/lib/livebook_web/live/hub/secret_form_component.ex
@@ -75,7 +75,7 @@ defmodule LivebookWeb.Hub.SecretFormComponent do
<.hidden_field field={f[:hub_id]} value={@hub.id} />
<.hidden_field field={f[:deployment_group_id]} value={@deployment_group_id} />
- <.button type="submit" disabled={not @changeset.valid?}>
+ <.button type="submit" disabled={@disabled or not @changeset.valid?}>
<.remix_icon icon={@button.icon} />
{@button.label}
diff --git a/proto/lib/livebook_proto/agent_connected.pb.ex b/proto/lib/livebook_proto/agent_connected.pb.ex
index 75234eb03..60b249bfd 100644
--- a/proto/lib/livebook_proto/agent_connected.pb.ex
+++ b/proto/lib/livebook_proto/agent_connected.pb.ex
@@ -18,4 +18,5 @@ defmodule LivebookProto.AgentConnected do
json_name: "appDeployments"
field :agents, 9, repeated: true, type: LivebookProto.Agent
+ field :org_disabled, 10, type: :bool, json_name: "orgDisabled"
end
diff --git a/proto/lib/livebook_proto/event.pb.ex b/proto/lib/livebook_proto/event.pb.ex
index fe26e32e9..5eb37e100 100644
--- a/proto/lib/livebook_proto/event.pb.ex
+++ b/proto/lib/livebook_proto/event.pb.ex
@@ -71,4 +71,6 @@ defmodule LivebookProto.Event do
type: LivebookProto.AppDeploymentStopped,
json_name: "appDeploymentStopped",
oneof: 0
+
+ field :org_updated, 17, type: LivebookProto.OrgUpdated, json_name: "orgUpdated", oneof: 0
end
diff --git a/proto/lib/livebook_proto/org_updated.pb.ex b/proto/lib/livebook_proto/org_updated.pb.ex
new file mode 100644
index 000000000..ecf173425
--- /dev/null
+++ b/proto/lib/livebook_proto/org_updated.pb.ex
@@ -0,0 +1,6 @@
+defmodule LivebookProto.OrgUpdated do
+ use Protobuf, protoc_gen_elixir_version: "0.13.0", syntax: :proto3
+
+ field :id, 1, type: :string
+ field :disabled, 2, type: :bool
+end
diff --git a/proto/lib/livebook_proto/user_connected.pb.ex b/proto/lib/livebook_proto/user_connected.pb.ex
index a91b75669..81b8eec26 100644
--- a/proto/lib/livebook_proto/user_connected.pb.ex
+++ b/proto/lib/livebook_proto/user_connected.pb.ex
@@ -16,4 +16,5 @@ defmodule LivebookProto.UserConnected do
json_name: "appDeployments"
field :agents, 6, repeated: true, type: LivebookProto.Agent
+ field :org_disabled, 7, type: :bool, json_name: "orgDisabled"
end
diff --git a/proto/messages.proto b/proto/messages.proto
index 239c56fcc..67e53e5cd 100644
--- a/proto/messages.proto
+++ b/proto/messages.proto
@@ -110,6 +110,7 @@ message UserConnected {
repeated DeploymentGroup deployment_groups = 4;
repeated AppDeployment app_deployments = 5;
repeated Agent agents = 6;
+ bool org_disabled = 7;
}
message AgentConnected {
@@ -121,6 +122,7 @@ message AgentConnected {
repeated DeploymentGroup deployment_groups = 7;
repeated AppDeployment app_deployments = 8;
repeated Agent agents = 9;
+ bool org_disabled = 10;
}
message AppDeployment {
@@ -157,6 +159,11 @@ message AgentLeft {
string id = 1;
}
+message OrgUpdated {
+ string id = 1;
+ bool disabled = 2;
+}
+
message Agent {
string id = 1;
string name = 2;
@@ -210,5 +217,6 @@ message Event {
AgentJoined agent_joined = 14;
AgentLeft agent_left = 15;
AppDeploymentStopped app_deployment_stopped = 16;
+ OrgUpdated org_updated = 17;
}
}