From 0e8915fe636dfbcf664543fb66e9d576fee9141e Mon Sep 17 00:00:00 2001 From: michaeljguarino Date: Fri, 30 Aug 2024 11:31:37 -0400 Subject: [PATCH] Fix cloud instance validations * off by one on the regex * create instance first so its uniq constraints fire first --- apps/core/lib/core/schema/console_instance.ex | 12 +++++++++++- apps/core/lib/core/services/cloud.ex | 19 ++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/core/lib/core/schema/console_instance.ex b/apps/core/lib/core/schema/console_instance.ex index 55e230333..7df847d6c 100644 --- a/apps/core/lib/core/schema/console_instance.ex +++ b/apps/core/lib/core/schema/console_instance.ex @@ -100,9 +100,19 @@ defmodule Core.Schema.ConsoleInstance do |> cast_embed(:configuration, with: &configuration_changeset/2) |> cast_embed(:instance_status, with: &status_changeset/2) |> validate_required(@valid -- [:external_id]) + |> foreign_key_constraint(:cluster_id) + |> foreign_key_constraint(:postgres_id) + |> foreign_key_constraint(:owner_id) |> unique_constraint(:subdomain) |> unique_constraint(:name) - |> validate_format(:name, ~r/[a-z][a-z0-9]{5,10}/, message: "must be an alphanumeric string between 5 and 10 characters") + |> validate_format(:name, ~r/[a-z][a-z0-9]{5,10}/, message: "must be an alphanumeric string between 5 and 11 characters") + |> validate_region() + end + + def create_changeset(model, attrs \\ %{}) do + model + |> cast(attrs, @valid) + |> validate_required(~w(name region status cloud size)a) |> validate_region() end diff --git a/apps/core/lib/core/services/cloud.ex b/apps/core/lib/core/services/cloud.ex index 3e8c7f2ca..08f386ec5 100644 --- a/apps/core/lib/core/services/cloud.ex +++ b/apps/core/lib/core/services/cloud.ex @@ -13,6 +13,8 @@ defmodule Core.Services.Cloud do def get_instance!(id), do: Repo.get!(ConsoleInstance, id) + def get_instance_by_name(name), do: Repo.get_by(ConsoleInstance, name: name) + @spec upsert_cluster(map, binary) :: cluster_resp def upsert_cluster(attrs, name) do case Repo.get_by(CloudCluster, name: name) do @@ -39,7 +41,12 @@ defmodule Core.Services.Cloud do @spec create_instance(map, User.t) :: console_resp def create_instance(%{name: name} = attrs, %User{} = user) do start_transaction() - |> add_operation(:auth, fn _ -> allow(%ConsoleInstance{}, user, :create) end) + |> add_operation(:inst, fn _ -> + %ConsoleInstance{status: :pending} + |> ConsoleInstance.create_changeset(attrs) + |> allow(user, :create) + |> when_ok(:insert) + end) |> add_operation(:cluster, fn _ -> select_cluster(attrs[:cloud], attrs[:region]) end) |> add_operation(:postgres, fn _ -> select_roach(attrs[:cloud]) end) |> add_operation(:sa, fn _ -> @@ -67,10 +74,12 @@ defmodule Core.Services.Cloud do redirect_uris: Shell.merge_uris(["https://console.#{name}.#{domain()}/oauth/callback"], inst.oidc_provider) }, inst.id, sa) end) - |> add_operation(:instance, fn %{oidc: oidc, token: token, cluster: cluster, postgres: roach, sa: sa} -> - %ConsoleInstance{status: :pending, cluster_id: cluster.id, postgres_id: roach.id, owner_id: sa.id} - |> ConsoleInstance.changeset(add_configuration(attrs, name, token.token, oidc, user)) - |> Repo.insert() + |> add_operation(:instance, fn %{inst: inst, oidc: oidc, token: token, cluster: cluster, postgres: roach, sa: sa} -> + ConsoleInstance.changeset(inst, Map.merge( + %{cluster_id: cluster.id, postgres_id: roach.id, owner_id: sa.id}, + add_configuration(attrs, name, token.token, oidc, user) + )) + |> Repo.update() end) |> execute(extract: :instance) |> notify(:create, user)