Verified Commit 00c21255 authored by Pierre de Lacroix's avatar Pierre de Lacroix
Browse files

add bridge context

parent 68d18ab4
......@@ -7,6 +7,9 @@
# General application configuration
use Mix.Config
config :matrix_app_service,
ecto_repos: [MatrixAppService.Repo]
# Configures the endpoint
config :matrix_app_service, MatrixAppServiceWeb.Endpoint,
url: [host: "localhost"],
......
use Mix.Config
# Configure your database
#
# The MIX_TEST_PARTITION environment variable can be used
# to provide built-in test partitioning in CI environment.
# Run `mix help test` for more information.
config :matrix_app_service, MatrixAppService.Repo,
username: "postgres",
password: "postgres",
database: "matrix_app_service_test#{System.get_env("MIX_TEST_PARTITION")}",
hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :matrix_app_service, MatrixAppServiceWeb.Endpoint,
......
......@@ -21,7 +21,8 @@ defmodule MatrixAppService.Application do
if start_endpoint?() do
[
# MatrixAppServiceWeb.Endpoint
{MatrixAppServiceWeb.Endpoint, endpoint_config()}
{MatrixAppServiceWeb.Endpoint, endpoint_config()},
MatrixAppService.Repo
| children
]
else
......
defmodule MatrixAppService.Bridge do
use MatrixAppService.BridgeConfig, repo: MatrixAppService.Repo
end
defmodule MatrixAppService.Bridge.Room do
use Ecto.Schema
import Ecto.Changeset
schema "rooms" do
field :data, :map
field :local_id, :string
field :remote_id, :string
timestamps()
end
@doc false
def changeset(room, attrs) do
room
|> cast(attrs, [:local_id, :remote_id, :data])
# |> validate_required([:local_id, :remote_id, :data])
|> unique_constraint(:local_id)
|> unique_constraint(:remote_id)
end
end
defmodule MatrixAppService.Bridge.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :data, :map
field :local_id, :string
field :remote_id, :string
timestamps()
end
@doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:local_id, :remote_id, :data])
# |> validate_required([:local_id, :remote_id, :data])
|> unique_constraint(:local_id)
|> unique_constraint(:remote_id)
end
end
defmodule MatrixAppService.BridgeConfig do
@moduledoc """
The Bridge config.
"""
defmacro __using__([repo: repo]) do
quote bind_quoted: [repo: repo] do
@repo repo
import Ecto.Query, warn: false
# alias MatrixAppService.Repo
alias MatrixAppService.Bridge.User
@doc """
Returns the list of users.
## Examples
iex> list_users()
[%User{}, ...]
"""
def list_users do
@repo.all(User)
end
@doc """
Gets a single user.
Raises `Ecto.NoResultsError` if the User does not exist.
## Examples
iex> get_user!(123)
%User{}
iex> get_user!(456)
** (Ecto.NoResultsError)
"""
def get_user!(id), do: @repo.get!(User, id)
def get_user_by_local_id(local_id), do: @repo.get_by(User, local_id: local_id) || %User{local_id: local_id}
def get_user_by_remote_id(remote_id), do: @repo.get_by(User, remote_id: remote_id) || %User{remote_id: remote_id}
@doc """
Creates a user.
## Examples
iex> create_user(%{field: value})
{:ok, %User{}}
iex> create_user(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_user(attrs \\ %{}) do
%User{}
|> User.changeset(attrs)
|> @repo.insert()
end
def upsert_user(attrs, selectors) do
with %User{} = user <- @repo.get_by(User, selectors) do
update_user(user, attrs)
else
_ ->
create_user(Enum.into(selectors, attrs, fn {k, v} -> {to_string(k), v} end))
end
end
@doc """
Updates a user.
## Examples
iex> update_user(user, %{field: new_value})
{:ok, %User{}}
iex> update_user(user, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_user(%User{} = user, attrs) do
user
|> User.changeset(attrs)
|> @repo.update()
end
@doc """
Deletes a user.
## Examples
iex> delete_user(user)
{:ok, %User{}}
iex> delete_user(user)
{:error, %Ecto.Changeset{}}
"""
def delete_user(%User{} = user) do
@repo.delete(user)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking user changes.
## Examples
iex> change_user(user)
%Ecto.Changeset{data: %User{}}
"""
def change_user(%User{} = user, attrs \\ %{}) do
User.changeset(user, attrs)
end
alias MatrixAppService.Bridge.Room
@doc """
Returns the list of rooms.
## Examples
iex> list_rooms()
[%Room{}, ...]
"""
def list_rooms do
@repo.all(Room)
end
@doc """
Gets a single room.
Raises `Ecto.NoResultsError` if the Room does not exist.
## Examples
iex> get_room!(123)
%Room{}
iex> get_room!(456)
** (Ecto.NoResultsError)
"""
def get_room!(id), do: @repo.get!(Room, id)
def get_room_by_local_id(local_id), do: @repo.get_by(Room, local_id: local_id) || %Room{local_id: local_id}
def get_room_by_remote_id(remote_id), do: @repo.get_by(Room, remote_id: remote_id) || %Room{remote_id: remote_id}
@doc """
Creates a room.
## Examples
iex> create_room(%{field: value})
{:ok, %Room{}}
iex> create_room(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_room(attrs \\ %{}) do
%Room{}
|> Room.changeset(attrs)
|> @repo.insert()
end
@doc """
Updates a room.
## Examples
iex> update_room(room, %{field: new_value})
{:ok, %Room{}}
iex> update_room(room, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_room(%Room{} = room, attrs) do
room
|> Room.changeset(attrs)
|> @repo.update()
end
@doc """
Deletes a room.
## Examples
iex> delete_room(room)
{:ok, %Room{}}
iex> delete_room(room)
{:error, %Ecto.Changeset{}}
"""
def delete_room(%Room{} = room) do
@repo.delete(room)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking room changes.
## Examples
iex> change_room(room)
%Ecto.Changeset{data: %Room{}}
"""
def change_room(%Room{} = room, attrs \\ %{}) do
Room.changeset(room, attrs)
end
end
end
end
defmodule MatrixAppService.Migrations do
use Ecto.Migration
def change do
create table(:users) do
add :local_id, :string
add :remote_id, :string
add :data, :map
timestamps()
end
create unique_index(:users, [:local_id])
create unique_index(:users, [:remote_id])
create table(:rooms) do
add :local_id, :string
add :remote_id, :string
add :data, :map
timestamps()
end
create unique_index(:rooms, [:local_id])
create unique_index(:rooms, [:remote_id])
end
end
defmodule MatrixAppService.Repo do
use Ecto.Repo,
otp_app: :matrix_app_service,
adapter: Ecto.Adapters.Postgres
end
......@@ -59,11 +59,13 @@ defmodule MatrixAppService.MixProject do
{:telemetry_poller, "~> 0.4"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:phoenix_ecto, "~> 4.1"},
{:ecto_sql, "~> 3.4"},
{:polyjuice_client, "~> 0.3.1"},
{:ex_doc, "~> 0.22", only: :dev, runtime: false},
{:junit_formatter, "~> 3.1", only: :test},
{:cobertura_cover, "~> 0.9.0", only: :test}
{:cobertura_cover, "~> 0.9.0", only: :test},
{:postgrex, ">= 0.0.0", only: :test}
]
end
......
......@@ -24,6 +24,7 @@
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
"phoenix": {:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
"plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
"plug_cowboy": {:hex, :plug_cowboy, "2.4.1", "779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
......@@ -32,6 +33,7 @@
"polyjuice_client": {:hex, :polyjuice_client, "0.3.1", "cc312602a8da0d4d61b0a890bb72d9c6662f17cd0fc5782d8f7358274e3e6e4b", [:mix], [{:hackney, "~> 1.12", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:mutex, "~> 1.1.3", [hex: :mutex, repo: "hexpm", optional: false]}, {:polyjuice_util, "~> 0.1.0", [hex: :polyjuice_util, repo: "hexpm", optional: false]}], "hexpm", "e9585faab7562cac3e91a64d328905cefabc74219fafa9e77e09f4e5e4e82957"},
"polyjuice_util": {:hex, :polyjuice_util, "0.1.0", "69901959c143245b47829c8302d0605dff6c0e1c3b116730c162982e0f512ee0", [:mix], [], "hexpm", "af5d1f614f52ce1da59a1f5a7c49249a2dbfda279d99d52d1b4e83e84c19a8d5"},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
"postgrex": {:hex, :postgrex, "0.15.7", "724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
......
defmodule MatrixAppService.Repo.Migrations.MigrateItself do
use Ecto.Migration
def change do
MatrixAppService.Migrations.change()
end
end
defmodule MatrixAppService.BridgeTest do
use MatrixAppService.DataCase
alias MatrixAppService.Bridge
describe "users" do
alias MatrixAppService.Bridge.User
@valid_attrs %{data: %{}, local_id: "some local_id", remote_id: "some remote_id"}
@update_attrs %{data: %{}, local_id: "some updated local_id", remote_id: "some updated remote_id"}
# @invalid_attrs %{data: nil, local_id: nil, remote_id: nil}
def user_fixture(attrs \\ %{}) do
{:ok, user} =
attrs
|> Enum.into(@valid_attrs)
|> Bridge.create_user()
user
end
test "list_users/0 returns all users" do
user = user_fixture()
assert Bridge.list_users() == [user]
end
test "get_user!/1 returns the user with given id" do
user = user_fixture()
assert Bridge.get_user!(user.id) == user
end
test "create_user/1 with valid data creates a user" do
assert {:ok, %User{} = user} = Bridge.create_user(@valid_attrs)
assert user.data == %{}
assert user.local_id == "some local_id"
assert user.remote_id == "some remote_id"
end
# test "create_user/1 with invalid data returns error changeset" do
# assert {:error, %Ecto.Changeset{}} = Bridge.create_user(@invalid_attrs)
# end
test "update_user/2 with valid data updates the user" do
user = user_fixture()
assert {:ok, %User{} = user} = Bridge.update_user(user, @update_attrs)
assert user.data == %{}
assert user.local_id == "some updated local_id"
assert user.remote_id == "some updated remote_id"
end
# test "update_user/2 with invalid data returns error changeset" do
# user = user_fixture()
# assert {:error, %Ecto.Changeset{}} = Bridge.update_user(user, @invalid_attrs)
# assert user == Bridge.get_user!(user.id)
# end
test "delete_user/1 deletes the user" do
user = user_fixture()
assert {:ok, %User{}} = Bridge.delete_user(user)
assert_raise Ecto.NoResultsError, fn -> Bridge.get_user!(user.id) end
end
test "change_user/1 returns a user changeset" do
user = user_fixture()
assert %Ecto.Changeset{} = Bridge.change_user(user)
end
end
describe "rooms" do
alias MatrixAppService.Bridge.Room
@valid_attrs %{data: %{}, local_id: "some local_id", remote_id: "some remote_id"}
@update_attrs %{data: %{}, local_id: "some updated local_id", remote_id: "some updated remote_id"}
# @invalid_attrs %{data: nil, local_id: nil, remote_id: nil}
def room_fixture(attrs \\ %{}) do
{:ok, room} =
attrs
|> Enum.into(@valid_attrs)
|> Bridge.create_room()
room
end
test "list_rooms/0 returns all rooms" do
room = room_fixture()
assert Bridge.list_rooms() == [room]
end
test "get_room!/1 returns the room with given id" do
room = room_fixture()
assert Bridge.get_room!(room.id) == room
end
test "create_room/1 with valid data creates a room" do
assert {:ok, %Room{} = room} = Bridge.create_room(@valid_attrs)
assert room.data == %{}
assert room.local_id == "some local_id"
assert room.remote_id == "some remote_id"
end
# test "create_room/1 with invalid data returns error changeset" do
# assert {:error, %Ecto.Changeset{}} = Bridge.create_room(@invalid_attrs)
# end
test "update_room/2 with valid data updates the room" do
room = room_fixture()
assert {:ok, %Room{} = room} = Bridge.update_room(room, @update_attrs)
assert room.data == %{}
assert room.local_id == "some updated local_id"
assert room.remote_id == "some updated remote_id"
end
# test "update_room/2 with invalid data returns error changeset" do
# room = room_fixture()
# assert {:error, %Ecto.Changeset{}} = Bridge.update_room(room, @invalid_attrs)
# assert room == Bridge.get_room!(room.id)
# end
test "delete_room/1 deletes the room" do
room = room_fixture()
assert {:ok, %Room{}} = Bridge.delete_room(room)
assert_raise Ecto.NoResultsError, fn -> Bridge.get_room!(room.id) end
end
test "change_room/1 returns a room changeset" do
room = room_fixture()
assert %Ecto.Changeset{} = Bridge.change_room(room)
end
end
end
defmodule MatrixAppService.DataCase do
@moduledoc """
This module defines the setup for tests requiring
access to the application's data layer.
You may define functions here to be used as helpers in
your tests.
Finally, if the test case interacts with the database,
it cannot be async. For this reason, every test runs
inside a transaction which is reset at the beginning
of the test unless the test case is marked as async.
"""
use ExUnit.CaseTemplate
alias Ecto.Adapters.SQL.Sandbox
alias Ecto.Changeset
alias MatrixAppService.Repo
using do
quote do
alias MatrixAppService.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query
import MatrixAppService.DataCase
end
end
setup tags do
:ok = Sandbox.checkout(Repo)
unless tags[:async] do
Sandbox.mode(Repo, {:shared, self()})
end
:ok
end
@doc """
A helper that transform changeset errors to a map of messages.
assert {:error, changeset} = Accounts.create_user(%{password: "short"})
assert "password is too short" in errors_on(changeset).password
assert %{password: ["password is too short"]} = errors_on(changeset)
"""
def errors_on(changeset) do
Changeset.traverse_errors(changeset, fn {message, opts} ->
Enum.reduce(opts, message, fn {key, value}, acc ->
String.replace(acc, "%{#{key}}", to_string(value))
end)
end)
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment