add integrations context with CRUD operations
This commit is contained in:
parent
39f0ffe253
commit
e302b8e9c4
2 changed files with 199 additions and 0 deletions
62
lib/towerops/integrations.ex
Normal file
62
lib/towerops/integrations.ex
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
defmodule Towerops.Integrations do
|
||||
@moduledoc """
|
||||
Context for managing third-party integrations per organization.
|
||||
"""
|
||||
import Ecto.Query
|
||||
|
||||
alias Towerops.Integrations.Integration
|
||||
alias Towerops.Repo
|
||||
|
||||
def list_integrations(organization_id) do
|
||||
Integration
|
||||
|> where(organization_id: ^organization_id)
|
||||
|> order_by(:provider)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def get_integration(organization_id, provider) do
|
||||
case Repo.get_by(Integration, organization_id: organization_id, provider: provider) do
|
||||
nil -> {:error, :not_found}
|
||||
integration -> {:ok, integration}
|
||||
end
|
||||
end
|
||||
|
||||
def get_integration!(organization_id, provider) do
|
||||
Repo.get_by!(Integration, organization_id: organization_id, provider: provider)
|
||||
end
|
||||
|
||||
def create_integration(organization_id, attrs) do
|
||||
%Integration{}
|
||||
|> Integration.changeset(Map.put(attrs, :organization_id, organization_id))
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
def update_integration(%Integration{} = integration, attrs) do
|
||||
integration
|
||||
|> Integration.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
def update_sync_status(%Integration{} = integration, status) do
|
||||
integration
|
||||
|> Integration.changeset(%{
|
||||
last_sync_status: status,
|
||||
last_synced_at: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
})
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
def delete_integration(%Integration{} = integration) do
|
||||
Repo.delete(integration)
|
||||
end
|
||||
|
||||
def change_integration(%Integration{} = integration, attrs \\ %{}) do
|
||||
Integration.changeset(integration, attrs)
|
||||
end
|
||||
|
||||
def list_enabled_integrations(provider) do
|
||||
Integration
|
||||
|> where(provider: ^provider, enabled: true)
|
||||
|> Repo.all()
|
||||
end
|
||||
end
|
||||
137
test/towerops/integrations_test.exs
Normal file
137
test/towerops/integrations_test.exs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
defmodule Towerops.IntegrationsTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
import Towerops.AccountsFixtures
|
||||
import Towerops.OrganizationsFixtures
|
||||
|
||||
alias Towerops.Integrations
|
||||
alias Towerops.Integrations.Integration
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
organization = organization_fixture(user.id)
|
||||
%{organization: organization}
|
||||
end
|
||||
|
||||
describe "list_integrations/1" do
|
||||
test "returns all integrations for an organization", %{organization: org} do
|
||||
{:ok, _} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
integrations = Integrations.list_integrations(org.id)
|
||||
assert length(integrations) == 1
|
||||
end
|
||||
|
||||
test "does not return integrations from other orgs", %{organization: org} do
|
||||
user2 = user_fixture()
|
||||
org2 = organization_fixture(user2.id)
|
||||
{:ok, _} = Integrations.create_integration(org2.id, %{provider: "preseem"})
|
||||
assert Integrations.list_integrations(org.id) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_integration/2" do
|
||||
test "returns integration by org and provider", %{organization: org} do
|
||||
{:ok, created} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
assert {:ok, fetched} = Integrations.get_integration(org.id, "preseem")
|
||||
assert fetched.id == created.id
|
||||
end
|
||||
|
||||
test "returns error when not found", %{organization: org} do
|
||||
assert {:error, :not_found} = Integrations.get_integration(org.id, "preseem")
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_integration!/2" do
|
||||
test "returns integration by org and provider", %{organization: org} do
|
||||
{:ok, created} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
fetched = Integrations.get_integration!(org.id, "preseem")
|
||||
assert fetched.id == created.id
|
||||
end
|
||||
|
||||
test "raises when not found", %{organization: org} do
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Integrations.get_integration!(org.id, "preseem")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "create_integration/2" do
|
||||
test "creates with valid attrs", %{organization: org} do
|
||||
attrs = %{provider: "preseem", credentials: %{"api_key" => "test-123"}, enabled: true}
|
||||
assert {:ok, %Integration{} = integration} = Integrations.create_integration(org.id, attrs)
|
||||
assert integration.provider == "preseem"
|
||||
assert integration.credentials == %{"api_key" => "test-123"}
|
||||
assert integration.enabled == true
|
||||
assert integration.organization_id == org.id
|
||||
end
|
||||
|
||||
test "rejects duplicate provider per org", %{organization: org} do
|
||||
{:ok, _} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
assert {:error, changeset} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
assert "has already been taken" in errors_on(changeset).provider
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_integration/2" do
|
||||
test "updates credentials", %{organization: org} do
|
||||
{:ok, integration} =
|
||||
Integrations.create_integration(org.id, %{
|
||||
provider: "preseem",
|
||||
credentials: %{"api_key" => "old-key"}
|
||||
})
|
||||
|
||||
assert {:ok, updated} =
|
||||
Integrations.update_integration(integration, %{credentials: %{"api_key" => "new-key"}})
|
||||
|
||||
assert updated.credentials == %{"api_key" => "new-key"}
|
||||
end
|
||||
|
||||
test "updates enabled flag", %{organization: org} do
|
||||
{:ok, integration} =
|
||||
Integrations.create_integration(org.id, %{provider: "preseem", enabled: false})
|
||||
|
||||
assert {:ok, updated} = Integrations.update_integration(integration, %{enabled: true})
|
||||
assert updated.enabled == true
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_sync_status/2" do
|
||||
test "updates last_synced_at and last_sync_status", %{organization: org} do
|
||||
{:ok, integration} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
assert integration.last_sync_status == "never"
|
||||
assert integration.last_synced_at == nil
|
||||
|
||||
assert {:ok, updated} = Integrations.update_sync_status(integration, "success")
|
||||
assert updated.last_sync_status == "success"
|
||||
assert updated.last_synced_at
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_integration/1" do
|
||||
test "deletes the integration", %{organization: org} do
|
||||
{:ok, integration} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
assert {:ok, _} = Integrations.delete_integration(integration)
|
||||
assert {:error, :not_found} = Integrations.get_integration(org.id, "preseem")
|
||||
end
|
||||
end
|
||||
|
||||
describe "change_integration/2" do
|
||||
test "returns a changeset", %{organization: org} do
|
||||
{:ok, integration} = Integrations.create_integration(org.id, %{provider: "preseem"})
|
||||
assert %Ecto.Changeset{} = Integrations.change_integration(integration)
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_enabled_integrations/1" do
|
||||
test "returns only enabled integrations for a provider", %{organization: org} do
|
||||
{:ok, _} = Integrations.create_integration(org.id, %{provider: "preseem", enabled: true})
|
||||
|
||||
user2 = user_fixture()
|
||||
org2 = organization_fixture(user2.id)
|
||||
{:ok, _} = Integrations.create_integration(org2.id, %{provider: "preseem", enabled: false})
|
||||
|
||||
enabled = Integrations.list_enabled_integrations("preseem")
|
||||
assert length(enabled) == 1
|
||||
assert hd(enabled).organization_id == org.id
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue