diff --git a/lib/philomena/filters.ex b/lib/philomena/filters.ex new file mode 100644 index 00000000..5402b185 --- /dev/null +++ b/lib/philomena/filters.ex @@ -0,0 +1,119 @@ +defmodule Philomena.Filters do + @moduledoc """ + The Filters context. + """ + + import Ecto.Query, warn: false + alias Philomena.Repo + + alias Philomena.Filters.Filter + + @doc """ + Returns the list of filters. + + ## Examples + + iex> list_filters() + [%Filter{}, ...] + + """ + def list_filters do + Repo.all(Filter) + end + + @doc """ + Returns the default filter. + + ## Examples + + iex> default_filter() + %Filter{} + + """ + def default_filter do + Filter + |> where(system: true, name: "Default") + |> Repo.one!() + end + + @doc """ + Gets a single filter. + + Raises `Ecto.NoResultsError` if the Filter does not exist. + + ## Examples + + iex> get_filter!(123) + %Filter{} + + iex> get_filter!(456) + ** (Ecto.NoResultsError) + + """ + def get_filter!(id), do: Repo.get!(Filter, id) + + @doc """ + Creates a filter. + + ## Examples + + iex> create_filter(%{field: value}) + {:ok, %Filter{}} + + iex> create_filter(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_filter(attrs \\ %{}) do + %Filter{} + |> Filter.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a filter. + + ## Examples + + iex> update_filter(filter, %{field: new_value}) + {:ok, %Filter{}} + + iex> update_filter(filter, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_filter(%Filter{} = filter, attrs) do + filter + |> Filter.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a Filter. + + ## Examples + + iex> delete_filter(filter) + {:ok, %Filter{}} + + iex> delete_filter(filter) + {:error, %Ecto.Changeset{}} + + """ + def delete_filter(%Filter{} = filter) do + Repo.delete(filter) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking filter changes. + + ## Examples + + iex> change_filter(filter) + %Ecto.Changeset{source: %Filter{}} + + """ + def change_filter(%Filter{} = filter) do + Filter.changeset(filter, %{}) + end +end diff --git a/lib/philomena/filters/filter.ex b/lib/philomena/filters/filter.ex new file mode 100644 index 00000000..bfffbc50 --- /dev/null +++ b/lib/philomena/filters/filter.ex @@ -0,0 +1,27 @@ +defmodule Philomena.Filters.Filter do + use Ecto.Schema + import Ecto.Changeset + + schema "filters" do + belongs_to :user, Philomena.Users.User + + field :name, :string + field :description, :string + field :system, :boolean + field :public, :boolean + field :hidden_complex_str, :string + field :spoilered_complex_str, :string + field :hidden_tag_ids, {:array, :integer}, default: [] + field :spoilered_tag_ids, {:array, :integer}, default: [] + field :user_count, :integer, default: 0 + + timestamps(inserted_at: :created_at) + end + + @doc false + def changeset(filter, attrs) do + filter + |> cast(attrs, []) + |> validate_required([]) + end +end diff --git a/lib/philomena/users/user.ex b/lib/philomena/users/user.ex index ceb0b6cc..8024c424 100644 --- a/lib/philomena/users/user.ex +++ b/lib/philomena/users/user.ex @@ -9,6 +9,8 @@ defmodule Philomena.Users.User do import Ecto.Changeset schema "users" do + belongs_to :current_filter, Philomena.Filters.Filter + field :email, :string field :encrypted_password, :string field :password_hash, :string, source: :encrypted_password diff --git a/lib/philomena_web/controllers/image_controller.ex b/lib/philomena_web/controllers/image_controller.ex index acba3904..d9503d54 100644 --- a/lib/philomena_web/controllers/image_controller.ex +++ b/lib/philomena_web/controllers/image_controller.ex @@ -1,11 +1,29 @@ defmodule PhilomenaWeb.ImageController do use PhilomenaWeb, :controller - alias Philomena.Images - alias Philomena.Images.Image + alias Philomena.{Images, Images.Image} + import Ecto.Query def index(conn, _params) do - images = Images.list_images() + images = + Image.search_records( + %{ + query: %{ + bool: %{ + must_not: %{ + terms: %{ + tag_ids: conn.assigns[:current_filter].hidden_tag_ids + } + } + } + }, + sort: %{ + created_at: :desc + } + }, + Image |> preload(:tags) + ) + render(conn, "index.html", images: images) end @@ -30,33 +48,4 @@ defmodule PhilomenaWeb.ImageController do image = Images.get_image!(id) render(conn, "show.html", image: image) end - - def edit(conn, %{"id" => id}) do - image = Images.get_image!(id) - changeset = Images.change_image(image) - render(conn, "edit.html", image: image, changeset: changeset) - end - - def update(conn, %{"id" => id, "image" => image_params}) do - image = Images.get_image!(id) - - case Images.update_image(image, image_params) do - {:ok, image} -> - conn - |> put_flash(:info, "Image updated successfully.") - |> redirect(to: Routes.image_path(conn, :show, image)) - - {:error, %Ecto.Changeset{} = changeset} -> - render(conn, "edit.html", image: image, changeset: changeset) - end - end - - def delete(conn, %{"id" => id}) do - image = Images.get_image!(id) - {:ok, _image} = Images.delete_image(image) - - conn - |> put_flash(:info, "Image deleted successfully.") - |> redirect(to: Routes.image_path(conn, :index)) - end end diff --git a/lib/philomena_web/endpoint.ex b/lib/philomena_web/endpoint.ex index df1e30dc..7667b112 100644 --- a/lib/philomena_web/endpoint.ex +++ b/lib/philomena_web/endpoint.ex @@ -43,8 +43,8 @@ defmodule PhilomenaWeb.Endpoint do signing_salt: "signed cookie", encryption_salt: "authenticated encrypted cookie" - plug Philomena.Plugs.Session, otp_app: :philomena - + plug PhilomenaWeb.Plugs.Session, otp_app: :philomena plug PhilomenaWeb.Plugs.RenderTime + plug PhilomenaWeb.Plugs.CurrentFilter plug PhilomenaWeb.Router end diff --git a/lib/philomena_web/plugs/current_filter.ex b/lib/philomena_web/plugs/current_filter.ex new file mode 100644 index 00000000..645db57d --- /dev/null +++ b/lib/philomena_web/plugs/current_filter.ex @@ -0,0 +1,26 @@ +defmodule PhilomenaWeb.Plugs.CurrentFilter do + import Plug.Conn + import Ecto.Query + + alias Philomena.Filters + alias Pow.Plug + + # No options + def init([]), do: false + + # Assign current filter + def call(conn, _opts) do + user = conn |> Plug.current_user() + + filter = + if user do + user = user |> preload(:current_filter) + user.current_filter + else + Filters.default_filter() + end + + conn + |> assign(:current_filter, filter) + end +end diff --git a/lib/philomena_web/plugs/session.ex b/lib/philomena_web/plugs/session.ex index 1caa2b85..e3bac93b 100644 --- a/lib/philomena_web/plugs/session.ex +++ b/lib/philomena_web/plugs/session.ex @@ -1,4 +1,4 @@ -defmodule Philomena.Plugs.Session do +defmodule PhilomenaWeb.Plugs.Session do use Pow.Plug.Base alias Plug.Conn diff --git a/test/philomena/filters_test.exs b/test/philomena/filters_test.exs new file mode 100644 index 00000000..6bcd6bcf --- /dev/null +++ b/test/philomena/filters_test.exs @@ -0,0 +1,62 @@ +defmodule Philomena.FiltersTest do + use Philomena.DataCase + + alias Philomena.Filters + + describe "filters" do + alias Philomena.Filters.Filter + + @valid_attrs %{} + @update_attrs %{} + @invalid_attrs %{} + + def filter_fixture(attrs \\ %{}) do + {:ok, filter} = + attrs + |> Enum.into(@valid_attrs) + |> Filters.create_filter() + + filter + end + + test "list_filters/0 returns all filters" do + filter = filter_fixture() + assert Filters.list_filters() == [filter] + end + + test "get_filter!/1 returns the filter with given id" do + filter = filter_fixture() + assert Filters.get_filter!(filter.id) == filter + end + + test "create_filter/1 with valid data creates a filter" do + assert {:ok, %Filter{} = filter} = Filters.create_filter(@valid_attrs) + end + + test "create_filter/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Filters.create_filter(@invalid_attrs) + end + + test "update_filter/2 with valid data updates the filter" do + filter = filter_fixture() + assert {:ok, %Filter{} = filter} = Filters.update_filter(filter, @update_attrs) + end + + test "update_filter/2 with invalid data returns error changeset" do + filter = filter_fixture() + assert {:error, %Ecto.Changeset{}} = Filters.update_filter(filter, @invalid_attrs) + assert filter == Filters.get_filter!(filter.id) + end + + test "delete_filter/1 deletes the filter" do + filter = filter_fixture() + assert {:ok, %Filter{}} = Filters.delete_filter(filter) + assert_raise Ecto.NoResultsError, fn -> Filters.get_filter!(filter.id) end + end + + test "change_filter/1 returns a filter changeset" do + filter = filter_fixture() + assert %Ecto.Changeset{} = Filters.change_filter(filter) + end + end +end