Skip to content

Commit

Permalink
Allow to create a source
Browse files Browse the repository at this point in the history
  • Loading branch information
Loïc Knuchel committed Nov 11, 2023
1 parent 1d0effd commit 112e689
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 6 deletions.
44 changes: 39 additions & 5 deletions backend/lib/azimutt_web/controllers/api/source_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,36 @@ defmodule AzimuttWeb.Api.SourceController do
do: conn |> render("show.json", source: source, ctx: ctx)
end

def create(conn, %{"organization_id" => _organization_id, "project_id" => _project_id} = _params) do
# TODO
_create_schema = %{}
conn |> send_resp(:not_found, "WIP")
def create(conn, %{"organization_id" => _organization_id, "project_id" => project_id} = params) do
now = DateTime.utc_now()
ctx = CtxParams.from_params(params)
current_user = conn.assigns.current_user

create_schema = %{
"type" => "object",
"additionalProperties" => false,
"required" => ["name", "kind", "tables", "relations"],
"properties" => %{
"name" => %{"type" => "string"},
"kind" => ProjectSchema.source_kind(),
"tables" => %{"type" => "array", "items" => ProjectSchema.table()},
"relations" => %{"type" => "array", "items" => ProjectSchema.relation()},
"types" => %{"type" => "array", "items" => ProjectSchema.type()},
"enabled" => %{"type" => "boolean"}
},
"definitions" => %{"column" => ProjectSchema.column()}
}

with {:ok, body} <- validate_json_schema(create_schema, conn.body_params) |> Result.zip_error_left(:bad_request),
{:ok, %Project{} = project} <- Projects.get_project(project_id, current_user),
{:ok, content} <- Projects.get_project_content(project),
{:ok, json} <- Jason.decode(content),
:ok <- if(body["kind"]["kind"] == "AmlEditor", do: {:error, {:forbidden, "AML sources can't be created via API."}}, else: :ok),
source = create_source(body, now),
json_updated = json |> Map.put("sources", json["sources"] ++ [source]),
{:ok, content_updated} <- Jason.encode(json_updated),
{:ok, %Project{} = _project_updated} <- Projects.update_project_file(project, content_updated, current_user, now),
do: conn |> render("show.json", source: source, ctx: ctx)
end

def update(conn, %{"organization_id" => _organization_id, "project_id" => project_id, "source_id" => source_id} = params) do
Expand All @@ -59,7 +85,7 @@ defmodule AzimuttWeb.Api.SourceController do
{:ok, content} <- Projects.get_project_content(project),
{:ok, json} <- Jason.decode(content),
{:ok, source} <- json["sources"] |> Enum.find(fn s -> s["id"] == source_id end) |> Result.from_nillable(),
:ok <- if(source["kind"]["kind"] == "AmlEditor", do: {:error, {:forbidden, "AML sources can't be updated."}}, else: :ok),
:ok <- if(source["kind"]["kind"] == "AmlEditor", do: {:error, {:forbidden, "AML sources can't be updated via API."}}, else: :ok),
json_updated = json |> Map.put("sources", json["sources"] |> Enum.map(fn s -> if(s["id"] == source_id, do: update_source(s, body), else: s) end)),
{:ok, content_updated} <- Jason.encode(json_updated),
{:ok, %Project{} = _project_updated} <- Projects.update_project_file(project, content_updated, current_user, now),
Expand All @@ -81,6 +107,14 @@ defmodule AzimuttWeb.Api.SourceController do
do: conn |> render("show.json", source: source, ctx: ctx)
end

defp create_source(params, now) do
params
|> Map.put("id", Ecto.UUID.generate())
|> Map.put("content", [])
|> Map.put("createdAt", DateTime.to_unix(now, :millisecond))
|> Map.put("updatedAt", DateTime.to_unix(now, :millisecond))
end

defp update_source(source, params) do
source
|> Map.put("tables", params["tables"])
Expand Down
54 changes: 53 additions & 1 deletion backend/lib/azimutt_web/utils/project_schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule AzimuttWeb.Utils.ProjectSchema do
"schema" => %{"type" => "string"},
"name" => %{"type" => "string"},
"value" => %{
"anyOf" => [
"oneOf" => [
%{"type" => "object", "additionalProperties" => false, "required" => ["enum"], "properties" => %{"enum" => %{"type" => "array", "items" => %{"type" => "string"}}}},
%{"type" => "object", "additionalProperties" => false, "required" => ["definition"], "properties" => %{"definition" => %{"type" => "string"}}}
]
Expand Down Expand Up @@ -125,6 +125,58 @@ defmodule AzimuttWeb.Utils.ProjectSchema do
}
}

@source_kind %{
"oneOf" =>
[
%{
"type" => "object",
"additionalProperties" => false,
"required" => ["kind", "url"],
"properties" => %{
"kind" => %{"const" => "DatabaseConnection"},
"url" => %{"type" => "string"}
}
}
# FIXME: removed the AmlEditor source kind because it made others pass without needed properties :/
# %{
# "type" => "object",
# "additionalProperties" => false,
# "required" => ["kind"],
# "properties" => %{
# "kind" => %{"const" => "AmlEditor"}
# }
# }
] ++
(["SqlLocalFile", "PrismaLocalFile", "JsonLocalFile"]
|> Enum.map(fn kind ->
%{
"type" => "object",
"additionalProperties" => false,
"required" => ["kind", "name", "size", "modified"],
"properties" => %{
"kind" => %{"const" => kind},
"name" => %{"type" => "string"},
"size" => %{"type" => "number"},
"modified" => %{"type" => "integer"}
}
}
end)) ++
(["SqlRemoteFile", "PrismaRemoteFile", "JsonRemoteFile"]
|> Enum.map(fn kind ->
%{
"type" => "object",
"additionalProperties" => false,
"required" => ["kind", "url", "size"],
"properties" => %{
"kind" => %{"const" => kind},
"url" => %{"type" => "string"},
"size" => %{"type" => "number"}
}
}
end))
}

def source_kind, do: @source_kind
def table, do: @table
def column, do: @column
def relation, do: @relation
Expand Down

0 comments on commit 112e689

Please sign in to comment.